접근 제어 (RBAC, 시스템 역할, 데이터베이스 역할, 미래 권한)
Snowflake 접근 제어의 기본인 역할 기반 접근 제어(RBAC)와 소유권, 시스템 역할의 쓰임, 접근 역할과 기능 역할을 나누는 설계, 데이터베이스 역할, 미래 권한과 관리형 스키마, 보조 역할, 권한 감사 쿼리와 흔한 권한 오류를 정리합니다.
기본 모델
Snowflake 의 접근 제어는 역할(role)에 권한(privilege)을 주고, 사용자에게 역할을 주는 구조입니다. 사용자에게 직접 권한을 주지 않습니다 (예외로 사용자 역할 없이 쓰는 기능이 일부 있지만 기본 설계는 역할 중심입니다).
- 소유권(OWNERSHIP): 객체를 만든 역할이 소유자가 됩니다. 소유 역할은 그 객체의 모든 권한을 가지며, 권한을 다른 역할에 줄 수 있습니다.
- 역할 계층: 역할을 다른 역할에 주면 상위 역할이 하위 역할의 권한을 물려받습니다. 모든 사용자 정의 역할을 결국 SYSADMIN 아래에 매다는 것이 공식 권장입니다.
- 세션의 역할: 쿼리는 현재 세션의 주 역할(primary role) 과 보조 역할(secondary roles) 의 권한을 합쳐 실행됩니다. 단, 객체를 만들 때 소유권은 주 역할이 갖습니다.
시스템 역할
| 역할 | 쓰임 | 주의 |
|---|---|---|
| ORGADMIN | 조직 수준 작업 (계정 만들기, 조직 사용량) | 조직 계정 기능과 함께 쓰임 |
| ACCOUNTADMIN | 계정 최상위. 결제, 계정 설정 | 일상 작업에 쓰지 않음, 최소 두 명, MFA 필수 |
| SECURITYADMIN | 권한 부여 관리 (MANAGE GRANTS) | 사용자와 역할 관리 |
| USERADMIN | 사용자와 역할 만들기 | |
| SYSADMIN | 웨어하우스, 데이터베이스 같은 객체 만들기 | 사용자 정의 역할의 상위 |
| PUBLIC | 모든 사용자가 자동으로 가짐 | 여기에 준 권한은 전원에게 열림 |
주의 ACCOUNTADMIN 을 사용자의 기본 역할로 두지 마세요. 실수로 만든 객체의 소유권이 ACCOUNTADMIN 으로 가서 다른 역할이 관리하지 못하는 일이 흔합니다.
접근 역할과 기능 역할
규모가 커지면 두 층으로 나누는 설계가 관리하기 쉽습니다.
- 접근 역할(access role): "sales DB 읽기", "sales DB 쓰기" 처럼 객체 묶음에 대한 권한만 가집니다.
- 기능 역할(functional role): "영업 분석가", "데이터 엔지니어" 처럼 사람의 업무를 뜻하고, 접근 역할 여러 개를 받습니다. 사용자에게는 기능 역할만 줍니다.
USE ROLE USERADMIN;
CREATE ROLE sales_read; -- 접근 역할
CREATE ROLE sales_write;
CREATE ROLE analyst; -- 기능 역할
USE ROLE SECURITYADMIN;
GRANT USAGE ON DATABASE sales TO ROLE sales_read;
GRANT USAGE ON ALL SCHEMAS IN DATABASE sales TO ROLE sales_read;
GRANT SELECT ON ALL TABLES IN DATABASE sales TO ROLE sales_read;
GRANT SELECT ON FUTURE TABLES IN DATABASE sales TO ROLE sales_read;
GRANT SELECT ON FUTURE VIEWS IN DATABASE sales TO ROLE sales_read;
GRANT ROLE sales_read TO ROLE analyst;
GRANT USAGE ON WAREHOUSE bi_wh TO ROLE analyst;
GRANT ROLE analyst TO ROLE SYSADMIN; -- 계층에 매달기
GRANT ROLE analyst TO USER kim;
ALTER USER kim SET DEFAULT_ROLE = analyst DEFAULT_WAREHOUSE = bi_wh;데이터베이스 역할
데이터베이스 역할(database role)은 데이터베이스 안에 사는 역할입니다. 데이터베이스와 함께 복제되고 공유에 넣을 수 있어, 접근 역할을 데이터베이스 역할로 만들면 복제와 공유 때 권한 구조가 같이 따라갑니다.
CREATE DATABASE ROLE sales.reader;
GRANT USAGE ON SCHEMA sales.public TO DATABASE ROLE sales.reader;
GRANT SELECT ON ALL TABLES IN SCHEMA sales.public TO DATABASE ROLE sales.reader;
GRANT DATABASE ROLE sales.reader TO ROLE analyst;SNOWFLAKE.CORTEX_USER, SNOWFLAKE.AI_FUNCTIONS_USER 처럼 Snowflake 가 미리 만든 데이터베이스 역할도 같은 방식으로 받습니다.
미래 권한과 관리형 스키마
- 미래 권한(future grants):
GRANT ... ON FUTURE TABLES IN SCHEMA는 앞으로 만들어질 객체에 자동으로 권한을 줍니다. 스키마 수준 미래 권한이 있으면 같은 객체 종류의 데이터베이스 수준 미래 권한보다 우선합니다. 두 수준을 섞으면 "데이터베이스에 걸었는데 왜 안 되지" 가 생깁니다. - 관리형 접근 스키마(managed access schema):
CREATE SCHEMA ... WITH MANAGED ACCESS로 만들면 객체 소유자가 아니라 스키마 소유자(또는 MANAGE GRANTS 보유 역할)만 권한을 줄 수 있습니다. 권한이 여기저기서 새는 것을 막습니다.
CREATE SCHEMA sales.mart WITH MANAGED ACCESS;보조 역할
USE SECONDARY ROLES ALL; -- 내가 가진 모든 역할의 권한을 함께 씀
USE SECONDARY ROLES NONE; -- 주 역할만Snowflake 는 새 사용자의 기본 보조 역할을 ALL 로 바꾸는 방향으로 동작을 바꿔 왔습니다 (BCR 번들로 단계 적용). 편하지만 "어떤 역할 덕분에 이 쿼리가 됐는지" 가 흐려지므로, 서비스 사용자나 파이프라인은 DEFAULT_SECONDARY_ROLES = () 로 명시하는 편이 안전합니다.
권한 감사
SHOW GRANTS TO ROLE analyst; -- 역할이 가진 권한
SHOW GRANTS OF ROLE analyst; -- 이 역할을 받은 사용자, 역할
SHOW GRANTS ON TABLE sales.public.orders;
SHOW FUTURE GRANTS IN SCHEMA sales.public;
-- ACCOUNTADMIN 을 가진 사용자 (지연 있음)
SELECT grantee_name, created_on
FROM snowflake.account_usage.grants_to_users
WHERE role = 'ACCOUNTADMIN' AND deleted_on IS NULL;ACCOUNT_USAGE 의 권한 뷰는 최대 2시간 정도 늦게 반영되므로, 방금 바꾼 권한은 SHOW GRANTS 로 확인합니다. Trust Center 의 보안 점검도 과도한 ACCOUNTADMIN 부여를 경고합니다.
흔한 실수
| 실수 | 결과 | 바로잡기 |
|---|---|---|
| 테이블 SELECT 만 주고 DB, 스키마 USAGE 를 빠뜨림 | 객체가 안 보임 | 세 단계(DB USAGE, 스키마 USAGE, 객체 권한)를 한 묶음으로 |
| 웨어하우스 USAGE 를 안 줌 | 쿼리를 실행할 수 없음 | 기능 역할에 웨어하우스 USAGE |
| PUBLIC 에 권한을 줌 | 전 사용자에게 열림 | PUBLIC 에서 회수 |
| 개인 역할로 운영 객체 생성 | 퇴사 시 소유권 문제 | 운영 객체는 서비스 역할이 소유, GRANT OWNERSHIP ... COPY CURRENT GRANTS 로 이전 |
트러블슈팅
증상: "SQL compilation error: Object 'SALES.PUBLIC.ORDERS' does not exist or not authorized." 가 납니다.
원인: 객체가 정말 없거나, 현재 역할이 DB 또는 스키마 USAGE, 테이블 SELECT 중 하나를 갖지 않았습니다. Snowflake 는 권한이 없을 때도 "존재하지 않음" 으로 답합니다.
해결:
SELECT CURRENT_ROLE(), CURRENT_SECONDARY_ROLES();로 역할을 확인하고,SHOW GRANTS TO ROLE로 세 단계 권한을 점검합니다.증상: 새로 만든 테이블만 다른 팀이 못 읽습니다.
원인: 미래 권한이 없거나 스키마 수준 미래 권한이 데이터베이스 수준을 가렸습니다.
해결:
SHOW FUTURE GRANTS IN SCHEMA로 확인하고, 이미 만든 테이블은GRANT ... ON ALL TABLES로 따로 채웁니다.