행 필터링 및 열 마스킹에 대한 일반적인 패턴

이 페이지에서는 ABAC 행 필터 및 열 마스크 정책을 구현하기 위한 일반적인 패턴을 설명합니다.

캐스트 호환 마스킹 함수

Azure Databricks 대상 열의 데이터 형식과 일치하도록 마스킹 함수 출력을 자동으로 캐스팅합니다. 열 마스크에 대한 자동 형식 캐스팅을 참조하세요.

다음 패턴은 캐스트 호환 마스킹 함수를 디자인하는 데 도움이 됩니다.

캐스팅 가능한 형식 반환

열을 마스킹할 때 동일한 데이터 형식 또는 열에 캐스팅할 수 있는 형식을 반환합니다. 정책에서 대상으로 하는 열의 데이터 형식을 확인하고 함수의 모든 분기가 호환되는 값을 반환하는지 확인합니다.

-- Succeeds: Masks a DOUBLE column, returns DOUBLE in every branch
CREATE FUNCTION mask_salary(salary DOUBLE, user_role STRING)
RETURNS DOUBLE
RETURN CASE
  WHEN user_role IN ('admin', 'hr') THEN salary
  WHEN user_role = 'manager' THEN ROUND(salary / 1000) * 1000
  ELSE 0.0
END;

-- Fails: 'CONFIDENTIAL' cannot be cast to a DOUBLE column type
CREATE FUNCTION mask_salary_as_text(salary DOUBLE, user_role STRING)
RETURNS STRING
RETURN CASE
  WHEN user_role IN ('admin', 'hr') THEN CAST(salary AS STRING)
  ELSE 'CONFIDENTIAL'
END;

숫자 오버플로 방지

마스크 함수가 대상 열보다 더 넓은 숫자 형식을 허용하고 반환하면 결과가 자동으로 열의 형식으로 다시 캐스팅됩니다. 반환된 값이 더 좁은 형식의 범위를 초과하면 런타임에 캐스트 오버플로 및 쿼리가 실패합니다.

-- The target column is TINYINT (max 127). The input is upcast to BIGINT
-- for the function. Adding 1000 produces a BIGINT result that overflows
-- when cast back to TINYINT.
CREATE FUNCTION mask_score(score BIGINT)
RETURNS BIGINT
RETURN score + 1000;

여러 열 형식에 VARIANT 사용

여러 열 형식은 VARIANT 기반 마스킹 함수를 참조하세요.

테스트 캐스트 호환성

다양한 데이터 패턴으로 마스킹 함수를 테스트합니다.

SELECT CAST(mask_salary(salary, 'admin') AS DOUBLE) FROM employees;
SELECT CAST(mask_salary(salary, 'manager') AS DOUBLE) FROM employees;
SELECT CAST(mask_salary(salary, 'viewer') AS DOUBLE) FROM employees;

여러 열 형식에 대한 VARIANT 기반 마스킹 함수

예를 들어, 서로 다른 데이터 형식의 열(예: INT, DOUBLE, DECIMAL(10,2), DECIMAL(15,5) 등)을 마스킹해야 하는 경우, VARIANT 형식을 수락하고 반환하는 하나의 마스킹 UDF를 작성할 수 있습니다. Azure Databricks ANSI SQL 표준에 따라 대상 열의 데이터 형식과 일치하도록 열 마스크 함수 출력을 자동으로 캐스팅합니다.

이 방법은 UDF 및 필요한 정책의 수를 줄입니다. 각 열 형식에 대해 별도의 마스킹 함수를 작성하는 대신 하나의 함수가 모든 형식을 처리합니다.

단일 함수를 사용하여 여러 숫자 형식 마스크

각 숫자 정밀도에 대해 별도의 마스크 함수를 만드는 대신 단일 함수를 사용하여 VARIANT 모두 처리할 수 있습니다.

CREATE FUNCTION mask_numeric(val VARIANT)
RETURNS VARIANT
DETERMINISTIC
RETURN 0::VARIANT;

이 함수는 0VARIANT로 반환하며, Azure Databricks가 자동으로 대상 열의 형식으로 캐스팅합니다. 이 함수를 사용하는 단일 ABAC 정책은 각 정밀도에 대해 별도의 함수를 요구하지 않고도 INT, DOUBLE, DECIMAL 열을 마스킹할 수 있습니다.

함수 내에서 형식을 명시적으로 유지하려는 경우 다음을 사용하여 schema_of_variant()형식에서 분기하고 각각에 대해 적절한 마스크된 값을 반환할 수 있습니다.

-- Use VARIANT to accommodate different data types
CREATE FUNCTION flexible_mask(data VARIANT)
RETURNS VARIANT
RETURN CASE
  WHEN schema_of_variant(data) = 'INT' THEN 0::VARIANT
  WHEN schema_of_variant(data) = 'DATE' THEN DATE'1970-01-01'::VARIANT
  WHEN schema_of_variant(data) = 'DOUBLE' THEN 0.00::VARIANT
  ELSE NULL::VARIANT
END;

구조체 열을 VARIANT로 마스킹하기

Databricks Runtime 18.1 이상의 경우, ABAC 정책 내에서 구조체 열을 VARIANT 형식으로 캐스팅하여 마스킹할 수 있습니다. 구조체의 형태에 따라 분기하여 필드를 선택적으로 삭제할 수 있습니다.

메모

구조체를 마스킹에 VARIANT 캐스팅하는 것은 ABAC 열 마스크 정책 내에서만 지원됩니다.

다음 예제에서는 두 개의 서로 다른 구조체 셰이프를 식별하고 각각에서 중요한 필드를 수정하는 데 사용합니다 schema_of_variant() .

CREATE FUNCTION flexible_mask(data VARIANT)
RETURNS VARIANT
RETURN CASE
WHEN schema_of_variant(data) = 'OBJECT<age: BIGINT, email: STRING>' THEN
  to_variant_object(named_struct('age', data:age, 'email', 'redacted'))
WHEN schema_of_variant(data) = 'OBJECT<id: BIGINT, ssn: STRING>' THEN
  to_variant_object(named_struct('id', data:id, 'ssn', 'xxx-xx-xxxx'))
ELSE NULL::VARIANT
END;

중요한 열에 태그가 지정될 때까지 액세스 방지

일반적인 거버넌스 패턴은 데이터가 분류되었는지 여부에 따라 액세스를 제어하는 것입니다. 분류 상태에 따라 다양한 수준의 보호를 적용하는 기본 제한 태그 및 정책을 사용하여 이를 구현할 수 있습니다.

  1. 카탈로그 또는 스키마 수준에서 태그를 적용하여 자동화 또는 태그 상속을 통해 기본적으로 모든 새 개체에 태그를 classification : unverified 적용하여 카탈로그 또는 스키마에 추가된 모든 새 테이블이 태그를 자동으로 상속하도록 합니다.
  2. 태그가 지정된 테이블에 대한 액세스를 차단하는 행 필터 정책을 만듭니다 classification : unverified.
  3. 태그가 더 이상 존재하지 않는 테이블에서 classification : unverified 중요한 열을 마스킹하는 열 마스크 정책을 만듭니다.
  4. 데이터 관리자가 분류를 완료하면 태그를 업데이트합니다. 차단 정책이 더 이상 일치하지 않으며 마스킹 정책이 적용됩니다.
-- Block access to unverified tables for all non-admin users
CREATE FUNCTION catalog.schema.block_all() RETURNS BOOLEAN
  RETURN FALSE;

CREATE POLICY block_unverified
ON CATALOG my_catalog
ROW FILTER catalog.schema.block_all
TO `account users` EXCEPT `data_admins`
FOR TABLES
WHEN has_tag_value('classification', 'unverified');

중요한 데이터를 분류한 후 보호하려면, classification : unverified 태그가 더 이상 없을 때 적용이 시작되는 열 마스크 정책을 정의하십시오.

CREATE FUNCTION catalog.schema.mask_pii(val STRING)
RETURNS STRING
RETURN '***';

CREATE POLICY mask_reviewed_pii
ON CATALOG my_catalog
COLUMN MASK catalog.schema.mask_pii
TO `account users`
EXCEPT `data_admins`
FOR TABLES
WHEN NOT has_tag_value('classification', 'unverified')
MATCH COLUMNS (has_tag_value('pii', 'name') OR has_tag_value('pii', 'address')) AS m
ON COLUMN m;

regex 없이 부분 표시

regex 대신 문자열 작업을 사용하여 중요한 값의 일부를 표시합니다. Regex 기반 마스킹은 큰 텍스트 필드에 비용이 많이 드는 모든 행에 대한 전체 값을 검색합니다( 큰 텍스트 필드에서 regex 마스킹 방지 참조).

CREATE FUNCTION mask_ssn(ssn STRING, show_last INT) RETURNS STRING
DETERMINISTIC
  RETURN CONCAT('***-**-', RIGHT(ssn, show_last));

일관된 해시(결정적 가명화)

일관된 해시(결정적 가명화라고도 함)는 중요한 데이터를 여러 테이블에서 동일한 해시된 값으로 바꿉니다. 함수를 표시하면 DETERMINISTIC 함수가 항상 동일한 입력에 대해 동일한 결과를 반환하므로 쿼리를 최적화하는 데 도움이 됩니다. 결정적이고 오류로부터 안전한 식 사용을 참조하세요.

다음 함수는 문자열 값을 일관되게 해시하고 매개 변수를 version 사용하여 키 회전을 지원합니다. 정책의 version 조항을 통해 USING COLUMNS 숫자를 증가시켜 이전 버전을 사용한 기록 데이터를 중단하지 않고 새 해시를 생성합니다. 이 함수는 해시하기 전에 원래 값을 버전 번호와 연결하므로 동일한 버전의 동일한 입력은 항상 동일한 해시를 생성합니다.

CREATE FUNCTION pseudonymize(val STRING, version INT) RETURNS STRING
DETERMINISTIC
  RETURN SHA2(CONCAT(val, CAST(version AS STRING)), 256);

쿼리하는 사용자의 속성을 기반으로 열을 마스킹합니다

Important

ABAC 정책의 신원 속성은 베타 버전입니다. 이를 사용하려면 계정 관리자가 계정 콘솔 리뷰 페이지에서 ABAC 정책 미리보기에서 신원 속성을 활성화해야 합니다. 계정 수준 미리 보기 관리를 참조하세요.

컬럼 마스크 정책은 쿼리 사용자의 신원 속성을 사용하여 전용 그룹이 필요하지 않고도 민감한 데이터를 마스킹할 수 있습니다. 예를 들어, department = HR이 있는 사용자에게는 데이터를 마스킹되지 않은 상태로 유지하고 다른 모든 사용자에게는 마스킹할 수 있습니다.

이러한 패턴은 신원 제공자로부터 사용자에게 식별 속성을 할당해야 하며, 기능들은 태그 전용 조건과 다르게 행동하여 정책 작성 방식에 영향을 미칩니다. 사용하기 전에 Identity 속성 함수identity 속성을 검토하세요.

Important

함수들은 사용자가 속성에 대한 값을 갖지 못하거나 속성 키가 존재하지 않을 때 해결 false 됩니다. 이 결과가 접근을 허용하는 것이 아니라 제한하도록 조건 false 을 작성하세요. 속성이 일치할 때를 제외하고 마스크가 적용되도록 NOT 일치를 부정하세요. 예를 들어, WHEN NOT has_identity_attribute_value('department', 'HR')은(는) 부서가 HR인 사용자를 제외한 모든 사용자에 대해 해당 열을 마스킹하며, 누락된 값도 false이므로 부서 속성이 없는 사용자 역시 마스킹됩니다. 그 반대는 피하세요. 속성 값이 일치할 때만 마스킹하는 조건을 사용하면 해당 속성에 값이 없는 사용자는 마스킹되지 않은 상태로 남게 됩니다.

평가 동작에 대해서는 정체성 속성 조건을 참조하세요. 제한 사항은 정책 조건에서의 정체성 속성을 참조하세요.

고정 값을 매칭하세요

학과가 아닌 HR모든 사람을 위한 마스크 착용:ssn

CREATE FUNCTION hr_catalog.people.mask_ssn(s STRING) RETURNS STRING RETURN '***-**-****';

CREATE OR REPLACE POLICY mask_ssn_non_hr
ON SCHEMA hr_catalog.people
COLUMN MASK hr_catalog.people.mask_ssn
TO `account users`
FOR TABLES
WHEN NOT has_identity_attribute_value('department', 'HR')
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn_col
ON COLUMN ssn_col;

이 예시에서, 부서 HR 소속 사용자는 실제 가치를 봅니다. 다른 부서의 사용자와 부서 속성이 없는 사용자 모두 마스크를 볼 수 있습니다.

관리되는 태그와 일치 여부 확인

앞서 예시는 정책 내에서 특정 속성 값(HR)을 명명하므로, 여러 부서를 커버하려면 각 부서별로 별도의 정책을 작성해야 합니다. 모든 부서를 단일 정책으로 커버하려면 각 테이블을 소유한 부서로 태그한 후, 쿼리 사용자의 department 속성을 해당 태그와 비교하세요. 이 열은 사용자의 부서가 테이블 값과 dept_tag 일치할 때만 드러납니다:

CREATE FUNCTION prod.sales.mask_ssn(s STRING) RETURNS STRING RETURN '***-**-****';

CREATE OR REPLACE POLICY mask_unless_dept_matches
ON SCHEMA prod.sales
COLUMN MASK prod.sales.mask_ssn
TO `account users`
FOR TABLES
WHEN NOT has_identity_attribute_tag_match('department', 'dept_tag')
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn_col
ON COLUMN ssn_col;

속성 키와 값은 모두 대소문자를 구분하며, 값은 정확히 일치해야 합니다. 즉, Financefinance는 일치하지 않습니다.

사용자를 대신해 행동하는 외부 에이전트의 접근 제한

Important

ABAC 정책의 컨텍스트 속성은 베타 버전입니다. 이를 사용하려면 계정 관리자가 계정 콘솔 리뷰 페이지에서 UC ABAC 컨텍스트 속성 미리보기를 활성화해야 합니다. 계정 수준 미리 보기 관리를 참조하세요.

컨텍스트 속성은 OAuth 애플리케이션을 통해 사용자가 대신 요청할 때 데이터 접근을 제한하는 데 사용할 수 있습니다. 에이전트가 OAuth로 연결되어 있다면, 사용자가 워크스페이스에서 직접 데이터를 읽을 수 있음에도 불구하고, 에이전트가 사용자를 대신해 행동할 때 데이터에 접근하지 못하도록 이 설정을 사용할 수 있습니다.

Azure Databricks CLI, SDK 또는 SQL Statement Execution API를 통한 OAuth로 인증된 모든 액세스는 사용자가 수동으로 쿼리하는 경우에도 request.is_on_behalf_of'true'(으)로 설정합니다. 개인 액세스 토큰(PAT)으로 인증된 접근은 그렇지 않습니다. 이 메커니즘으로는 Genie 액세스를 처리할 수 없습니다. 'true'을(를) request.is_on_behalf_of로 설정하지 않기 때문입니다.

이 패턴들은 컨텍스트 속성 함수를 사용합니다. 사용 가능한 속성과 동작에 대해서는 Context 속성 함수(베타)를 참조하세요.

컨텍스트 속성을 보내는 에이전트를 설정하세요

컨텍스트 속성을 사용하려면 맞춤형 OAuth 애플리케이션을 사용해 에이전트를 Azure Databricks에 연결하세요:

  1. 계정 관리자가 계정 콘솔에서 UC ABAC 컨텍스트 속성 미리보기를 활성화합니다. Azure Databricks 미리 보기 관리를 참조하세요.
  2. 계정 관리자는 계정 콘솔에서 커스텀 OAuth 애플리케이션을 등록하고 클라이언트 ID를 기록합니다. 파트너 OAuth 애플리케이션 사용 또는 사용 안 함을 참조 하세요.
  3. 해당 OAuth 애플리케이션을 통해 Azure Databricks가 관리하는 MCP에 에이전트를 연결하세요. OAuth 인증을 이용한 Connect client를 참조하세요.

내장 databricks-cli 클라이언트를 사용하는 에이전트는 여전히 OAuth를 통해 인증하므로 request.is_on_behalf_of'true'를 읽습니다. 하지만 두 경우 모두 클라이언트 ID를 databricks-cli 공유하기 때문에 CLI의 요청과 수동 사용을 구분할 수 없습니다. 특정 애플리케이션을 관리하려면 맞춤형 OAuth 애플리케이션을 등록하고 에이전트를 통해 연결합니다.

OAuth 개념에 대해서는 Authorize user access to Azure Databricks with OAuth를 참조하세요.

Warning

보험 약관이 보장하지 않는 경로를 통해 상담원이 데이터에 접근할 수 없도록 하세요:

  • 만약 에 따라 request.is_on_behalf_of접근 권한을 제한한다면, 에이전트가 PAT로 인증할 수 없도록 하세요. PAT는 request.is_on_behalf_of'true'(으)로 설정하지 않으므로, 해당 속성에 대한 조건은 그 속성을 제한하지 않습니다.
  • request.client_id을 기준으로 액세스를 제한하는 경우, 일반 databricks-cli 클라이언트처럼 해당 조건이 적용되지 않는 클라이언트를 통해 에이전트가 접속할 수 없도록 하세요.

대리 요청을 위한 열을 가리기

등록된 OAuth 애플리케이션을 통해 작동하는 에이전트와 같이 사용자를 대신해 실행되는 요청에 대한 마스크 ssn 사용, 그리고 직접 쿼리에 대해서는 마스크를 해제한 채 남겨두는 것:

CREATE FUNCTION hr_catalog.people.mask_ssn(s STRING) RETURNS STRING RETURN '***-**-****';

CREATE OR REPLACE POLICY mask_ssn_for_agents
ON SCHEMA hr_catalog.people
COLUMN MASK hr_catalog.people.mask_ssn
TO `account users`
FOR TABLES
WHEN has_context_attribute_value('request.is_on_behalf_of', 'true')
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn_col
ON COLUMN ssn_col;

이 예시에서는 직접 쿼리는 실제 값을 반환하고, 대리 요청은 마스킹된 값을 확인하게 됩니다. CLI와 SQL Statement Execution API를 사용하면 request.is_on_behalf_of'true'를 읽으므로, 이 정책은 해당 요청에서도 해당 열을 마스킹합니다. 대신 특정 애플리케이션을 대상으로 하려면 request.client_id을 해당 애플리케이션의 클라이언트 ID와 일치시키세요.

열을 승인된 신청서로 제한하세요

승인된 애플리케이션에서 온 요청(OAuth 클라이언트 ID로 식별됨)을 제외한 모든 외부 요청에 대해 마스크를 사용하세요 ssn :

CREATE OR REPLACE POLICY mask_ssn_unapproved_apps
ON SCHEMA hr_catalog.people
COLUMN MASK hr_catalog.people.mask_ssn
TO `account users`
FOR TABLES
WHEN NOT has_context_attribute_value('request.client_id', '<your-app-client-id>')
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn_col
ON COLUMN ssn_col;

어떤 애플리케이션이 요청을 했는지 확인하려면 감사 로그에서 해당 identity_metadata.acting_resource 필드를 확인해 보세요.

열 전용 조건자를 사용하여 행 필터링

테이블 열만 참조하는 간단한 부울 논리를 사용하여 행을 필터링합니다. 열 전용 조건자는 조건자 푸시다운을 사용하도록 설정하므로 검색 중에 엔진이 관련 없는 데이터를 건너뛸 수 있습니다( 보호된 테이블의 조건자 푸시다운 이해 참조).

CREATE FUNCTION filter_by_region(region STRING, allowed STRING)
RETURNS BOOLEAN
DETERMINISTIC
  RETURN array_contains(split(allowed, ','), lower(region));

허용된 지역을 상수로 전달하는 정책과 함께 사용합니다.

CREATE POLICY regional_access
ON CATALOG analytics
ROW FILTER filter_by_region
TO 'emea_team'
FOR TABLES
MATCH COLUMNS has_tag('region') AS rgn
USING COLUMNS (rgn, 'emea,apac');

여러 관련 열에서 행 필터링

테이블에 관련 특성을 나타내는 열이 여러 개 있는 경우(예 ship_to_countrybill_to_country: ) 별도의 태그 조건과 일치시키고 둘 다 단일 UDF에 전달할 수 있습니다. 이렇게 하면 각 열에 대해 별도의 정책을 만들지 않습니다. 정책은 절에 MATCH COLUMNS 최대 3개의 열 식을 포함할 수 있습니다(정책 할당량 참조).

CREATE FUNCTION filter_by_countries(ship_country STRING, bill_country STRING, allowed STRING)
RETURNS BOOLEAN
DETERMINISTIC
  RETURN array_contains(split(allowed, ','), lower(ship_country))
      OR array_contains(split(allowed, ','), lower(bill_country));

CREATE POLICY regional_orders
ON SCHEMA prod.orders
ROW FILTER filter_by_countries
TO analysts
FOR TABLES
WHEN has_tag_value('sensitivity', 'high')
MATCH COLUMNS
  has_tag('ship_country') AS ship,
  has_tag('bill_country') AS bill
USING COLUMNS (ship, bill, 'us,ca,mx');

분석가는 배송 또는 청구 국가가 허용 목록에 있는 주문만 확인합니다.

ABAC 정책 UDF의 조회 테이블

액세스 규칙은 사용자별로 다르며 정책 TO/EXCEPT 의 절만으로 표현할 수 없는 경우 작은 조회 테이블에 대한 액세스 권한을 확인할 수 있습니다. 가능한 경우 보안 주체를 대상으로 지정하는 기본 접근 방식이므로 사용합니다 TO/EXCEPT ( 보안 주체를 대상으로 하는 방법 참조). 최적화 프로그램에서 하위 쿼리를 브로드캐스트 해시 조인으로 변환하도록 조회 테이블을 작게 유지합니다( 조회 테이블 작게 유지 참조).

CREATE TABLE access_rules (
  principal VARCHAR(255),
  priority VARCHAR(64)
);

INSERT INTO access_rules VALUES
  ('alice@company.com', '1-URGENT'),
  ('alice@company.com', '2-HIGH'),
  ('bob@company.com', '1-URGENT');

CREATE FUNCTION priority_allowed(o_priority STRING) RETURNS BOOLEAN
RETURN EXISTS (
  SELECT 1 FROM access_rules
  WHERE principal = session_user() AND priority = o_priority
);

CREATE POLICY priority_filter
ON CATALOG operations
ROW FILTER priority_allowed
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag('priority') AS pri
USING COLUMNS (pri);