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

이 페이지에서는 ABAC 행 필터 및 열 마스크 정책을 구현하기 위한 일반적인 패턴을 설명합니다. 전반적인 개념은 ABAC(특성 기반 액세스 제어)에 대한 핵심 개념을 참조하세요. 정책 구문은 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 사용하여 키 회전을 지원합니다. 정책의 USING COLUMNS 조항을 통해 version 숫자를 증가시켜 이전 버전을 사용한 기록 데이터를 중단하지 않고 새 해시를 생성합니다. 이 함수는 해시하기 전에 원래 값을 버전 번호와 연결하므로 동일한 버전의 동일한 입력은 항상 동일한 해시를 생성합니다.

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

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

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

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);