Couchbase 4.5에서는 데이터가 버킷별로 보안이 유지되었습니다. 각 버킷에는 비밀번호가 있었고, N1QL 쿼리를 통해 버킷에 액세스하려면 사용자가 쿼리에 버킷 비밀번호를 포함시켜야 했습니다. 비밀번호가 없는 버킷도 가능했지만, 프로덕션 환경에서는 권장되지 않았습니다.

이 방식은 기본적인 보호 기능을 제공했지만, 사용자가 버킷으로 모든 것을 할 수도 있고 아무것도 하지 않을 수도 있는 매우 세분화된 방식이었습니다. 또한, 여러 버킷에 액세스하는 쿼리는 모든 버킷에 대해 비밀번호를 입력해야 했기 때문에 특히 비밀번호가 변경되는 경우 불편했습니다.

사용자가 이러한 문제를 피할 수 있도록 Couchbase Server 5.0에 역할 기반 액세스 제어(RBAC)를 도입했습니다. 이제 데이터에 대한 액세스는 버킷의 세분화된 역할을 통해 제어되며, 모든 사용자에게 데이터베이스에서 실제로 수행해야 하는 작업에 맞는 역할이 할당될 수 있습니다.

이 문서에서는 Couchbase Server 5.0에서 RBAC이 제공하는 주요 기능을 안내합니다. 실습을 통해 새로운 기능을 직접 사용해 볼 수 있습니다.

설정

실습을 위해서는 Couchbase Server 5.0, Enterprise Edition을 설치해야 합니다. 설치하는 동안 관리자 이름이 "관리자"이고 비밀번호가 "password"이도록 구성합니다. 물론 프로덕션 환경에서는 권장되지 않습니다.

관리 콘솔(http://localhost:8091)에 로그인하여 버킷 화면으로 이동합니다. 메모리 부족을 방지하기 위해 각각 100MB의 메모리 할당량을 가진 두 개의 버킷, 즉 "testbucket1"과 "testbucket2"를 만듭니다.

그런 다음 쿼리 화면으로 이동하여 방금 만든 두 개의 버킷에 기본 인덱스를 만듭니다. 기본 인덱스를 사용하면 버킷에서 쿼리를 실행할 수 있습니다.

인덱스 화면으로 이동하여 인덱스가 실제로 생성되었는지 확인할 수 있습니다. 두 인덱스의 이름은 모두 "#primary"입니다.

주요 역할

누가 어떤 N1QL 쿼리를 실행할 수 있는지를 제어하는 네 가지 주요 역할이 있습니다. 쿼리 선택, 쿼리 삽입, 쿼리 업데이트 및 쿼리 삭제 역할은 각각 해당 유형의 N1QL 쿼리를 실행할 수 있게 해줍니다. 또한 다음 섹션인 중요한 추가 역할에서 다룰 세 가지 특수 역할(query_manage_index, query_system_catalog 및 query_external_access)이 더 있습니다.

하지만 그 외에도 다양한 역할이 있습니다. 이러한 역할은 적용되는 버킷에 따라 매개변수화됩니다. 사용자가 query_select 역할만 가질 수 있는 것이 아니라, 사용자가 testbucket1에 대해 SELECT 쿼리를 실행할 수 있는 query_select[testbucket1]과 같이 역할이 어떤 버킷에 속해 있는지 알아야 합니다. query_select[*]로 표시된 모든 버킷에서 이 역할을 가질 수도 있습니다.

직접 해보려면 Couchbase 콘솔로 이동하여 보안 화면에서 비밀번호 "password"와 역할 query_select[testbucket1]을 사용하여 사용자 user1을 새로 만드세요.

역할은 사용자 만들기 메뉴의 '쿼리 역할' 아래에서 찾을 수 있습니다.

그런 다음 "user2"에 대해서도 동일한 작업을 수행하되, 해당 사용자에게 query_select[testbucket2]를 부여합니다.

이제 역할을 사용하여 이러한 버킷에 대해 쿼리를 실행해 보겠습니다. Couchbase와 함께 제공되는 CBQ 셸 도구를 사용하겠습니다.

그 결과 다음과 같은 응답을 받았습니다:

이 오류는 어떤 역할이 부족한지 매우 명확하게 알려줍니다. 올바른 역할을 가진 사용자 1로 다시 시도해 보겠습니다:

효과가 있었습니다:

올바른 역할을 가지고 있지만 잘못된 버킷에 있는 user2로 직접 쿼리를 시도해 보세요. 요청은 실패할 것입니다.

이제 두 개의 버킷을 대상으로 하는 좀 더 복잡한 쿼리를 시도해 보겠습니다. 먼저 이 쿼리를 실행합니다:

시스템에서 쿼리_인서트[testbucket2] 역할이 필요하다고 알려줍니다:

필요한 역할을 가진 새 사용자 'user3'을 만든 다음 다시 시도합니다:

여전히 오류가 발생하지만 이전과는 다른 오류입니다. 실행하려는 쿼리는 테스트버킷1에서 선택하고 테스트버킷2에 삽입하는 두 부분으로 구성되어 있습니다. 삽입을 위한 자격 증명은 충분히 제공했지만 선택을 위한 자격 증명은 제공하지 않았습니다. 콘솔로 이동하여 사용자3에 query_select[testbucket2]를 추가하고 다시 시도합니다. 이번에는 쿼리가 작동합니다.

한 가지 더 시도해 보겠습니다. 쿼리에 RETURNING 절을 추가하고 실행을 시도해 보겠습니다:

실패합니다:

여기서 무슨 일이 일어나고 있는지는 삽입한 버킷(testbucket2)에서 RETURNING 절이 삽입 직후에 발생하는 SELECT로 취급되고 있다는 것입니다. 사용자에게 query_select[testbucket2] 역할이 없으므로 거부되고 있습니다.

사용자3에 query_select[testbucket2] 역할을 추가하고 쿼리를 다시 실행합니다. 이제 작동합니다.

중요한 추가 역할

N1QL로 작업할 때 알아야 할 세 가지 역할이 더 있습니다.

쿼리_관리_색인
먼저 인덱스를 만들어 보겠습니다:

그러면 오류가 발생합니다:

버킷에서 인덱스 관리 쿼리 역할은 해당 버킷에서 인덱스를 생성, 삭제 또는 구축하는 데 필요합니다.

쿼리_관리_인덱스[testbucket1] 역할을 가진 새 사용자 'user4'를 만듭니다. 테스트 버킷의 인덱스 생성 를 다시 입력합니다. 이제 쿼리가 작동합니다.

쿼리_시스템_카탈로그
이전 버전의 Couchbase에서는 누구나 시스템 테이블에 완전히 액세스할 수 있었습니다. 지금은 이 문서의 뒷부분에서 설명하는 여러 가지 방법으로 제한되어 있지만, 시스템 테이블에 액세스할 수 있는 유용한 역할인 query_system_catalog가 있습니다. 이 역할은 쿼리나 시스템의 문제를 디버깅할 수 있어야 하지만 전체 관리자 권한이 주어져서는 안 되는 직원에게 특히 유용합니다.

관리자로 system:keyspaces를 쿼리하면 시스템에서 만든 두 개의 버킷을 모두 볼 수 있습니다:

하지만 자격 증명 없이 동일한 쿼리를 실행하면 결과가 필터링됩니다:

역할이 query_system_catalog인 새 사용자 'user5'를 만들고 쿼리를 다시 실행합니다. 관리자 권한으로 쿼리를 실행했을 때와 동일한 결과가 표시됩니다.

쿼리_외부_액세스

새로운 CURL() 함수를 사용하면 N1QL 내에서 REST 서비스를 쿼리할 수 있습니다. 이 함수를 사용하려면 몇 가지 구성을 수행하고 새 역할 query_external_access를 사용하여 쿼리를 실행해야 합니다.

먼저 쿼리를 시도해 보겠습니다:

적절한 권한이 제공되지 않아 쿼리가 거부되었습니다:

역할이 query_external_access인 사용자 "user6"을 만들고 해당 사용자를 사용하여 쿼리를 다시 실행합니다. 이번에는 보안상의 이유로 기본적으로 비활성화되어 있는 CURL()을 활성화하지 않았기 때문에 쿼리 실행이 거부됩니다.

다음 내용으로 "curl_whitelist.json" 파일을 만듭니다:

couchbase 디렉터리 아래에 배치합니다. Mac의 경우 정확한 위치는 "/Applications/Couchbase Server.app/Contents/Resources/couchbase-core/var/lib/couchbase/n1qlcerts/curl_whitelist.json"입니다. 다른 시스템에서는 위치가 약간 다름. 쿼리를 다시 시도하면 다음과 같이 데이터를 다운로드하여 올바르게 실행됩니다:

N1QL 역할의 전체 목록은 다음과 같습니다:

역할 허가 GRANT 구문
쿼리 선택 SELECT 문 GRANT ON 테스트버킷을 내사용자에게 선택
쿼리 삽입 문 삽입 내사용자에게 테스트버킷에 삽입을 부여합니다.
쿼리 업데이트 업데이트 내역 내사용자에게 테스트버킷에 업데이트 권한 부여
쿼리 삭제 문 삭제 내사용자에게 테스트버킷 삭제 권한을 부여합니다.
시스템 카탈로그 쿼리 시스템 키 공간에 액세스 GRANT query_system_catalog TO myuser
쿼리 색인 관리 인덱스 작업 GRANT query_manage_index ON testbucket TO myuser
외부 액세스 쿼리 CURL() 함수 내사용자에게 쿼리_외부_액세스 권한 부여

설명 및 준비

물론 쿼리를 실행하는 것 외에도 다른 작업을 할 수 있습니다. EXPLAIN을 사용하여 쿼리 엔진이 쿼리를 계산하는 방식을 이해할 수 있습니다. 그리고 PREPARE를 사용하여 반복 실행을 위해 쿼리를 설정할 수 있습니다.

Couchbase 5.0에서 EXPLAIN 및 PREPARE에 대한 권한은 간단합니다. 기본 문에 필요한 권한과 동일합니다. 그게 전부입니다.

이를 테스트하기 위해 앞의 '기본 역할' 섹션에서 사용한 것과 동일한 간단한 SELECT 문을 설명해 보겠습니다:

이에 대한 응답으로 특정 역할을 묻는 오류 메시지가 표시됩니다:

사용자에게 해당 역할을 제공하겠습니다:

'기본 역할'에서 보았던 것처럼 성공합니다.

이제 "기본 역할"에서 두 번째 문을 준비해 보겠습니다:

문 자체에 대해 원래와 동일한 오류 메시지가 표시됩니다:

그리고 SELECT 및 INSERT에 대한 자격 증명을 가진 사용자를 추가하면 PREPARE가 성공합니다:

부여 및 취소

5.0에서 N1QL에는 사용자에게 역할을 부여(GRANT)하고 이를 취소(REVOKE)하기 위한 문이 포함되어 있습니다. 이러한 문을 실행하려면 관리자 권한이 필요합니다.

이러한 문을 시도하기 전에 어떤 사용자가 구성되어 있고 어떤 역할을 하는지 검토해 보겠습니다. 다음은 Couchbase 콘솔의 보안 화면에서 볼 수 있는 내용입니다.

다음과 같이 user1에게 새 역할 cluster_admin을 부여할 수 있습니다:

이 작업이 성공하면 곧바로 새 역할 할당을 반영하도록 Couchbase 콘솔이 업데이트됩니다.

다음과 같이 매개변수화된 역할을 할당할 수도 있습니다:

초기 승인은 취소를 통해 취소할 수 있습니다:

이러한 모든 매개변수는 인수의 목록을 사용할 수 있습니다:

마지막으로 쿼리_인서트, 쿼리_업데이트, 쿼리_삭제, 쿼리_선택의 경우 쿼리_ 접두사는 선택 사항이므로 일부 구문을 더 친숙하게 만들 수 있습니다:

오라클과의 비교

Couchbase 5.0의 역할 기반 액세스 제어는 기존의 다른 데이터베이스 시스템에서 액세스 제어를 사용해 본 전문가에게 친숙하도록 설계되었습니다. 지금쯤이면 삽입/선택/업데이트/삭제 권한이 테이블과 같은 버킷에 적용되는 것과 같은 익숙한 개념을 인식하셨을 것입니다. 또한 광범위한 권한을 가진 관리자 사용자라는 개념도 익숙하실 것입니다. Couchbase 5.0의 역할 기반 액세스 제어는 기존의 다른 데이터베이스 시스템에서 액세스 제어를 사용해 본 전문가에게 친숙하도록 설계되었습니다. 지금쯤이면 삽입/선택/업데이트/삭제 권한이 테이블과 같은 버킷에 적용되는 것과 같은 익숙한 개념을 인식하셨을 것입니다. 또한 광범위한 권한을 가진 관리자 사용자라는 개념도 익숙하실 것입니다.

예를 들어 이 GRANT 쿼리는 Couchbase와 Oracle 모두에서 작동합니다:

Couchbase와 Oracle과 같은 다른 시스템의 개념적 차이점 중 하나는 사용자와 역할이라는 이원적 권한 모델을 가지고 있다는 점입니다. 일반적으로 사용자, 역할 및 권한이 있는 삼원 모델을 사용합니다. 따라서 Oracle에서 사용자에게 권한을 부여하는 것은 사용자에게 개체에 대한 권한을 부여하는 것입니다. Couchbase에서는 사용자에게 매개변수화된 역할을 부여하는 것입니다.

5.0에서는 역할이 정적입니다. 역할 생성/삭제/변경 문에 해당하는 문이 없습니다.

카우치베이스 권한은 시스템 전체 또는 버킷에 대한 권한입니다. 테이블, 열 또는 컬렉션에 대한 권한이라는 개념은 없습니다.

Couchbase에서 부여 및 취소는 관리자 사용자만 가능합니다. 관리자 옵션이나 부여 옵션과 같은 것은 없습니다. 권한을 변경하려면 관리자 권한이 필요합니다.

마지막으로, SET ROLE에 해당하는 명령이 없습니다. SET ROLE은 세션 수준 명령으로, Couchbase에서는 세션이 없고 개별 RESTful 요청만 있기 때문에 의미가 없습니다.

새로운 시스템 키 공간

카우치베이스 5.0에는 사용자와 관련된 세 가지 새로운 시스템 키 공간이 도입되었습니다. 첫 번째는 system:user_info입니다. 이 키스페이스는 역할을 포함하여 시스템에 구성된 사용자를 나열합니다. 쿼리를 해보겠습니다:

이렇게 하면 설정한 모든 사용자에 대해 하나씩, 그리고 구성된 관리자에 대해 이렇게 7개의 항목이 생깁니다:

system:applicable_roles 키스페이스는 비슷하지만 각 사용자 역할을 별도의 항목으로 분리하여 데이터에 대한 보다 관계적인 보기를 생성합니다:

마지막으로 system:my_user_info 키스페이스에는 쿼리와 함께 자격 증명이 전달된 사용자에 해당하는 system:my_user_info의 일부가 표시됩니다.

시스템 키 공간에 액세스

보안 운영의 일반적인 철학에 따라, 시스템 키 공간(버킷)은 버전 5.0에서 보안이 강화되었습니다. 제한의 정도는 각 키공간에 있는 데이터에 따라 달라집니다.

세 개의 키 공간에는 공격자에게 가치가 있을 만한 것이 없습니다:

  • 시스템:데이터스토어
  • 시스템:네임스페이스
  • 시스템:이중

따라서 이러한 키 공간은 보안되지 않습니다. 액세스하는 데 자격 증명이 필요하지 않습니다.

보안의 다른 쪽 끝에는 사용자 목록과 해당 역할이 포함된 system:user_info 및 system:applicable_roles가 있습니다. 이 테이블은 관리자 및 읽기 전용 관리자 사용자만 액세스할 수 있습니다. system:my_user_info 테이블도 비슷하지만 쿼리와 함께 자격 증명이 제시된 사용자의 관련 정보만 표시합니다. 위에서 이미 이러한 테이블을 살펴보았습니다.

다음 네 개의 시스템 키 공간에는 다양한 런타임 및 구성 정보가 포함되어 있습니다.

  • 시스템:준비됨
  • 시스템:완료_요청
  • 시스템:활성_요청
  • 시스템:노드

여기에 포함된 정보는 사용자 정보만큼 민감하지 않기 때문에 더 광범위하게 볼 수 있습니다. 대부분의 관리자, 심지어 미성년자 관리자도 액세스할 수 있습니다: 관리자, 읽기 전용 관리자, 클러스터 관리자, 쿼리 시스템 카탈로그, 복제 관리자, 버킷 관리자(모든 버킷) 또는 보기 관리자(모든 버킷).

위에서 시스템 카탈로그 쿼리 권한으로 만든 사용자 user5로 system:prepareds를 살펴봅시다.

이것은 앞서 만든 준비된 문 하나를 보여줍니다.

system:keyspaces 키스페이스에는 시스템에 구성된 버킷 목록이 표시됩니다. 이 정보는 공격자에게 시스템이 어떤 용도로 사용되는지에 대한 정보를 제공하기 때문에 다소 민감한 정보입니다. 따라서 높은 수준의 역할(관리자, 읽기 전용 관리자, 클러스터 관리자)을 가진 사용자는 이 키스페이스의 모든 것을 볼 수 있습니다. 쿼리 시스템 카탈로그 역할이 있는 사용자도 이 역할이 쿼리 문제를 디버깅하기 위한 것이므로 모든 것을 볼 수 있습니다. 다른 사용자의 경우 보기가 필터링되어 쿼리 선택 권한이 있는 키 스페이스만 볼 수 있습니다.

예를 들어, 자격 증명이 없는 시스템:키스페이스에 대한 쿼리는 성공하지만 항목은 표시되지 않습니다:

시스템 카탈로그 쿼리 역할을 가진 user5에 대한 자격 증명을 추가하면 모든 항목이 표시됩니다:

query_select[testbucket1]만 있는 user1에 대한 자격 증명을 사용하면 testbucket1에 대한 항목만 볼 수 있습니다.

시스템:인덱스 키스페이스는 시스템:키스페이스와 매우 유사하게 처리됩니다. 상위 수준 역할은 전체 액세스를 허용하고, 쿼리_select 역할은 필터링된 액세스를 허용합니다. 실제 차이점은 쿼리_관리_인덱스 역할은 쿼리_선택과 같이 필터링된 액세스를 허용한다는 것입니다.

관리자 API 보호

N1QL 쿼리 엔진에는 시스템 키 공간 중 세 가지에 해당하는 RESTful API인 system:prepareds, system:completed_requests, system:active_requests가 있습니다. 이전에는 Couchbase 4.6에서 개방되어 있었지만 지금은 보안이 유지됩니다. 키 스페이스와 동일한 자격 증명이 필요합니다.

필요한 역할이 있는 user5로 다시 시도하면 작동합니다.

마이그레이션된 비밀번호 없는 버킷에 액세스

4.6에서 5.0으로 마이그레이션할 때는 기존 권한 패턴을 유지하여 레거시 애플리케이션이 이전처럼 계속 작동할 수 있도록 하는 것이 유용합니다. 4.6에서는 버킷 자체의 비밀번호를 사용하여 액세스를 제어했지만 5.0에서는 다양한 역할을 가진 사용자를 기반으로 액세스를 제어하기 때문에 이 경우 약간 까다롭습니다.

기존 액세스 패턴을 유지하기 위해 업그레이드 프로세스 중에 원래 버킷과 일치하는 이름과 비밀번호를 가진 사용자를 생성합니다. 이렇게 하면 비밀번호 없이 액세스하는 경우에도 기존 애플리케이션이 하던 작업을 계속 수행할 수 있습니다.

이를 실제로 확인하려면 약간의 노력이 필요합니다. 편안해지세요.

먼저 Couchbase 4.6을 설치합니다. 그런 다음 비밀번호가 없는 "openbucket"과 비밀번호가 "password"인 "closedbucket"이라는 두 개의 버킷을 만듭니다.

쿼리 탭으로 이동하여 두 버킷 모두에 대한 기본 인덱스를 추가하여 N1QL 쿼리를 실행할 수 있도록 합니다.쿼리 탭으로 이동하여 두 버킷 모두에 대한 기본 인덱스를 추가하여 N1QL 쿼리를 실행할 수 있도록 합니다.

비밀번호 없이 OpenBucket을 쿼리할 수 있는지 확인합니다:

그러나 비밀번호 없이 닫힌 버킷을 쿼리하는 것은 실패합니다:

하지만 비밀번호로 ClosedBucket을 쿼리할 수 있습니다:

이것이 5.0으로 업그레이드할 때 보존하고자 하는 액세스 패턴입니다. 이제 방금 만든 기본 데이터는 그대로 유지하면서 Couchbase를 종료하고 5.0으로 업그레이드합니다. 그런 다음 Couchbase 콘솔의 보안 화면으로 이동합니다. 업그레이드 프로세스에서 생성된 두 명의 새 사용자를 볼 수 있습니다.

"closedbucket" 사용자는 4.6에서 버킷에 할당된 비밀번호와 "closedbucket" 버킷과 동일한 이름을 갖습니다. 이를 통해 기존 폐쇄형 버킷에 대한 액세스를 유지할 수 있습니다. "openbucket" 사용자는 동일한 작업을 수행하지만 오픈버킷의 경우입니다.

이전 액세스 패턴이 여전히 작동하는지 확인해 보겠습니다.

비밀번호 없이도 OpenBucket에 액세스할 수 있습니다.

비밀번호가 없으면 Closedbucket 액세스가 실패합니다.

그러나 비밀번호를 사용하면 ClosedBucket 액세스가 성공합니다.

만세! 모든 것이 예전처럼 작동합니다. 가서 간식을 준비하세요.

요약

  • Couchbase 4.6의 액세스 제어는 버킷에 비밀번호를 사용했습니다. 5.0에서는 사용자에게 할당된 역할을 사용합니다.
  • N1QL에 대한 사용자의 액세스를 제어하는 데 사용되는 주요 역할은 쿼리 선택/쿼리 삽입/쿼리 업데이트/쿼리 삭제입니다. 모두 버킷별로 매개변수화되어 있습니다.
  • 보다 전문화된 중요한 역할로는 쿼리_관리_인덱스, 쿼리_시스템_카탈로그, 쿼리_외부_액세스 등이 있습니다.
  • 쿼리를 설명하거나 준비하는 데는 쿼리를 실행하는 것과 동일한 역할이 필요합니다.
    역할을 부여하고 취소할 수 있는 새로운 명령문이 있습니다.
  • 역할 시스템은 다른 주요 데이터베이스에 익숙한 사용자에게는 익숙할 것입니다. 가장 큰 차이점은 Couchbase에는 역할 외의 권한에 대한 개념이 없다는 것입니다.
  • 사용자와 사용자에게 할당된 역할을 쿼리할 수 있는 새로운 시스템 키 공간이 있습니다.
    시스템 키 공간은 보안을 위해 제어됩니다. 동작은 키 공간에 있는 데이터의 민감도에 따라 키 공간마다 다릅니다.
  • 비밀번호가 없는 버킷의 경우에도 기존 액세스 패턴은 4.6에서 5.0으로 마이그레이션한 후에도 계속 작동합니다.

작성자

게시자 요한 라슨

요한 라슨은 카우치베이스의 선임 소프트웨어 엔지니어입니다. Johan은 분산형 NoSQL 시스템에서 JSON 데이터를 위한 SQL 기반 쿼리 언어를 구축하는 업무를 담당하고 있습니다.

댓글 남기기