dbt Core × Snowflakeにおける本番データガバナンスとタグベースマスキングの実装設計
はじめに
こんにちは、NKKTech Global 技術チームです。
Snowflakeとdbt Coreを組み合わせたデータパイプライン運用において、多くのセキュリティ担当者が直面する「落とし穴」があります。
- 「Snowflake側でせっかくカラムにマスキングポリシーを付与したのに、dbt runが走ったらテーブルが再作成されてポリシーが剥がれてしまった」
- 「新しいテーブルやカラムが追加されるたびに、手動でSQLを叩いてマスキングを再設定しており、ヒューマンエラーによる情報漏洩(PII漏洩)のリスクが放置されている」
これを根本から解決するのが、Snowflakeの**オブジェクトタグ(Object Tagging)とタグベースマスキングポリシー(Tag-based Masking Policy)**です。
カラム自体ではなく「タグ」に対してマスキングルールを紐付け、dbt側からはYAMLのメタデータ定義を通じてタグを宣言することで、テーブルが何度再作成されても100%自動でマスキングが再適用される仕組みを構築できます。
1. タグベースマスキングの全体アーキテクチャ
dbtのYAMLファイルで宣言されたセキュリティ分類(meta)が、dbtマクロを通じてSnowflakeのタグに変換され、Snowflakeエンジンが動的にマスキングを発動します。
2. 【ステップ1】Snowflake側の事前準備(タグとポリシー作成)
まず、Snowflakeのセキュリティ管理者ロール(ACCOUNTADMIN または SECURITYADMIN)で、中央集権型のガバナンスオブジェクトを作成します。
-- 1. ガバナンス専用データベース・スキーマの作成
CREATE DATABASE IF NOT EXISTS GOVERNANCE_DB;
CREATE SCHEMA IF NOT EXISTS GOVERNANCE_DB.POLICIES;
USE SCHEMA GOVERNANCE_DB.POLICIES;
-- 2. セキュリティタグの定義
CREATE OR REPLACE TAG pii_type
ALLOWED_VALUES 'email', 'name', 'phone', 'financial'
COMMENT = '個人情報および機密データの分類タグ';
-- 3. メールアドレス用マスキングポリシーの作成
CREATE OR REPLACE MASKING POLICY mask_email AS (val string)
RETURNS string ->
CASE
-- PII閲覧許可ロールの場合は平文表示
WHEN CURRENT_ROLE() IN ('ACCOUNTADMIN', 'SECURITY_ADMIN', 'HR_RESTRICTED_ROLE') THEN val
-- それ以外のロールは先頭とドメインのみ残してマスク
WHEN val IS NOT NULL THEN REGEXP_REPLACE(val, '(^.).*(@.*$)', '\\1*****\\2')
ELSE NULL
END;
-- 4. 汎用文字列(氏名・電話等)用マスキングポリシー
CREATE OR REPLACE MASKING POLICY mask_generic_string AS (val string)
RETURNS string ->
CASE
WHEN CURRENT_ROLE() IN ('ACCOUNTADMIN', 'SECURITY_ADMIN') THEN val
WHEN val IS NOT NULL THEN '*** MASKED ***'
ELSE NULL
END;
-- 5. 【核心】タグに対してマスキングポリシーを紐付ける
ALTER TAG pii_type SET
MASKING POLICY mask_email = 'email',
MASKING POLICY mask_generic_string = 'name',
MASKING POLICY mask_generic_string = 'phone';
ここがポイント: カラムに対して
ALTER TABLE ... MODIFY COLUMN ... SET MASKING POLICYを実行するのではなく、ALTER TAG ... SET MASKING POLICYを実行します。これにより、今後該当タグが付与されたカラムには、テーブルが再作成されようが即座にポリシーが強制適用されます。
3. 【ステップ2】dbt Core側でのタグ自動付与マクロ実装
dbt標準の tags はdbt内部のセレクタ用(dbt run --select tag:foo)として使われることが多いため、Snowflakeの実オブジェクトタグには meta プロパティ を利用して連携します。
① dbtマクロの作成 (macros/apply_snowflake_tags.sql)
モデル実行後の post-hook で、schema.yml に記載されたメタデータを読み取り、Snowflakeの ALTER ... SET TAG を発行するマクロです。
{% macro apply_snowflake_tags() %}
{% if execute %}
{% for column_name, column_dict in model.columns.items() %}
{% if column_dict.meta and column_dict.meta.pii_type %}
{% set pii_val = column_dict.meta.pii_type %}
{% set alter_query %}
ALTER {{ model.materialized | upper }} {{ this }}
MODIFY COLUMN {{ adapter.quote(column_name) }}
SET TAG GOVERNANCE_DB.POLICIES.pii_type = '{{ pii_val }}';
{% endset %}
{% do run_query(alter_query) %}
{{ log("Applied Snowflake Tag [" ~ pii_val ~ "] to " ~ this ~ "." ~ column_name, info=True) }}
{% endif %}
{% endfor %}
{% endif %}
{% endmacro %}
② 全モデル共通の post-hook 設定 (dbt_project.yml)
すべてのモデル実行完了後に、自動的に上記マクロが走るように登録します。
# dbt_project.yml
name: 'enterprise_data_pipeline'
version: '1.0.0'
models:
enterprise_data_pipeline:
+post-hook:
- "{{ apply_snowflake_tags() }}"
4. 【ステップ3】データモデルの定義とメタデータ記述
データエンジニアやアナリストは、カラム定義の meta 辞書にタグ種別を書くだけで完了します。
カラム定義 (models/marts/schema.yml)
version: 2
models:
- name: dim_customers
description: "顧客マスタ(PII保護対象モデル)"
columns:
- name: customer_id
description: "顧客一意識別子 (非機密)"
tests:
- unique
- not_null
- name: email_address
description: "顧客連絡先メール"
meta:
pii_type: 'email' # 自動で mask_email ポリシーが適用される
- name: full_name
description: "顧客氏名"
meta:
pii_type: 'name' # 自動で mask_generic_string ポリシーが適用される
- name: total_lifetime_value
description: "累計購買金額 (非機密数値)"
モデルSQLの実装 (models/marts/dim_customers.sql)
{{
config(
materialized='table'
)
}}
SELECT
user_id AS customer_id,
email AS email_address,
CONCAT(first_name, ' ', last_name) AS full_name,
total_spent AS total_lifetime_value,
created_at
FROM {{ ref('stg_users') }}
dbt run -s dim_customers を実行すると、テーブルが物理的に新規作成された直後に post-hook が稼働し、email_address には pii_type = 'email'、full_name には pii_type = 'name' が自動でアタッチされます。
5. ロール別クエリ検証(マスキング動作確認)
設定が意図通りに動作しているか、異なる権限のロールでSELECTを実行して確認します。
-- 1. 一般アナリストロールでクエリ
USE ROLE ANALYST_ROLE;
SELECT customer_id, email_address, full_name, total_lifetime_value
FROM PROD_DWH.ANALYTICS.dim_customers
LIMIT 2;
-- [結果] 個人情報が完全に隠蔽される
-- customer_id | email_address | full_name | total_lifetime_value
-- CUST_001 | y*****@example.com | *** MASKED *** | 45000.00
-- CUST_002 | s*****@sample.co.jp | *** MASKED *** | 12800.50
-- 2. セキュリティ特権ロールでクエリ
USE ROLE SECURITY_ADMIN;
SELECT customer_id, email_address, full_name, total_lifetime_value
FROM PROD_DWH.ANALYTICS.dim_customers
LIMIT 2;
-- [結果] 業務上正当な権限を持つロールのみ平文で閲覧可能
-- customer_id | email_address | full_name | total_lifetime_value
-- CUST_001 | yamada.taro@example.com | 山田 太郎 | 45000.00
-- CUST_002 | sato.hanako@sample.co.jp | 佐藤 花子 | 12800.50
6. 本番運用のためのガバナンス・ガードレール
手作業によるヒューマンエラーをゼロにするため、CI/CDパイプラインに以下の2つの安全柵(Guardrails)を組み込みます。
① dbt-checkpointによるコミット前チェック
PR作成時、Gitの pre-commit または GitHub Actions上で、カラム名に email, phone, ssn などの文字列を含んでいるにもかかわらず、meta.pii_type が定義されていないPRを機械的にブロックします。
# .pre-commit-config.yaml
repos:
- repo: https://github.com/dbt-checkpoint/dbt-checkpoint
rev: v2.0.6
hooks:
- id: check-column-desc-are-same
- id: check-model-has-all-columns
② Snowflake タグ未付与カラムの定期監査クエリ
Snowflakeの ACCOUNT_USAGE ビューを利用し、個人情報の可能性がある名称を持ちながらタグが付いていない「野良カラム」を日次で検知し、Slackへアラート通知します。
-- PII疑いがあるがタグが付いていない列を検知する監査SQL
SELECT
table_catalog,
table_schema,
table_name,
column_name
FROM snowflake.account_usage.columns c
WHERE
(column_name ILIKE '%EMAIL%' OR column_name ILIKE '%PHONE%' OR column_name ILIKE '%NAME%')
AND deleted IS NULL
AND NOT EXISTS (
SELECT 1
FROM snowflake.account_usage.tag_references tr
WHERE tr.object_database = c.table_catalog
AND tr.object_schema = c.table_schema
AND tr.object_name = c.table_name
AND tr.column_name = c.column_name
AND tr.tag_name = 'PII_TYPE'
);
まとめ:データガバナンスは「コード」で自動化する
データ活用を加速させることと、厳格なデータコンプライアンス(GDPR / 個人情報保護法 / SOC 2)を遵守することは、両立可能です。
- Snowflakeのタグベースマスキング を中核に据え、オブジェクト再作成に耐えうる堅牢な基盤を作る。
-
dbtの
metaプロパティとマクロ により、データモデルのコード変更とセキュリティ設定を1つのPRで同期させる。 - CI/CDでの自動検証と監査クエリ により、タグの指定漏れを機械的に遮断する。
この「Governance as Code」のアプローチにより、運用工数を増やすことなく、データ漏洩リスクを最小限に抑えた安全な分析環境を実現できます。
お問い合わせ先
Snowflakeにおけるデータガバナンス基盤の構築、dbt CoreのCI/CD導入、セキュリティ要件に準拠したデータパイプライン設計に関するご相談は、下記よりお気軽にお問い合わせください。
- Webサイト: https://nkktech.com/
- メール: contact@nkk.com.vn
- LinkedIn: https://www.linkedin.com/company/nkktech
著者:NKKTech Global 技術チーム
私たちは、高度なクラウドセキュリティと実践的なデータエンジニアリングで、企業の信頼あるデータ活用をグローバルに支援します。
