행 액세스 정책 사용하기¶
이 항목에서는 행 액세스 정책의 구현에 대해 소개합니다.
이 항목의 내용:
행 액세스 정책 구현하기¶
다음 하위 섹션에서는 행 액세스 정책 구현 방법에 대한 두 가지 예를 제시합니다.
매핑 테이블 조회를 사용하는 일반적인 행 액세스 정책.
쿼리 성능을 높이기 위해 기존 행 액세스 정책 하위 쿼리를 메모이제이션 가능 함수로 바꾸기.
예: 매핑 테이블 조회¶
행 액세스 정책 권한을 구성하고 테이블 및 뷰에 행 액세스 정책을 추가하는 대표적인 지침은 다음과 같습니다.
이러한 단계에서는 다음을 가정합니다.
관리 방식은 중앙 집중식입니다.
행 액세스 정책 사용 사례에 하이브리드 또는 분산형 관리 방식이 포함된 경우, 행 액세스 정책 관리하기 에서 역할 및 권한의 대표적인 배포를 참조하십시오.
대표적인 사용 사례: 매핑 테이블을 사용하여 쿼리 결과 필터링 에서와 유사하게, 매핑 테이블이 필요합니다.
다음 단계에서는 CURRENT_ROLE 컨텍스트 함수를 사용하여 사용자가 쿼리 결과에서 행을 볼 수 있는지 여부를 확인하며, 대표적인 사용 사례에서는 사용자의 이름(즉, CURRENT_USER)에 대해 중점적으로 알아봅니다.
역할 활성화와 역할 계층 구조가 중요한 경우 정책 조건이 IS_ROLE_IN_SESSION 컨텍스트 함수를 사용하는 것이 좋습니다. 정책 예제는 IS_ROLE_IN_SESSION 함수의 예 섹션을 참조하십시오.
컨텍스트 함수가 다른 경우에도 매핑 테이블을 사용하여 행 액세스 정책을 구현하는 전체 프로세스는 동일하게 유지됩니다.
SECURITYADMIN 시스템 역할은 행 액세스 정책을 관리 및 구현하도록 사용자 지정 역할에 권한을 부여합니다.
프로덕션 환경에서 낮은 권한의 사용자 지정(즉,
database_admin
또는finance_admin
)을 위해 더 높은 권한의 역할(즉, SECURITYADMIN 또는 ACCOUNTADMIN)을 사용하지 않으려면, 낮은 권한의 역할에 행 액세스 정책을 관리 및 구현하기 위한 권한이 있는지 확인하십시오.자세한 내용은 행 액세스 정책 권한 및 DDL 명령, 작업 및 권한 요약 섹션을 참조하십시오.
행 액세스 정책으로 보호할 테이블을 만드는 단계(1단계)와 테이블에 행 액세스 정책을 추가하는 단계(5단계)가 따로 있습니다. 행 액세스 정책이 이미 존재한다고 가정하고 테이블 생성 시 테이블에 행 액세스 정책을 추가할 수 있습니다. 구문에 대한 자세한 내용은 CREATE TABLE 섹션을 참조하십시오.
1단계: 데이터를 위한 테이블 만들기¶
판매 데이터를 위한 테이블을 생성합니다.
CREATE TABLE sales (
customer varchar,
product varchar,
spend decimal(20, 2),
sale_date date,
region varchar
);
2단계: 매핑 테이블 및 사용자 지정 역할 만들기 및 SELECT 권한 부여¶
대표적인 예 에서와 같이 security
스키마에서 매핑 테이블을 생성합니다. 이 테이블은 sales
테이블의 영업 관리자가 볼 수 있는 행을 정의합니다.
CREATE TABLE security.salesmanagerregions ( sales_manager varchar, region varchar );
다음으로, 보안 관리자는 mapping_role
사용자 지정 역할을 생성하고 사용자 지정 역할에 SELECT 권한을 부여합니다. 이 권한을 통해 사용자 지정 역할을 보유한 사용자는 매핑 테이블을 쿼리할 수 있습니다.
USE ROLE SECURITYADMIN; CREATE ROLE mapping_role; GRANT SELECT ON TABLE security.salesmanagerregions TO ROLE mapping_role;
3단계: 행 액세스 정책 만들기¶
스키마 소유자 역할로, 다음 조건 2개가 적용된 행 액세스 정책을 생성합니다.
sales_executive_role
사용자 지정 역할을 보유한 사용자는 모든 행을 볼 수 있습니다.sales_manager
사용자 지정 역할을 보유한 사용자는salesmanagerregions
매핑 테이블에 따라 행을 볼 수 있습니다.
스키마 소유자 역할에는 자동으로 CREATE ROW ACCESS POLICY 권한이 부여됨에 유의하십시오. 다른 역할이 행 액세스 정책을 생성할 수 있어야 하는 경우, 스키마 소유자 역할은 다른 역할에 CREATE ROW ACCESS 정책 권한을 부여할 수 있습니다.
use role SCHEMA_OWNER_ROLE;
CREATE OR REPLACE ROW ACCESS POLICY security.sales_policy
AS (sales_region varchar) RETURNS BOOLEAN ->
'sales_executive_role' = CURRENT_ROLE()
OR EXISTS (
SELECT 1 FROM salesmanagerregions
WHERE sales_manager = CURRENT_ROLE()
AND region = sales_region
)
;
여기서
security.sales_policy
Security
스키마에서 행 액세스 정책의 이름입니다.AS (sales_region varchar)
행 액세스 정책을 위한 서명입니다.
서명은 매핑 테이블 속성 및 데이터 타입을 지정합니다. 반환된 값에 따라 행 액세스 정책이 추가된 테이블 또는 뷰에서 지정된 행에 대한 액세스 권한이 사용자에게 있는지 여부가 결정됩니다.
RETURNS BOOLEAN ->
행 액세스 정책의 적용을 지정합니다.
행 액세스 정책의
expression
은 오른쪽 화살표 바로 다음에 나옵니다(즉,->
).이 식은 부울 값으로 된 임의의 SQL 식일 수 있습니다. Snowflake는 UDFs, 외부 함수, 하위 쿼리를 사용하는 식을 호출하는 식을 지원합니다.
'sales_executive_role' = CURRENT_ROLE()
sales_executive_role
사용자 지정 역할을 보유한 사용자가 데이터를 볼 수 있도록 허용하는 행 액세스 정책 식의 첫 번째 조건입니다.OR EXISTS (select 1 from salesmanagerregions WHERE sales_manager = CURRENT_ROLE() AND region = sales_region)
하위 쿼리를 사용하는 행 액세스 정책 식의 두 번째 조건입니다.
{salesmanagerregions}
매핑 테이블에 나열된 리전을 지정하려면 하위 쿼리에서 CURRENT_ROLE이 데이터에 대해 실행된 쿼리가 있는sales_manager
사용자 지정 역할이어야 합니다.
팁
정책으로 보호되는 테이블에서 쿼리 성능을 높이려면 EXISTS
절의 매핑 테이블 조회 하위 쿼리를 메모이제이션 가능 함수 로 바꾸십시오.
자세한 내용은 (이 항목에서) 메모이제이션 가능 함수 예 를 참조하십시오.
4단계: 사용자 지정 역할에 권한 부여¶
SECURITYADMIN 시스템 역할을 사용하여 다음 문 2개를 실행합니다.
GRANT OWNERSHIP ON ROW ACCESS POLICY security.sales_policy TO mapping_role;
GRANT APPLY ON ROW ACCESS POLICY security.sales_policy TO ROLE sales_analyst_role;
이러한 두 GRANT <권한> 문의 효과는 다음과 같습니다.
정책의 소유권이 SECURITYADMIN 시스템 역할에 없습니다. 쿼리 런타임 시점에는 더 많은 권한을 보유한 SECURITYADMIN 시스템 역할이 아닌 소유자 권한 으로 정책이 실행되기 때문에 Snowflake는 사용자 지정 역할에 부여된 권한을 사용합니다. 이러한 방식은 Principle of Least Privilege를 지원합니다.
sales_analyst_role
사용자 지정 역할은 필요에 따라 테이블에 행 액세스 정책을 추가하거나 삭제할 수 있습니다.
5단계: 테이블에 행 액세스 정책 추가¶
Snowflake의 모든 테이블 또는 뷰는 한 번에 최대 1개의 행 액세스 정책을 지원할 수 있습니다.
Sales
데이터 테이블의 리전 열에 행 액세스 정책을 추가(즉, 바인딩)합니다.
USE ROLE SECURITYADMIN;
ALTER TABLE sales ADD ROW ACCESS POLICY security.sales_policy ON (region);
6단계: 보호되는 테이블 데이터를 역할이 쿼리하도록 허용¶
보호되는 sales
데이터에 대한 SELECT 권한을 sales_manager_role
사용자 지정 역할에 부여합니다.
GRANT SELECT ON TABLE sales TO ROLE sales_manager_role;
7단계: 정책 테스트¶
판매 데이터가 Sales
데이터로 채워지면, 행 액세스 정책을 테스트합니다.
USE ROLE sales_manager_role;
SELECT product, SUM(spend)
FROM sales
WHERE YEAR(sale_date) = 2020
GROUP BY product;
예: 정책 하위 쿼리를 메모이제이션 가능 함수로 바꾸기¶
이 예에 나와 있는 단계에 따라 행 액세스 정책 조건에서 각 매핑 테이블 조회에 대해 메모이제이션 가능 함수 를 생성합니다. 각 EXISTS
절의 하위 쿼리는 테이블 이름이 각각 regions
, customers
, products
인 매핑 테이블 조회를 지정합니다.
CREATE OR REPLACE ROW ACCESS POLICY rap_NO_memoizable_function AS (region_id number, customer_id number, product_id number) RETURNS BOOLEAN -> EXISTS(SELECT 1 FROM regions WHERE id = region_id) OR EXISTS(SELECT 1 FROM customers WHERE id = customer_id) OR EXISTS(SELECT 1 FROM products WHERE id = product_id) ;
이후의 단계에서는 rap_admin
사용자 지정 역할이 행 액세스 정책을 생성할 수 있다고 가정합니다(즉, SCHEMA에서 CREATE ROW ACCESS POLICY 권한이 있음).
각각의 행 액세스 정책 매핑 테이블 조회를 메모이제이션 가능 함수로 바꾸려면 다음 단계를 완료하십시오.
메모이제이션 가능 함수를 관리하기 위해
functions_admin
이라는 사용자 지정 역할을 만듭니다.USE ROLE USERADMIN; CREATE ROLE functions_admin;
functions_admin
역할에 다음 권한을 부여하여governance.functions
라는 기존 스키마에서 메모이제이션 가능 함수를 만들 수 있도록 합니다.USE ROLE SECURITYADMIN; GRANT USAGE ON DATABASE governance TO ROLE functions_admin; GRANT USAGE ON SCHEMA governance.functions TO ROLE functions_admin; GRANT CREATE FUNCTION ON SCHEMA governance.functions TO ROLE functions_admin;
행 액세스 정책의 각
EXISTS
하위 쿼리 절에 대해 메모이제이션 가능 함수를 만듭니다. 각각의 메모이제이션 가능 함수 정의는 동일한 형식을 취합니다. 간결성을 위해 함수 예는 하나만 표시됩니다.USE ROLE functions_admin; USE SCHEMA governance.functions; CREATE OR REPLACE function allowed_regions() RETURNS array memoizable AS 'SELECT ARRAY_AGG(id) FROM regions';
CREATE ROW ACCESS POLICY 문을 사용하여 하위 쿼리를 메모이제이션 가능 함수로 바꾸는 새로운 행 액세스 정책을 정의합니다.
새로운 행 액세스 정책을 사용하면 정책에서 메모이제이션 가능 함수를 사용하거나 사용하지 않을 때 보호된 테이블에서 쿼리를 테스트하여 정책 조건에 메모이제이션 가능 함수를 사용할 때 성능에 미치는 영향을 정량화할 수 있습니다.
USE ROLE rap_admin; CREATE OR REPLACE ROW ACCESS POLICY rap_with_memoizable_function AS (region_id number, customer_id number, product_id number) RETURNS BOOLEAN -> ARRAY_CONTAINS(region_id, allowed_regions()) OR ARRAY_CONTAINS(customer_id, allowed_customers()) OR ARRAY_CONTAINS(product_id, allowed_products()) ;