네트워크 보안 (네트워크 규칙과 정책, PrivateLink, 외부 접근)
들어오는 연결을 제한하는 네트워크 규칙과 네트워크 정책, 클라우드 사설 연결(AWS PrivateLink, Azure Private Link, GCP Private Service Connect), 사설 연결만 허용하기, 내부 스테이지 접근 제한, 함수와 노트북이 밖으로 나가는 외부 접근 통합, 암호화와 Tri-Secret Secure 를 정리합니다.
두 방향을 나눠 생각합니다
| 방향 | 무엇을 막나 | 도구 |
|---|---|---|
| 들어오는 연결 (ingress) | 누가 어디서 Snowflake 에 접속하나 | 네트워크 규칙 + 네트워크 정책, 사설 연결 |
| 내부 스테이지 접근 | 스테이지 파일을 어느 네트워크에서 올리고 내리나 | 네트워크 규칙(INTERNAL_STAGE), 사설 연결 |
| 나가는 연결 (egress) | UDF, 프로시저, 노트북이 어느 외부 주소로 나가나 | 네트워크 규칙(EGRESS) + 외부 접근 통합 |
네트워크 규칙과 정책
네트워크 규칙(network rule) 은 "어떤 주소 목록" 을 담는 스키마 객체이고, 네트워크 정책(network policy) 은 규칙을 허용 목록, 차단 목록으로 묶어 계정이나 사용자에 거는 객체입니다. 예전처럼 정책에 IP 를 직접 적는 방식(ALLOWED_IP_LIST)도 동작하지만, 공식 권장은 규칙을 쓰는 방식입니다.
USE ROLE SECURITYADMIN;
CREATE DATABASE IF NOT EXISTS sec;
CREATE SCHEMA IF NOT EXISTS sec.net;
CREATE NETWORK RULE sec.net.office_ips
MODE = INGRESS TYPE = IPV4
VALUE_LIST = ('203.0.113.0/24', '198.51.100.10');
CREATE NETWORK RULE sec.net.corp_vpce
MODE = INGRESS TYPE = AWSVPCEID
VALUE_LIST = ('vpce-0abc123def4567890');
CREATE NETWORK POLICY corp_access
ALLOWED_NETWORK_RULE_LIST = ('sec.net.office_ips', 'sec.net.corp_vpce');
-- 먼저 내 세션 IP 가 허용되는지 확인한 뒤 계정에 적용
SELECT CURRENT_IP_ADDRESS();
ALTER ACCOUNT SET NETWORK_POLICY = corp_access;
-- 서비스 사용자에게 더 좁은 정책
CREATE NETWORK POLICY etl_only ALLOWED_NETWORK_RULE_LIST = ('sec.net.etl_ips');
ALTER USER etl_svc SET NETWORK_POLICY = etl_only;- 사용자에 건 정책이 계정 정책보다 우선합니다.
- 규칙 종류(TYPE):
IPV4,AWSVPCEID,AZURELINKID,HOST_PORT,PRIVATE_HOST_PORT등. 모드(MODE):INGRESS,INTERNAL_STAGE,EGRESS등. - 허용 목록에 하나도 해당하지 않으면 차단입니다. 차단 목록이 허용 목록보다 우선합니다.
- PAT 를 쓰는 서비스 사용자는 네트워크 정책이 반드시 있어야 합니다.
주의 계정 정책을 걸기 전에 내 현재 IP 가 포함됐는지 꼭 확인하세요. 잘못 걸면 관리자도 잠깁니다. 계정 정책은 ACCOUNTADMIN 이나 SECURITYADMIN 이 다른 허용된 네트워크에서만 되돌릴 수 있습니다.
사설 연결
| 클라우드 | 서비스 | 필요한 에디션 |
|---|---|---|
| AWS | AWS PrivateLink | Business Critical 이상 |
| Azure | Azure Private Link | Business Critical 이상 |
| Google Cloud | Private Service Connect | Business Critical 이상 |
사설 연결을 쓰면 클라이언트 트래픽이 공용 인터넷 대신 클라우드 내부망으로 Snowflake 에 닿습니다. 계정마다 사설 연결용 URL(privatelink 가 들어간 호스트 이름)이 따로 있고, DNS 를 그 이름으로 풀리게 설정해야 합니다.
SELECT SYSTEM$GET_PRIVATELINK_CONFIG(); -- 사설 연결 호스트 이름과 설정 값
SELECT SYSTEM$ALLOWLIST_PRIVATELINK(); -- 방화벽에 열어야 할 호스트2026년 2월 24일 계정 접속을 사설 연결로만 강제하는 기능이 GA 가 되었습니다. 공용 엔드포인트를 막으면 사설 연결이 아닌 경로는 네트워크 정책과 상관없이 차단됩니다. 정확한 매개변수 이름과 예외 처리(Snowsight, 파트너 연결 등)는 공식 문서를 확인하고 적용합니다.
내부 스테이지
사설 연결을 써도 내부 스테이지 파일은 클라우드 스토리지 주소로 오갑니다. AWS 에서는 S3 용 사설 연결을 따로 설정하고, INTERNAL_STAGE 모드 네트워크 규칙으로 내부 스테이지 접근을 특정 VPC 엔드포인트로 좁힐 수 있습니다.
나가는 연결: 외부 접근 통합
UDF, 저장 프로시저, Notebooks, Snowpark Container Services 는 기본적으로 인터넷에 나갈 수 없습니다. 외부 API 를 부르려면 다음 세 가지를 만듭니다.
CREATE NETWORK RULE sec.net.weather_api
MODE = EGRESS TYPE = HOST_PORT
VALUE_LIST = ('api.weather.example.com:443');
CREATE SECRET sec.net.weather_key TYPE = GENERIC_STRING SECRET_STRING = '***';
CREATE EXTERNAL ACCESS INTEGRATION weather_eai
ALLOWED_NETWORK_RULES = (sec.net.weather_api)
ALLOWED_AUTHENTICATION_SECRETS = (sec.net.weather_key)
ENABLED = TRUE;
CREATE OR REPLACE FUNCTION util.get_weather(city STRING)
RETURNS VARIANT LANGUAGE PYTHON RUNTIME_VERSION = '3.11'
HANDLER = 'run' PACKAGES = ('requests')
EXTERNAL_ACCESS_INTEGRATIONS = (weather_eai)
SECRETS = ('key' = sec.net.weather_key)
AS $$
import _snowflake, requests
def run(city):
k = _snowflake.get_generic_secret_string('key')
return requests.get('https://api.weather.example.com/v1', params={'q': city, 'key': k}).json()
$$;- 비밀 값은
SECRET객체에 두고 코드에 적지 않습니다. - 호스트는 와일드카드보다 정확한 이름을 씁니다. 나가는 트래픽도 감사 대상입니다.
암호화
- 모든 데이터는 저장 시 AES-256 으로 암호화되고, 키는 계층형으로 관리되며 주기적으로 교체됩니다. 전송 구간은 TLS 1.2 이상입니다.
- Tri-Secret Secure (Business Critical 이상)는 고객이 클라우드 KMS 에 가진 키와 Snowflake 키를 합쳐 복합 마스터 키를 만듭니다. 고객이 키를 끊으면 Snowflake 도 데이터를 읽지 못합니다.
- 주기적 재암호화(periodic rekeying)는 Enterprise 이상에서 켤 수 있습니다.
점검 목록
| 항목 | 확인 방법 |
|---|---|
| 계정에 네트워크 정책이 있나 | SHOW PARAMETERS LIKE 'NETWORK_POLICY' IN ACCOUNT; |
| 서비스 사용자마다 좁은 정책이 있나 | SHOW USERS 와 DESC USER |
| 정책 차단 로그인 | LOGIN_HISTORY 의 오류 메시지 |
| 외부 접근 통합 목록 | SHOW INTEGRATIONS LIKE '%EAI%'; |
| 권장 설정 위반 | Trust Center 의 보안 스캐너 |
트러블슈팅
증상: 네트워크 정책을 건 뒤 BI 도구가 "Incoming request with IP/Token ... is not allowed to access Snowflake" 로 실패합니다.
원인: BI 서버의 나가는 IP(NAT 게이트웨이 주소)가 허용 규칙에 없습니다. 사설 연결을 쓰는 경우 VPC 엔드포인트 ID 가 규칙에 없습니다.
해결:
LOGIN_HISTORY의client_ip로 실제 출발 IP 를 확인해 규칙에 넣습니다. 사설 연결이라면AWSVPCEID규칙을 추가합니다.증상: Python UDF 에서 외부 API 를 부르면 연결 시간 초과가 납니다.
원인: 함수에 외부 접근 통합을 붙이지 않았거나, 규칙의 호스트, 포트가 실제 요청과 다릅니다 (리다이렉트되는 호스트 포함).
해결:
EXTERNAL_ACCESS_INTEGRATIONS를 확인하고, 리다이렉트 대상 호스트까지 규칙에 넣습니다.