주요 컨텐츠로 이동
제품

임베딩을 넘어: 모든 사용자를 위해 AI/BI 대시보드 보안을 확보하는 방법

게시된 하나의 대시보드에서 사용자별 행 수준 보안을 지원합니다. 단일 권한 테이블을 통해 액세스가 제어되므로 외부 파트너와 내부 팀이 동일한 임베디드 대시보드를 안전하게 공유할 수 있습니다.

작성자: Sonakshi Pandey

  • 하나의 대시보드로 모든 사용자를 지원합니다. 단일 권한 테이블과 서명된 임베드 토큰의 __aibi_external_value에 의해 각 사용자가 액세스할 수 있는 행이 결정되므로, 고객별로 대시보드를 생성하거나 쿼리마다 필터를 반복할 필요가 없습니다.
  • 액세스 권한은 수동으로 관리되는 사용자 목록이 아니라 ID 제공업체 그룹을 통해 부여됩니다. 애플리케이션은 임베드 토큰을 생성하기 전에 on-behalf-of 토큰을 사용하여 내부 사용자의 그룹을 확인합니다.
  • 기본 거부(Default-deny) 및 심층 방어 적용. 이 패턴은 민감한 열을 마스킹하고, 권한이 없는 사용자의 토큰 요청을 거부하며, Unity Catalog 행 필터를 사용하여 직접적인 SQL 액세스를 보호합니다.

과제

고객용 애플리케이션에 Databricks AI/BI 대시보드를 임베딩하는 것은 비교적 간단합니다. 임베딩을 활성화하고, 백엔드에서 범위 지정 토큰을 생성한 다음, 클라이언트 SDK를 통해 대시보드를 렌더링하면 됩니다. 기본 가이드인 고객용 애플리케이션에 Databricks AI/BI 대시보드를 임베딩하는 방법에서 이 프로세스를 처음부터 끝까지 자세히 설명합니다.

더 까다로운 문제는 권한 부여입니다. 대시보드가 임베딩된 후 각 사용자가 어떤 행(row)을 볼 수 있어야 할까요? 파트너는 자신의 데이터만 보아야 하고, 내부 팀은 해당 지역의 데이터만 보아야 할 수 있습니다. 이 가이드에서는 이러한 규칙을 적용하는 방법을 설명합니다.

이 참조 패턴은 여러 Databricks 기능인 __aibi_external_value, Unity Catalog 행 필터 및 열 마스크, 그리고 ID 제공업체(IdP)로부터 동기화된 그룹을 결합합니다. 이는 활성화할 수 있는 단일 기능이 아니라 하나의 디자인 패턴입니다.

하나의 규칙, 두 가지 적용 경로

image1.png

동일한 권한 테이블이 애플리케이션을 통해 액세스하는 임베딩된 대시보드와 Databricks 사용자가 실행하는 직접 SQL 쿼리라는 두 가지 경로를 모두 제어합니다.

구체적인 시나리오

서부(West), 동부(East), 중부(Central)의 세 지역에 걸친 데이터를 위해 공유 "미결 매출채권(AR) 작업" 대시보드를 사용하는 회사를 가정해 보겠습니다. 이 대시보드는 두 부류의 사용자를 대상으로 합니다.

  • Acme Ops, Bolt Partners, Core Logistics와 같은 외부 운영 파트너는 Databricks 로그인 계정이 없으며 화이트 레이블 포털을 통해 대시보드에 액세스합니다. 각 파트너는 연락처 이메일이 마스킹된 상태로 자신의 지역 데이터만 볼 수 있어야 합니다.
  • 내부 팀은 Databricks에 로그인하는 회사의 직원들입니다. 재무 팀은 모든 지역에 액세스해야 하는 반면, 지역 운영 팀은 자신의 지역만 볼 수 있어야 합니다. 이들의 액세스 권한은 수동으로 관리되는 사용자 목록이 아니라 Okta 또는 Entra ID와 같은 ID 제공업체 그룹에서 부여됩니다.

다섯 명의 사용자가 하나의 데이터 세트를 공유하며, 각각 다른 부분을 보게 됩니다: Acme Ops, Bolt Partners, Core Logistics, 재무 팀, 그리고 지역 운영 팀. 아래 예시는 Acme와 재무 팀에 초점을 맞추고 있으며, 식별자 partner_acme, finance_all, West가 이 예시들을 나타냅니다. 동일하게 게시된 대시보드에서 Acme는 이메일이 마스킹된 West 지역을 보고, 재무 팀은 세 지역 전체를 마스킹 없이 보게 됩니다.

하나의 테이블, 하나의 뷰, 하나의 대시보드

액세스 규칙은 대시보드나 쿼리 여기저기에 분산되지 않고 한 곳에서 관리됩니다. 고객별로 대시보드를 만들면 동기화가 어긋날 수 있는 복사본이 생성되고, 모든 쿼리에서 필터를 반복하면 실수가 발생할 가능성이 커집니다.

이 모델은 세 가지 오브젝트로 구성됩니다:

  • 기본 테이블 `open_ar_tasks`는 AR 작업당 하나의 행을 보유하며, 지역 및 연락처 이메일 태그가 지정되어 있습니다.
task_idmarketoperating_partneramount_opencontact_email
T-1001WestAcme Ops$12,400jane@acme.com
T-1002EastBolt Partners$8,900raj@bolt.com
T-1003CentralCore Logistics$15,200mia@core.com
  • 권한 테이블은 액세스를 위한 단일 진실 공급원(single source of truth)입니다. 각 행은 범위(scope)가 액세스할 수 있는 지역과 민감한 값을 마스킹해야 하는지 여부를 식별합니다. viewer_scope 열에는 partner_acme와 같은 외부 파트너 ID와 finance_all과 같은 내부 그룹 이름이 모두 저장됩니다.
viewer_scopemarketmask_pii
partner_acmeWesttrue
finance_allWestfalse
finance_allEastfalse
finance_allCentralfalse
ops_westWestfalse
  • 보안 뷰(Secured view)는 기본 테이블을 권한 테이블과 조인하므로, 사용자는 권한이 있는 지역만 볼 수 있으며 플래그가 설정된 경우 이메일이 마스킹됩니다.

대부분의 배포에서는 업스트림 권한 시스템 또는 애플리케이션 소유의 그룹-지역 매핑이 이 테이블을 채우며, 각 사용자별로 수동 편집하지 않습니다.

이를 통해 고객별 대시보드를 만들거나 쿼리마다 필터를 반복할 필요가 없습니다. 규칙은 대시보드를 수정하지 않고도 쿼리, 감사 및 변경할 수 있는 테이블에 저장됩니다.

사용자별로 적용되는 보안 뷰는 해당 사용자가 권한을 가진 데이터만 반환합니다:

Acme(external_value = partner_acme): West 지역만 표시, 연락처 이메일 마스킹됨.

task_idmarketoperating_partneramount_opencontact_email
T-1001WestAcme Ops$12,400****@acme.com

재무 팀(external_value = finance_all): 세 지역 모두 표시, 연락처 이메일 전체 표시.

task_idmarketoperating_partneramount_opencontact_email
T-1001WestAcme Ops$12,400jane@acme.com
T-1002EastBolt Partners$8,900raj@bolt.com
T-1003CentralCore Logistics$15,200mia@core.com

__aibi_external_value가 생성되는 방식

백엔드는 임베드 토큰을 생성할 때 이 값을 설정합니다. 서비스 주체(service principal)로 인증하고 Databricks에 두 가지 값, 즉 감사를 위해 사용자를 식별하는 external_viewer_id와 사용자의 범위를 나타내는 external_value가 포함된 범위 지정 토큰을 요청합니다. Databricks가 토큰에 서명하므로 사용자는 임베딩된 값을 수정할 수 없으며, 이 값은 대시보드 SQL에 __aibi_external_value로 노출됩니다. 서비스 주체의 자격 증명을 보유하므로 이 백엔드는 브라우저가 아닌 신뢰할 수 있는 서버 측 구성 요소이며, 해당 자격 증명은 소스 제어가 아닌 비밀 관리자(secrets manager)에 보관됩니다.

핵심 세부 사항은 어떤 ID로 쿼리를 실행하는가입니다. 임베딩된 쿼리는 사용자의 Databricks ID가 아니라 구성된 게시 ID(publishing identity)로 실행됩니다.

외부 임베딩의 경우, Databricks는 개별 데이터 권한을 사용하고 서비스 주체에 자체 데이터 액세스 권한을 부여하여 쿼리가 서비스 주체로 실행되도록 할 것을 권장합니다. (대신 공유 데이터 권한으로 게시하면 게시자의 자격 증명으로 쿼리가 실행됩니다.) 그런 다음 뷰는 __aibi_external_value를 통해 각 사용자에 대한 액세스 범위를 좁힙니다. 쿼리가 서비스 주체로 실행되기 때문에, 임베드 경로에서 대시보드를 보는 실제 사람을 is_account_group_member()로 식별할 수 없습니다.

중요한 세부 사항은 external_value가 파트너 ID에 국한되지 않는다는 점입니다. 백엔드가 토큰에 서명하는 모든 범위가 될 수 있습니다. 예를 들어 외부 파트너의 경우 partner_acme, 내부 그룹의 경우 finance_all(해당 그룹 이름)이 될 수 있습니다.

권한 테이블은 동일한 열에 파트너 ID와 그룹 이름을 모두 보유하므로, 하나의 대시보드, 하나의 뷰, 하나의 필터로 두 가지를 모두 처리할 수 있습니다.

사용자는 서명된 값을 보거나 설정할 수 없으므로 이를 변경할 수 없습니다. 알 수 없는 범위는 어떤 행과도 일치하지 않으므로 기본 거부(default-deny) 동작을 제공합니다.

동일한 뷰와 동일한 필터(WHERE viewer_scope = __aibi_external_value)가 두 부류의 사용자 모두에게 제공됩니다. 해당 범위의 출처만 다릅니다:

속성외부 파트너내부 팀
Databricks 로그인아니요, 포털을 통해 액세스예, IdP를 통해 로그인
범위 설정 주체고정된 파트너 ID권한이 부여된 IdP 그룹
__aibi_external_value로 서명된 값partner_acmefinance_all
일치하는 권한단일 지역권한이 부여된 하나 이상의 지역

개인이 아닌 그룹에 액세스 권한 부여

조직은 일반적으로 ID 제공업체로부터 동기화된 그룹을 통해 액세스를 관리합니다. 누군가 Okta의 Finance 그룹에 가입하면 그들의 액세스 권한이 자동으로 finance_all에 매핑되며, 데이터 테이블을 건드릴 필요가 없습니다. 이 예시에서 finance_all은 모든 지역에 매핑되고 ops_west는 West 지역에 매핑됩니다.

애플리케이션은 뷰어에게 어떤 그룹이 속해 있는지 어떻게 알 수 있을까요? 임베딩 중에는 SQL에 의존할 수 없습니다. 쿼리가 서비스 주체(service principal)로 실행되어 is_account_group_member()가 잘못된 ID를 확인하기 때문입니다. 애플리케이션은 토큰을 생성하기 전에 뷰어를 식별할 수 있는 백엔드에서 뷰어의 그룹을 확인해야 합니다.

한 가지 옵션은 사용자 권한 부여가 활성화된 Databricks Apps에서 애플리케이션을 실행하는 것입니다.

로그인한 내부 사용자의 경우, 플랫폼은 뷰어의 이메일과 대리(OBO) 토큰을 포함한 신뢰할 수 있는 ID 컨텍스트를 백엔드로 전달합니다. 백엔드는 이 토큰을 사용하여 뷰어로서 SCIM /Me를 호출하고 해당 그룹을 읽습니다.

이 방식은 사용자가 자신의 레코드를 읽는 것이므로 서비스 주체에 대한 관리자 권한이 필요하지 않습니다. 다만 사용자 권한 부여 범위가 필요하며, Apps OBO 기능은 아직 개발 중이므로 실제 배포 환경에서 검증한 후 사용하는 것이 좋습니다.

권한이 있는 그룹을 찾지 못하면, 원시 이메일과 같은 더 넓은 범위의 ID로 대체하는 대신 안전하게 실패(fail closed) 처리하고 토큰 발급을 거부하십시오.

뷰어가 권한이 있는 여러 그룹에 속해 있는 경우, 결과를 결정론적으로 해결하십시오. 우선순위를 정의하거나 토큰을 생성하기 전에 여러 그룹을 하나의 표준 범위로 매핑하여 동일한 뷰어가 항상 일관된 액세스 권한을 받도록 하십시오.

외부 파트너는 더 간단합니다. Databricks ID가 없으므로 이들의 범위는 로그인 시 할당되는 고정된 파트너 ID가 됩니다. 동일한 토큰, 동일한 필터가 적용되며 조회가 필요 없습니다.

설계 시 고려해야 할 한 가지 제한 사항은 서명된 토큰이 단 하나의 external_value만 가질 수 있다는 점입니다. 뷰어가 서로 다른 권한을 가진 여러 그룹에 속해 있더라도 하나의 토큰은 여전히 하나의 범위만 나타낼 수 있습니다. 1인당 하나의 역할만 갖는 일반적인 경우에는 이 방식도 괜찮습니다.

진정한 다중 그룹 결합(union)의 경우, 모든 그룹에 대해 행 필터가 OR 연산을 수행할 수 있는 전체 액세스 그룹 또는 아래의 직접 SQL 경로를 사용하십시오. 복합 범위(예: JSON)를 external_value에 패킹할 수 있지만, 이 경우 파싱 및 매칭 작업이 데이터 세트 SQL로 이동하며 1 KB 페이로드 제한을 받게 됩니다.

보안 보장 강화

행 필터링은 각 뷰어가 자신의 행만 볼 수 있도록 하는 기본 동작을 제공합니다. 세 가지 추가 레이어가 제어 기능을 강화하며, 세 레이어 모두 동일한 권한 테이블에서 읽습니다.

뷰어별 민감한 열 마스킹

행 수준 보안은 뷰어가 액세스할 수 있는 행을 결정합니다. 마스킹은 외부 파트너가 일반적으로 내부 팀만큼 상세한 정보가 필요하지 않기 때문에 볼 수 있는 열을 결정합니다.

파트너의 경우 true이고 내부 그룹의 경우 false인 mask_pii 플래그는 보안 뷰의 마스킹 로직(위 SQL의 CASE 표현식)을 실행합니다. 동일한 대시보드에서 내부 뷰어에게는 전체 이메일을 보여주고, 파트너에게는 ****@example.com과 같이 마스킹된 값을 보여줄 수 있습니다. 마스킹 규칙이 여러 테이블에 걸쳐 있고 복잡해지면 Unity Catalog 열 마스크 및 속성 기반 액세스 제어(ABAC)를 사용하는 것이 장기적으로 더 좋습니다. 여기서는 예제를 독립적으로 유지하기 위해 뷰를 사용합니다.

기본 거부 및 검증

알 수 없는 범위는 대시보드 행을 반환하지 않아야 하며, 기본 데이터 구조에 대해 아무것도 드러내지 않아야 합니다. 구조를 암시하는 오류도, 부분적인 데이터도 없이 빈 결과만 반환해야 합니다. 더 일찍 차단하는 것이 훨씬 더 깔끔합니다. 백엔드가 토큰을 생성하기 전에 권한 테이블을 확인하고 권한이 있는 행이 0개인 범위는 거부하는 것입니다. 마찬가지로 중요한 점은 범위가 클라이언트가 제공한 매개변수가 아니라 인증된 뷰어로부터 파생되므로, 뷰어가 다른 테넌트의 범위를 요청할 수 없다는 것입니다.

토큰 발급 단계에서 제어하면 거부된 뷰어가 토큰을 아예 받지 못하도록 방지할 수 있으며, 이는 SQL 필터에만 의존하는 것보다 훨씬 효과적입니다. 토큰 발급 성공과 거부된 요청을 모두 로깅하면 권한 부여 결정을 감사할 수 있습니다. 거부된 뷰어는 아예 나타나지 않으며, 요청이 통과되더라도 알 수 없는 범위는 여전히 대시보드 행을 반환하지 않습니다. 이 로그에 external_viewer_id와 해당 범위를 기록하면 감사 중에 각 권한 부여 결정을 실제 고객 또는 사용자로 추적할 수 있습니다.

직접 SQL 경로 보호

임베드 제어는 애플리케이션 경로를 보호합니다. 기본 테이블을 직접 쿼리하는 Databricks 사용자는 별도의 위협 요인입니다. 쿼리하는 사용자의 ID 및 그룹에 매핑된 Unity Catalog 행 필터를 기본 테이블에 추가하십시오. 이 직접 쿼리 경로에서 is_account_group_member()는 실제 사용자를 평가하고 권한이 있는 모든 그룹을 결합할 수 있습니다. 아래 함수의 게시자 예외 처리(current_user()가 게시 ID와 동일함)는 대시보드를 게시하거나 새로 고치는 ID에 대해 의도적으로 허용된 비상 조치(break-glass)이며, 일반적인 운영자 우회 수단이 아닙니다. 이는 선택 사항이며 위험성이 높으므로 정당한 사유가 있는 경우에만 포함하고 배포별로 승인하십시오.

민감한 필드에 대한 열 마스크도 동일한 방식으로 작동합니다. 이러한 Unity Catalog 제어는 임베드 경로와 분리되어 있습니다. 임베디드 뷰어는 __aibi_external_value 및 권한 뷰를 통해 범위가 지정되는 반면, 직접 워크스페이스 쿼리는 호출자의 ID와 그룹을 평가하는 Unity Catalog 행 필터에 의해 보호됩니다. 두 적용 지점 모두 동일한 권한 테이블을 사용합니다.

구축하기 전에

"멀티 테넌시"에 대하여. 이는 풀링된 논리적 멀티 테넌시입니다. 외부 파트너는 서로 격리되는 반면, 내부 직원은 회사 자체 테넌트 내에서 그룹 기반(역할 기반) 액세스 권한을 받습니다. 모든 데이터는 공유 테이블에 유지되며 토큰, 뷰 필터 및 권한 테이블이 격리를 강제합니다. 직접 SQL 행 필터는 앱 외부에서도 동일한 보장을 확장합니다.

이 패턴을 사용해야 하는 경우. Databricks 계정이 없는 외부 파트너와 내부 직원이 하나의 대시보드를 공유해야 할 때 이 패턴을 사용하십시오. 모든 뷰어가 내부 Databricks 사용자인 경우 Unity Catalog 행 및 열 보안을 사용하는 기본 임베딩으로도 충분할 수 있습니다.

실제 제약 조건 및 주의 사항. 게시하기 전에 현재 설명서를 참조하여 다음 제품 제한 사항 및 운영 세부 정보를 확인하십시오.

  • 토큰의 수명은 1시간으로 짧으므로, 특히 탭을 열어둔 경우 앱에서 토큰을 새로 고쳐야 합니다. 클라이언트 SDK를 사용하면 이 작업을 쉽게 수행할 수 있습니다. 토큰 만료 시간이 다가오면 getNewToken 콜백이 /api/token 엔드포인트에서 토큰을 다시 가져옵니다.
  • `external_viewer_id`와 `external_value`를 합쳐서 1 KB 미만으로 유지하십시오. JSON 블롭이나 긴 이메일이 아닌 간결한 식별자를 사용해야 합니다.
  • 외부 임베딩의 경우 워크스페이스당 초당 20회의 대시보드 로드 속도 제한이 적용됩니다. 대규모 B2B 포털의 경우 알아둘 가치가 있습니다.
  • PII가 아닌 `external_viewer_id`를 사용하십시오. 감사 로그에 기록되므로 전체 이름이나 원시 이메일보다는 고유한 고객 또는 사용자 ID를 사용하는 것이 좋습니다.
  • 다운로드는 기본적으로 활성화되어 있습니다. 워크스페이스 관리자가 다운로드 기능을 끄지 않는 한, 임베디드 뷰어는 CSV, TSV, Excel 및 PNG를 내보낼 수 있습니다. 내보낸 결과가 예상되는 뷰어 제한 데이터와 일치하는지 확인하세요.
  • 직접 SQL 경로를 위한 계정 수준 그룹을 프로비저닝하세요. UC 행 필터 및 마스크는 워크스페이스 로컬 그룹이 아닌 계정 수준 그룹에 대해 is_account_group_member()를 평가합니다. 임베드 경로는 이 함수를 호출하지 않습니다.
  • 대규모 권한 테이블을 주의 깊게 살펴보세요. 수천 개의 범위나 깊은 계층 구조의 경우 조인 및 마스크 표현식을 단순하게 유지하고, 규칙이 복잡해지면 ABAC에 의존하세요.

핵심 요약

  • 액세스 규칙을 하나의 권한 테이블에 유지하고, 이를 임베디드 대시보드와 직접 SQL 보호 모두에 사용하세요.
  • 뷰어 또는 그룹 범위를 __aibi_external_value에 서명하여 입력하세요. 사용자가 편집할 수 있는 필터에 의존하지 마세요.
  • 기본 거부(default-deny), 마스킹 및 Unity Catalog 행 필터를 계층화된 제어 기능으로 사용하세요.
  • 임베딩은 첫 단계에 불과합니다. 액세스 제어를 설계하고 검증하는 것이 가장 중요한 작업입니다.

다음 단계

기본 가이드인 고객 대상 애플리케이션에 Databricks AI/BI 대시보드를 임베드하는 방법으로 시작한 다음, 이 포스트에서 설명하는 권한, 마스킹 및 기본 거부 패턴을 적용해 보세요. 기반이 되는 거버넌스 제어에 대한 자세한 내용은 AI/BI 임베딩 문서Unity Catalog 행 필터 및 열 마스크ABAC 가이드를 참조하세요.

(이 글은 AI의 도움을 받아 번역되었습니다. 원문이 궁금하시다면 여기를 클릭해 주세요)

최신 게시물을 이메일로 받아보세요

블로그를 구독하고 최신 게시물을 이메일로 받아보세요.