[新機能]Data Movement Policies が一般提供となったのでデータのアンロード・ダウンロード・フェッチを制御してみた

[新機能]Data Movement Policies が一般提供となったのでデータのアンロード・ダウンロード・フェッチを制御してみた

Snowflake のデータ流出防止機能「Data Movement Policies」が2026年8月にGA化されました。本記事では、ポリシーの作成からアカウント・タグへの適用、ブロック・アラート動作、違反監視まで、実際の検証を通じて詳しく解説します。
2026.08.26

かわばたです。

2026年8月19日にData Movement Policies が一般提供(GA)となりました。
データのアンロード・ダウンロード・画面表示・プログラムやエージェント経由の取得といった操作を、「許可 / アラート付き許可 / ブロック」の3段階で制御できます。

本記事では、ポリシーの作成からタグ・アカウントへの適用、ブロックとアラートの動作、監視ビューでの違反確認までを検証します。

https://docs.snowflake.com/en/user-guide/data-movement-policies

【追記】
Snowflake Community Awards の「RISING COMMUNITY LEADER OF THE YEAR」部門・APJ枠のファイナリストに選ばれました。
詳細は下記よりご確認ください。

https://dev.classmethod.jp/articles/snowflake-community-awards-finalist-activities-review/

Data Movement Policies の概要

Data Movement Policy は、データの持ち出しにつながる移動・取得操作を制御するデータ流出防止(data exfiltration prevention)機能です。制御対象の移動タイプ(movement type)は6種類です。

TYPE 制御対象
COPY_INTO_EXTERNAL_STAGE 外部ステージへのアンロード
COPY_INTO_INTERNAL_STAGE 内部ステージへのアンロード
SNOWSIGHT_UI Snowsight 起点のデータアクセス(ワークシート等)
UI_DOWNLOAD Snowsight の対象画面でのクエリ結果ダウンロード
PROGRAMMATIC_FETCH ドライバー / コネクタ / SnowSQL / Snowflake CLI / SQL API / ストアドプロシージャ経由のフェッチ
AGENT_ACCESS エージェント / MCP クライアント経由のデータアクセス

1つのステートメントに対して評価される主 movement type は1つです。COPY_INTO_EXTERNAL_STAGE > COPY_INTO_INTERNAL_STAGE > AGENT_ACCESS > SNOWSIGHT_UI > PROGRAMMATIC_FETCH の固定順で分類され、UI_DOWNLOAD だけはクエリ完了後に独立して評価されます。ストアドプロシージャ内のフェッチは、Snowsight から呼び出しても PROGRAMMATIC_FETCH に分類されます。

Data Sharing やレプリケーションは、サポートされる movement type の一覧に含まれません。制御の中心は「アンロード・ダウンロード・プログラムやエージェント経由の取り出し」です。

Rule と Policy の2層構造

構成要素は2階層に分かれています。

  • Data Movement Rule: 移動タイプ1つに対し、MAX_ROWS を返す SQL 式で制限を定義する
  • Data Movement Policy: 複数の Rule を ENFORCE_RULES(超過でブロック)と ALERT_RULES(超過でも許可し違反記録)に束ね、タグまたはアカウントに適用する

MAX_ROWS の戻り値の意味は次の3通りです。

戻り値 意味
NULL 無制限(許可)
0 ブロック
正の整数 許可する最大行数

式の中では SYS_CONTEXT でロールや移動タイプ、接続経路(Snowflake CLI か SQL API か等)を参照でき、「特定ロールだけ許可」「特定経路だけ行数制限」といった条件分岐を書けます。

適用単位と優先順位

ポリシーはオブジェクトへの直接適用ではなく、タグ経由またはアカウント全体に適用します。複数が該当する場合は、より詳細な単位が優先されます。

  1. カラムレベルのタグ
  2. テーブルレベルのタグ
  3. スキーマレベルのタグ
  4. データベースレベルのタグ
  5. アカウントレベル(ベースライン)

前提条件

  • Enterprise Edition 以上
  • Rule / Policy の作成: スキーマへの CREATE DATA MOVEMENT RULE / CREATE DATA MOVEMENT POLICY 権限
  • タグ / アカウントへの適用: アカウントへの APPLY DATA MOVEMENT POLICY 権限

検証は2026年8月20日〜26日に AWS 東京リージョンのアカウントで実施しています。

事前準備

検証用の DB・ダミー給与テーブル(3000行)・タグ・アナリストロールを作成します。

事前準備
USE ROLE ACCOUNTADMIN;

CREATE OR REPLACE DATABASE DMP_TEST_DB;
CREATE SCHEMA DMP_TEST_DB.GOVERNANCE;
CREATE SCHEMA DMP_TEST_DB.HR;

-- ダミー給与テーブル(3000行)
CREATE OR REPLACE TABLE DMP_TEST_DB.HR.EMPLOYEE_SALARY AS
SELECT
  SEQ4() + 1                                        AS EMP_ID,
  'EMP_' || LPAD(TO_VARCHAR(SEQ4() + 1), 5, '0')    AS EMP_NAME,
  'emp' || TO_VARCHAR(SEQ4() + 1) || '@example.com' AS EMAIL,
  UNIFORM(4000000, 12000000, RANDOM())              AS SALARY,
  DECODE(MOD(SEQ4(), 4), 0, 'SALES', 1, 'HR', 2, 'ENGINEERING', 3, 'FINANCE') AS DEPARTMENT
FROM TABLE(GENERATOR(ROWCOUNT => 3000));

-- 優先順位検証用のタグなしテーブル(100行)
CREATE OR REPLACE TABLE DMP_TEST_DB.HR.OFFICE_LOCATION AS
SELECT
  SEQ4() + 1 AS LOCATION_ID,
  'OFFICE_' || TO_VARCHAR(SEQ4() + 1) AS LOCATION_NAME
FROM TABLE(GENERATOR(ROWCOUNT => 100));

CREATE OR REPLACE TAG DMP_TEST_DB.GOVERNANCE.PII_TAG;

-- 検証用アナリストロール
CREATE OR REPLACE ROLE DMP_ANALYST;
GRANT USAGE ON WAREHOUSE COMPUTE_WH TO ROLE DMP_ANALYST;
GRANT USAGE ON DATABASE DMP_TEST_DB TO ROLE DMP_ANALYST;
GRANT USAGE ON ALL SCHEMAS IN DATABASE DMP_TEST_DB TO ROLE DMP_ANALYST;
GRANT SELECT ON ALL TABLES IN DATABASE DMP_TEST_DB TO ROLE DMP_ANALYST;
GRANT ROLE DMP_ANALYST TO USER <検証ユーザー>;

Rule の作成

移動タイプごとに Rule を作成します。SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') で実行ロールを判定し、ACCOUNTADMIN は無制限(NULL)、それ以外は制限をかける構成です。

USE SCHEMA DMP_TEST_DB.GOVERNANCE;

-- 内部ステージへのアンロードを ACCOUNTADMIN 以外ブロック
CREATE OR REPLACE DATA MOVEMENT RULE R_COPY_INTERNAL_BLOCK
  TYPE = 'COPY_INTO_INTERNAL_STAGE'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE WHEN SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') = 'ACCOUNTADMIN' THEN NULL ELSE 0 END
  );

-- プログラムフェッチは ACCOUNTADMIN 無制限 / それ以外 1000行まで
CREATE OR REPLACE DATA MOVEMENT RULE R_PROG_FETCH_LIMIT
  TYPE = 'PROGRAMMATIC_FETCH'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE WHEN SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') = 'ACCOUNTADMIN' THEN NULL ELSE 1000 END
  );

-- Snowsight のダウンロードボタンを ACCOUNTADMIN 以外ブロック
CREATE OR REPLACE DATA MOVEMENT RULE R_UI_DOWNLOAD_BLOCK
  TYPE = 'UI_DOWNLOAD'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE WHEN SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') = 'ACCOUNTADMIN' THEN NULL ELSE 0 END
  );

-- Snowsight ワークシートの結果表示を ACCOUNTADMIN 以外ブロック
CREATE OR REPLACE DATA MOVEMENT RULE R_SNOWSIGHT_BLOCK
  TYPE = 'SNOWSIGHT_UI'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE WHEN SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') = 'ACCOUNTADMIN' THEN NULL ELSE 0 END
  );

-- エージェント / MCP クライアント経由アクセスを全ブロック
CREATE OR REPLACE DATA MOVEMENT RULE R_AGENT_BLOCK
  TYPE = 'AGENT_ACCESS'
  MAX_ROWS AS () RETURNS INTEGER
  -> (0);

-- ALERT 用: プログラムフェッチ 500行超で違反記録(許可はする)
CREATE OR REPLACE DATA MOVEMENT RULE R_PROG_FETCH_ALERT
  TYPE = 'PROGRAMMATIC_FETCH'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE WHEN SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') = 'ACCOUNTADMIN' THEN NULL ELSE 500 END
  );

Policy の作成

Rule を ENFORCE_RULESALERT_RULES に束ねます。

CREATE OR REPLACE DATA MOVEMENT POLICY DMP_PII_POLICY
  ENFORCE_RULES = (R_COPY_INTERNAL_BLOCK, R_PROG_FETCH_LIMIT, R_UI_DOWNLOAD_BLOCK, R_SNOWSIGHT_BLOCK, R_AGENT_BLOCK)
  ALERT_RULES = (R_PROG_FETCH_ALERT)
  COMMENT = 'PII guard: block unload/download/agent, fetch <= 1000, alert > 500';

DESCRIBE DATA MOVEMENT POLICY DMP_PII_POLICY;

2026-08-26_10h12_57

試してみた

タグへの適用: データ移動を含む伝播モードが必要

作成したタグに DMP を設定します。タグの伝播モードが既定(PROPAGATE = NONE)のままポリシーを設定するとエラー(503509)で拒否されるため、先にデータ移動を含む伝播モードを設定します。

ALTER TAG DMP_TEST_DB.GOVERNANCE.PII_TAG SET PROPAGATE = ON_DEPENDENCY_AND_DATA_MOVEMENT;
ALTER TAG DMP_TEST_DB.GOVERNANCE.PII_TAG SET DATA MOVEMENT POLICY DMP_TEST_DB.GOVERNANCE.DMP_PII_POLICY;

-- 給与カラムにタグを付与
ALTER TABLE DMP_TEST_DB.HR.EMPLOYEE_SALARY MODIFY COLUMN SALARY
  SET TAG DMP_TEST_DB.GOVERNANCE.PII_TAG = 'salary';

POLICY_REFERENCES でポリシーとタグの関連付けを確認すると ACTIVE になっています。

SELECT POLICY_NAME, REF_ENTITY_NAME, REF_ENTITY_DOMAIN, POLICY_STATUS
FROM TABLE(DMP_TEST_DB.INFORMATION_SCHEMA.POLICY_REFERENCES(
  REF_ENTITY_NAME => 'DMP_TEST_DB.GOVERNANCE.PII_TAG', REF_ENTITY_DOMAIN => 'TAG'));

2026-08-26_10h35_17

タグ経由のブロック動作

テーブルタグの施行後、DMP_ANALYST で各操作を試します。まず内部ステージへのアンロードはブロックされます。

-- DMP_ANALYST で実行
COPY INTO @~/dmp_test/ FROM DMP_TEST_DB.HR.EMPLOYEE_SALARY;

2026-08-26_10h47_34

プログラムフェッチの行数制限(1000行)は、境界値どおりに動作しました。

-- DMP_ANALYST で実行
SELECT * FROM DMP_TEST_DB.HR.EMPLOYEE_SALARY LIMIT 1001;  -- ブロック
SELECT * FROM DMP_TEST_DB.HR.EMPLOYEE_SALARY LIMIT 1000;  -- 成功(上限ちょうど)

2026-08-26_23h07_59

2026-08-26_23h09_24

アカウントへの適用: 即時に施行される

次に、アカウント全体のベースラインポリシーを検証します。ACCOUNTADMIN 以外のプログラムフェッチを全ブロックする Rule を作成し、アカウントに適用します。

CREATE OR REPLACE DATA MOVEMENT RULE R_BASELINE_PROG_FETCH_BLOCK
  TYPE = 'PROGRAMMATIC_FETCH'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE WHEN SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') = 'ACCOUNTADMIN' THEN NULL ELSE 0 END
  );

CREATE OR REPLACE DATA MOVEMENT POLICY DMP_ACCOUNT_BASELINE
  ENFORCE_RULES = (R_BASELINE_PROG_FETCH_BLOCK);

ALTER ACCOUNT SET DATA MOVEMENT POLICY DMP_TEST_DB.GOVERNANCE.DMP_ACCOUNT_BASELINE;

すでにアカウントレベルのポリシーが設定済みの場合は、末尾に FORCE を付けて置き換えます。

注意: アカウントに適用するポリシーの Rule には、復旧に使う管理ロール(本例では ACCOUNTADMIN)を除外する条件を必ず入れてください。全ロールで MAX_ROWS = 0 にすると、自分のセッションのフェッチもブロックされます。復旧用に ALTER ACCOUNT UNSET DATA MOVEMENT POLICY; を控えておくと安全です。

適用直後に DMP_ANALYST ロールで Snowflake CLI からクエリすると、即座にブロックされました。

-- DMP_ANALYST で実行
SELECT * FROM DMP_TEST_DB.HR.OFFICE_LOCATION LIMIT 5;

2026-08-26_11h40_23

エラーは SQL compilation error として返るため、クエリは実行されずウェアハウスも消費しないと考えられます。MAX_ROWS = 0 の場合は行数によらず一律ブロックで、1行しか返さない集計クエリも同じエラーになります。

-- DMP_ANALYST で実行
SELECT COUNT(*) FROM DMP_TEST_DB.HR.OFFICE_LOCATION;

2026-08-26_11h41_36

ACCOUNTADMIN では Rule が NULL(無制限)を返すため、同じクエリが成功します。

適用済みポリシーへの Rule 追加

アカウントに適用済みのポリシーにも、ALTER で Rule を後から追加できます。Snowsight 用の2つの ENFORCE Rule と、アンロード用の ALERT Rule を追加しました。

-- Snowsight ワークシート表示: ACCOUNTADMIN 以外は 100行まで
CREATE OR REPLACE DATA MOVEMENT RULE R_BASELINE_SNOWSIGHT_LIMIT
  TYPE = 'SNOWSIGHT_UI'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE WHEN SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') = 'ACCOUNTADMIN' THEN NULL ELSE 100 END
  );

-- Snowsight ダウンロードボタン: ACCOUNTADMIN 以外ブロック
CREATE OR REPLACE DATA MOVEMENT RULE R_BASELINE_UI_DOWNLOAD_BLOCK
  TYPE = 'UI_DOWNLOAD'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE WHEN SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') = 'ACCOUNTADMIN' THEN NULL ELSE 0 END
  );

-- ALERT: 内部ステージへのアンロードが 50行を超えたら違反記録
CREATE OR REPLACE DATA MOVEMENT RULE R_BASELINE_COPY_ALERT
  TYPE = 'COPY_INTO_INTERNAL_STAGE'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE WHEN SYS_CONTEXT('SNOWFLAKE$SESSION', 'ROLE') = 'ACCOUNTADMIN' THEN NULL ELSE 50 END
  );

ALTER DATA MOVEMENT POLICY DMP_ACCOUNT_BASELINE
  ADD ENFORCE_RULES = (R_BASELINE_SNOWSIGHT_LIMIT, R_BASELINE_UI_DOWNLOAD_BLOCK);
ALTER DATA MOVEMENT POLICY DMP_ACCOUNT_BASELINE
  ADD ALERT_RULES = (R_BASELINE_COPY_ALERT);

2026-08-26_15h30_50

ALERT_RULES: 許可しつつ違反として記録する

ALERT はしきい値を超えても操作自体は成功させ、違反として記録します。DMP_ANALYST で100行(しきい値50行超)を内部ステージへアンロードすると、成功しました。

-- DMP_ANALYST で実行
COPY INTO @~/dmp_alert/ FROM DMP_TEST_DB.HR.OFFICE_LOCATION;

2026-08-26_15h37_02

監視: DATA_MOVEMENT_VIOLATIONS ビュー

違反は SNOWFLAKE.ACCOUNT_USAGE.DATA_MOVEMENT_VIOLATIONS ビューに記録されます。ENFORCE でブロックしたクエリと ALERT で許可した操作の両方が対象です。以下は ALERT に該当した記録に絞った確認で、ENFORCE のブロックは ENFORCED_POLICY 列で同様に確認できます。記録直後は TIMESTAMP 等が未反映のことがあるため NULLS FIRST を付けています。

SELECT
  MOVEMENT_TYPE,
  USER_NAME,
  ALERTED_POLICIES,
  TIMESTAMP
FROM SNOWFLAKE.ACCOUNT_USAGE.DATA_MOVEMENT_VIOLATIONS
WHERE ALERTED_POLICIES IS NOT NULL
ORDER BY TIMESTAMP DESC NULLS FIRST
LIMIT 5;

2026-08-26_15h48_01

定義情報の棚卸しには DATA_MOVEMENT_POLICIES / DATA_MOVEMENT_POLICY_RULES / DATA_MOVEMENT_RULE_REFERENCES ビューを使えます。DATA_MOVEMENT_POLICY_RULES には Rule の式(FUNCTION_BODY)まで含まれます。

優先順位: テーブルタグのポリシーがベースラインより優先される

この時点で、アカウントには「ACCOUNTADMIN 以外のフェッチを全ブロック」するベースラインが、タグ付きテーブルには「1000行まで許可」するタグポリシーが両方効いています。DMP_ANALYST で両テーブルにクエリすると、優先順位が確認できます。

-- DMP_ANALYST で実行
SELECT * FROM DMP_TEST_DB.HR.EMPLOYEE_SALARY LIMIT 600;  -- 成功
SELECT * FROM DMP_TEST_DB.HR.OFFICE_LOCATION LIMIT 5;    -- ブロック

2026-08-26_22h01_06

2026-08-26_22h01_57

タグ付きテーブルへの600行フェッチは、ベースラインでは全ブロックのはずが、より詳細なテーブルタグのポリシー(1000行まで許可)が選ばれて成功します。タグのないテーブルはベースラインが適用されたままです。

ただし、タグポリシーが常にベースラインを単純上書きするわけではなく、優先順位は「参照するカラム・オブジェクトごとに最も詳細なポリシーを選ぶ」仕組みで、選ばれたポリシーが複数残る場合は、その中で最も厳しい MAX_ROWS がステートメント全体に適用されます。
今回はテーブル全体がタグ対象のため、有効ポリシーがタグ側の1つに定まりました。

なお、同じ2つの SELECT を Snowsightで実行すると結果が逆になります。
SNOWSIGHT_UI として評価されるため、タグ付きテーブルはタグポリシーの SNOWSIGHT_UI = 0 でブロック、タグなしテーブルはベースラインの100行制限内で表示されるためです。
優先順位は同じでも、評価される movement type が実行経路で変わる点に注意してください。

SNOWSIGHT_UI / UI_DOWNLOAD: Snowsight での挙動

Snowsight のワークシートでも DMP_ANALYST ロールで検証しました。制限(100行)以内のクエリは結果が表示され、ダウンロードボタンだけが無効化されます。ボタンにカーソルを合わせると「ダウンロードが無効です:データ移動ポリシーがトリガーされました」と表示されます。

-- DMP_ANALYST で実行(50行 <= 制限100行)
SELECT * FROM DMP_TEST_DB.HR.OFFICE_LOCATION LIMIT 50;

2026-08-26_22h08_42

一方、SNOWSIGHT_UI の制限(100行)を超える結果は、切り詰め表示ではなくクエリ自体がエラーになります。CLI と同じ「Data movement policy triggered.」が結果ペインに表示されます。

-- DMP_ANALYST で実行(300行 > 制限100行)
SELECT * FROM DMP_TEST_DB.HR.OFFICE_LOCATION;

2026-08-26_22h09_35

「制限行数までは見せる」のではなく「制限を超える結果は返さない」動作のため、SNOWSIGHT_UI に正の整数を設定する場合は、利用者側に LIMIT 句を付けてもらう運用になります。

AGENT_ACCESS: エージェント経由アクセスの制御

事前準備

事前準備としてエージェントの作成
USE ROLE ACCOUNTADMIN;

CREATE DATABASE IF NOT EXISTS KAWABATA_MART_DB;
CREATE SCHEMA IF NOT EXISTS KAWABATA_MART_DB.HR;

-- ダミー給与テーブル
CREATE OR REPLACE TABLE KAWABATA_MART_DB.HR.EMPLOYEE_SALARY AS
SELECT
  SEQ4() + 1                                     AS EMP_ID,
  'EMP_' || LPAD(TO_VARCHAR(SEQ4() + 1), 5, '0') AS EMP_NAME,
  UNIFORM(4000000, 12000000, RANDOM())           AS SALARY,
  DECODE(MOD(SEQ4(), 4), 0, 'SALES', 1, 'HR', 2, 'ENGINEERING', 3, 'FINANCE') AS DEPARTMENT
FROM TABLE(GENERATOR(ROWCOUNT => 100));

-- Cortex Analyst 用セマンティックビュー
CREATE OR REPLACE SEMANTIC VIEW KAWABATA_MART_DB.HR.EMPLOYEE_SV
  TABLES (
    employees AS KAWABATA_MART_DB.HR.EMPLOYEE_SALARY
      PRIMARY KEY (EMP_ID)
      WITH SYNONYMS ('社員', '従業員')
      COMMENT = '社員の給与情報'
  )
  DIMENSIONS (
    employees.emp_name AS emp_name COMMENT = '社員名',
    employees.department AS department COMMENT = '部署'
  )
  METRICS (
    employees.avg_salary AS AVG(salary) COMMENT = '平均給与',
    employees.total_salary AS SUM(salary) COMMENT = '給与合計'
  )
  COMMENT = 'AGENT_ACCESS 検証用';

-- エージェント作成(Cortex Analyst ツール付き)
CREATE OR REPLACE AGENT KAWABATA_MART_DB.HR.DMP_AGENT_TEST
  WITH PROFILE = '{"display_name": "DMP AGENT_ACCESS Test"}'
  FROM SPECIFICATION $$
{
  "models": { "orchestration": "auto" },
  "instructions": { "response": "社員データについて日本語で簡潔に答えてください。" },
  "tools": [
    {
      "tool_spec": {
        "type": "cortex_analyst_text_to_sql",
        "name": "employee_analyst"
      }
    }
  ],
  "tool_resources": {
    "employee_analyst": { "semantic_view": "KAWABATA_MART_DB.HR.EMPLOYEE_SV" }
  }
}
$$;

ポリシー付与前は通常通り出力されます。
2026-08-26_22h36_03

Rule / Policy 作成とアカウント適用

USE ROLE ACCOUNTADMIN;
CREATE SCHEMA IF NOT EXISTS KAWABATA_MART_DB.GOVERNANCE;
USE SCHEMA KAWABATA_MART_DB.GOVERNANCE;

-- 対象エージェントのみブロック(他エージェントは NULL = 無制限)
CREATE OR REPLACE DATA MOVEMENT RULE R_AGENT_SCOPED_BLOCK
  TYPE = 'AGENT_ACCESS'
  MAX_ROWS AS () RETURNS INTEGER
  -> (
    CASE
      WHEN SYS_CONTEXT('SNOWFLAKE$DATA_MOVEMENT', 'AGENT_NAME') LIKE '%DMP_AGENT_TEST%' THEN 0
      ELSE NULL
    END
  )
  COMMENT = 'Block data access for the test agent only';

CREATE OR REPLACE DATA MOVEMENT POLICY DMP_AGENT_TEST_POLICY
  ENFORCE_RULES = (R_AGENT_SCOPED_BLOCK)
  COMMENT = 'AGENT_ACCESS verification (temporary)';

ALTER ACCOUNT SET DATA MOVEMENT POLICY KAWABATA_MART_DB.GOVERNANCE.DMP_AGENT_TEST_POLICY;

AGENT_NAME には呼び出したエージェントの修飾名が入るため、実運用では完全修飾名の完全一致で判定すると誤マッチを防げます。

なお、AGENT_ACCESS の検証は前節までとは別のアカウントで実施しています。同一アカウントで試す場合は、適用済みのポリシーを FORCE で置き換えるか UNSET してから適用してください。検証後は ALTER ACCOUNT UNSET DATA MOVEMENT POLICY; で解除します。

上記適用後にSnowsight CoWorkで対象エージェントに、適用前と同じデータ質問を問い合わせました。

2026-08-26_22h50_25

データ移動ポリシーが適用されクエリが拒否されることが確認できました。

PARTITION BY 付きアンロードは無条件でブロックされる

公式ドキュメントに「DMP が有効な場合、PARTITION BY を使うアンロードは常にブロックされる」と記載があります。実際に試すと、Rule がすべて無制限(NULL)を返す ACCOUNTADMIN でもブロックされました。

-- ACCOUNTADMIN で実行
COPY INTO @~/dmp_part/ FROM (
  SELECT LOCATION_NAME, LOCATION_ID FROM DMP_TEST_DB.HR.OFFICE_LOCATION
) PARTITION BY (LOCATION_NAME);

2026-08-26_22h11_45

ポリシーがアカウントに適用されているだけで、Rule の内容にかかわらずブロックされます。PARTITION BY を使う既存のアンロードパイプラインがある環境では、DMP 導入前に影響確認が必要です。

制限事項・注意点

2026年8月26日時点の検証結果と公式ドキュメントから、導入時に気を付けたい点をまとめます。

制限事項・注意点
  • カラムタグ単独では施行を確認できなかった(本検証環境)。テーブルタグは1分以内、アカウント適用は即時に施行された
  • MAX_ROWS = 0 はコンパイル時(001003)、正の整数の上限超過は実行時(100168)にブロックされる(実測)
  • 上限超過のクエリは実行後に判定されるため、ウェアハウスを消費すると考えられる
  • DMP を設定するタグは PROPAGATE = ON_DEPENDENCY_AND_DATA_MOVEMENT または ON_DATA_MOVEMENT が必要(NONE のままではエラーで拒否される)
  • 主 movement type は1つに分類される。エージェント経由の COPY INTO は AGENT_ACCESS ではなく COPY_INTO_* で評価されるため、アンロードを止めるには COPY_INTO_* の Rule も必要
  • 複数のポリシーが有効なステートメントでは、最も厳しい MAX_ROWS が全体に適用される(詳細は優先順位の節)
  • PARTITION BY 付きアンロードは、Rule の内容にかかわらず DMP 適用中は常にブロックされる。このブロックは DATA_MOVEMENT_VIOLATIONS に記録されなかった(実測)
  • UI_DOWNLOADENFORCE_RULES のみ指定可能で、違反記録(DATA_MOVEMENT_VIOLATIONS)にも残らない
  • UI_DOWNLOAD の対象は Workspace の結果・ノートブックセル・Query History のダウンロード等。Streamlit アプリ、VS Code 拡張、HTML Export、CoWork は対象外
  • 同一ポリシーの同一セクション内に、同じ移動タイプの Rule は1つしか入れられない
  • 行数しきい値の評価はステートメント単位のため、クエリを分割した持ち出しは検出できない
  • 違反記録はベストエフォートで完全性の保証はない(違反行の実測反映は5〜10分程度)
  • ビュー反映の遅延は DATA_MOVEMENT_VIOLATIONS / DATA_MOVEMENT_RULE_REFERENCES が最大3時間、DATA_MOVEMENT_POLICIES / DATA_MOVEMENT_POLICY_RULES が最大2時間
  • クロスリージョン共有の保護は未対応

最後に

マスキング等の「見せ方」の制御に加えて、「持ち出し」自体を SQL 式で宣言的に制御できるのは嬉しいと感じました。
また、AGENT_ACCESSにも適用できるのは活用の幅が広がりそうです。

この記事が何かの参考になれば幸いです!


Snowflake World Tour Tokyo 2026に参加しませんか?

Snowflakeの国内最大級イベント「Snowflake World Tour Tokyo」が2026年9月10日(木)・11日(金)にグランドプリンスホテル新高輪にて開催されます。
最新のAI・データ活用事例やライブデモを体感できる無料イベントです。

Snowflake World Tour Tokyoイベントに参加する


Snowflake Community Awards ファイナリストに選出されました

DevelopersIO で Snowflake 記事を執筆している かわばた が、Snowflake Community Awards「RISING COMMUNITY LEADER OF THE YEAR」部門・APJ枠のファイナリストに選ばれました。
最終選考の30%はコミュニティ投票です。記事がお役に立っていたようでしたら、9月15日(火)までにぜひ一票お願いします。フォームの「(4 of 6) RISING COMMUNITY LEADER OF THE YEAR」で Tomohiro Kawabata | Classmethod, Japan を選択、2分ほどで完了します。

投票フォームを開く


Snowflakeの導入支援はクラスメソッドに!

クラスメソッドでは Snowflake の導入を支援しております。
製品の詳細や支援の内容についてお気軽にお問い合わせください。

Snowflakeの詳細を見る

この記事をシェアする

関連記事