
【新機能】Snowflake の Multi-party Approval が一般提供になったので重要操作への承認フローを必須化してみた
かわばたです。
2026年8月4日に GA となった Multi-party Approval (MPA) を使うと、重要操作に対して「2人目の承認者によるレビュー・承認」を必須化できるようになりました。
本記事では、ネットワークポリシーの変更を保護対象として、MPA のポリシー作成から承認フローの一連の流れ、拒否・キャンセルなどの異常系、Account Usage ビューでの監査までを検証します。
Multi-party Approval の概要
MPA は、指定した重要操作(保護対象操作)を単一の管理者だけでは実行できないようにする機能です。保護対象操作を実行しようとすると、いったんブロックされ、承認リクエストが発行されます。別の承認者がレビューし、承認して初めて、元の操作を実行できるようになります。
ランサムウェア攻撃などで管理者アカウントが侵害された場合でも、MFA の無効化や Tri-Secret Secure の鍵無効化といった致命的な操作を攻撃者が単独で実行できなくなる、というのが主なモチベーションです。
保護対象操作
保護できる操作は以下の 3 グループに分かれています。ポリシーのルールごとに、どの操作を保護するかを選択します。
| グループ | 操作 | 内容 |
|---|---|---|
| 管理操作 | MODIFY_MULTI_PARTY_APPROVAL | MPA ポリシー・ルール・アカウントへの適用/解除の変更(全ポリシーで必須)。SAML2 セキュリティ統合の作成・変更・削除も対象 |
| 管理操作 | DISABLE_MULTI_FACTOR_AUTHENTICATION | MFA の無効化およびユーザーパスワードのリセット |
| 管理操作 | MODIFY_TRI_SECRET_SECURE | Tri-Secret Secure 鍵の有効化/無効化 |
| 管理操作 | MODIFY_PRIVILEGED_ROLE_GRANTS | 管理者ロールの付与/剥奪 |
| 管理操作 | MODIFY_CORTEX_GUARDRAILS | Cortex AI ガードレールの変更 |
| 管理操作 | MODIFY_DATA_RETENTION_TIME | Time Travel 保持期間の変更 |
| ポリシー操作 | MODIFY_NETWORK_POLICY | アクティブなネットワークポリシー・ネットワークルールの変更、アカウント/ユーザーへの割り当ての変更 |
| ポリシー操作 | MODIFY_SESSION_POLICY | セッションポリシーの設定・割り当ての変更 |
| ポリシー操作 | MODIFY_AUTHENTICATION_POLICY | 認証ポリシーの設定・割り当ての変更 |
| ポリシー操作 | MODIFY_PASSWORD_POLICY | パスワードポリシーの設定・割り当ての変更 |
| セキュリティ統合操作 | MODIFY_OAUTH_INTEGRATION | OAuth 統合の変更 |
| セキュリティ統合操作 | MODIFY_EXTERNAL_OAUTH_INTEGRATION | External OAuth 統合の変更 |
| セキュリティ統合操作 | MODIFY_SCIM_INTEGRATION | SCIM 統合の変更 |
MODIFY_MULTI_PARTY_APPROVAL が SAML2 セキュリティ統合まで保護するのは、SSO の設定を変更されると「誰が承認者として認証できるか」自体を攻撃者が操作できてしまうためです。
注意: MODIFY_TRI_SECRET_SECURE の保護には Business Critical Edition 以上が必要です。MPA 機能自体のエディション要件は、2026年8月時点のドキュメントには明記されていません。
承認フロー
保護対象操作を実行しようとすると、次の 4 ステップのフローになります。
- リクエスターが保護対象操作の SQL を実行すると、
MPA_APPROVAL_REQUIREDエラーでブロックされ、request_idが返却される - リクエスターが
SYSTEM$UPDATE_MULTI_PARTY_APPROVAL_JUSTIFICATION()で業務上の理由(justification)を送信すると、リクエストが PENDING になり承認者に通知される - 承認者が Snowsight でリクエストをレビューし、承認または拒否を投票する。必要承認数に達すると APPROVED になる
- リクエスターが、ブロックされたときと完全に同一の SQL 文を再実行すると、承認済みリクエストとマッチして実行される(承認後3日以内)
リクエストの状態は PENDING / APPROVED / EXECUTED / REJECTED / CANCELLED / EXPIRED で遷移します。承認者が1名でも拒否すると、その時点で REJECTED となります。
EXPIRED になるパターンは 2 つある点に注意が必要です。
- PENDING のまま有効期限(request_duration_days)内に必要承認数に達しなかった場合
- APPROVED になったが、3日間のリプレイ期限内に再実行しなかった場合
「承認済みならいつでも再実行できる」わけではありません。
ポリシーの構成要素
MPA ポリシーは YAML 形式の定義を持つスキーマレベルのオブジェクトで、複数のルールを含められます。ルールごとの設定項目は以下のとおりです。
| 項目 | 必須/オプション | デフォルト | 範囲 |
|---|---|---|---|
| name(ルール名) | 必須 | - | - |
| operations(保護対象操作) | 必須 | - | 1 つ以上(空にできない) |
| approvers.users(承認者) | 必須 | - | - |
| required_approvals(必要承認数) | オプション | 2 | 1〜20。承認者リストの人数以下であること |
| request_duration_days(リクエスト有効期限) | オプション | 3日 | 最大14日 |
| self_approval_allowed(自己承認の許可) | オプション | true | true / false |
注意: すべてのポリシーは、MODIFY_MULTI_PARTY_APPROVAL を operations に含むルールを最低 1 つ持つ必要があります。これは、侵害された管理者が MPA 自体を単独で無効化・変更できないようにするための self-protecting ルールです。また、1 つの操作は同一ポリシー内で 1 つのルールにしか含められません。
注意: self_approval_allowed はデフォルト true です。リクエスターが承認者リストに含まれていると、自分のリクエストを自分で承認して必要承認数にカウントできてしまいます。self_approval_allowed: false を指定すると、リクエスター本人の投票は承認数に算入されなくなります。一方、true のまま required_approvals を 2 以上にしても単独実行は防げますが、リクエスター自身の投票は承認数に含まれます。リクエスターと承認者を明確に分離する four-eyes 原則(四眼原則)を求める場合は、self_approval_allowed: false を明示し、承認者をリクエスターと別ユーザーにする構成が適しています。
承認者の要件
承認者に指定できるユーザーには条件があります。
- ローカル Snowflake ユーザーまたは SCIM 管理ユーザーであること(サービスユーザーは不可)
- MFA に登録済みであること
- メールアドレスが検証済みであること
承認操作そのものに追加の権限は不要で、承認者に ACCOUNTADMIN を付与することは MPA の必須要件ではありません。最小権限の観点からも、承認者に不要な強い権限を持たせないことが望ましいです。
また、承認者に指定されたユーザーは保護され、SCIM 経由でのログイン名変更やデプロビジョニング(削除)はブロックされます。
前提条件
- MPA ポリシーの設定・管理には ACCOUNTADMIN ロールを使用する必要があります
- 承認者は MFA 登録済み・メールアドレス検証済みのユーザーである必要があります(ACCOUNTADMIN の付与は不要)
- 本検証では、保護対象操作を実行する KAWABATA_ADMIN(ACCOUNTADMIN を使用)と、承認者 APPROVER_ADMIN の 2 ユーザーに加え、ネットワークポリシーの割り当て先とする検証専用ユーザーを使用します
- 2026年8月4日の GA 後の環境で検証します
検証環境
- 検証期間: 2026年8月5日〜2026年8月11日
- Snowflakeトライアルアカウント Enterpriseエディション
- 検証ユーザー構成:
- KAWABATA_ADMIN: 保護対象操作を実行するリクエスター(ACCOUNTADMIN を使用)
- APPROVER_ADMIN: 承認者(MFA 登録済み・メール検証済み)
- MPA_TEST_USER: ネットワークポリシーの割り当て先とする検証専用ユーザー(ログインには使用しない)
事前準備
検証用ネットワークポリシーの作成とアクティブ化
保護対象操作の検証には MODIFY_NETWORK_POLICY を使います。ここで重要なのは、MODIFY_NETWORK_POLICY の保護範囲が「アクティブなネットワークポリシー・ネットワークルールの変更、アカウントまたはユーザーへの割り当ての変更」とされている点です。ネットワークポリシーは作成しただけでは有効にならず、アカウントまたはユーザーに割り当てて初めてアクティブになるため、どこにも割り当てていないポリシーの変更は MPA でブロックされない可能性があります。
そこで、ログインに使用しない検証専用ユーザーを作成し、そのユーザーにポリシーを割り当ててアクティブな状態を作ります。アカウントレベルへの割り当てはロックアウトのリスクがあるため避けます。
USE ROLE ACCOUNTADMIN;
-- 割り当て先の検証専用ユーザー(ログインには使用しない)
CREATE USER mpa_test_user
COMMENT = 'MPA verification: network policy assignment target';
-- 検証用ネットワークポリシー(全 IP 許可のため実質的な制限は追加されない)
CREATE NETWORK POLICY mpa_test_network_policy
ALLOWED_IP_LIST = ('0.0.0.0/0')
COMMENT = 'MPA verification test policy';
-- 検証専用ユーザーに割り当ててアクティブにする
ALTER USER mpa_test_user SET NETWORK_POLICY = mpa_test_network_policy;

注意: ユーザーへのネットワークポリシー割り当て自体も MODIFY_NETWORK_POLICY の保護範囲に含まれます。MPA 有効化後に割り当てようとすると承認が必要になるため、割り当ては MPA 有効化前に済ませておきます。
注意: 検証専用ユーザーであっても、次のように
DISABLED = TRUEを付けて作成すると、意図しないログインの可能性を設定そのものから排除できるため、より安全です(本検証は DISABLED なしで実施しています)。
CREATE USER mpa_test_user
DISABLED = TRUE
COMMENT = 'MPA verification: network policy assignment target; login disabled';
MPA ポリシーの作成
ポリシー格納用のデータベース・スキーマを用意し、MPA ポリシーを作成します。ルールは 2つ定義します。
- self_protection_rule: MPA 設定自体の変更を保護する必須ルール
- network_policy_rule: ネットワークポリシーの変更を保護する検証用ルール
承認者はリクエスターとは別のユーザー(APPROVER_ADMIN)のみとし、self_approval_allowed: false を明示します。これにより、KAWABATA_ADMIN は自分のリクエストを自分で承認できず、必ず APPROVER_ADMIN のレビューが必要になります。
CREATE DATABASE IF NOT EXISTS security_db;
CREATE SCHEMA IF NOT EXISTS security_db.policies;
CREATE MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy
AS $$
description: 'MPA verification policy'
rules:
- name: self_protection_rule
description: 'Protect MPA configuration changes'
operations: [MODIFY_MULTI_PARTY_APPROVAL]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
- name: network_policy_rule
description: 'Protect network policy changes'
operations: [MODIFY_NETWORK_POLICY]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
$$;

注意: 検証をシンプルにするため承認者1名 + required_approvals: 1 にしていますが、公式のベストプラクティスではすべてのルールで 2 以上が推奨されています。本番では承認者を複数名リストし、required_approvals: 2 以上 + self_approval_allowed: false の組み合わせが望ましいです(required_approvals は承認者リストの人数以下である必要があります)。
なお、MODIFY_MULTI_PARTY_APPROVAL を含むルールを定義せずにポリシーを作成しようとした場合の挙動も確認してみます。
CREATE MULTI PARTY APPROVAL POLICY security_db.policies.mpa_invalid_policy
AS $$
rules:
- name: network_policy_only_rule
operations: [MODIFY_NETWORK_POLICY]
approvers:
users: ['APPROVER_ADMIN']
$$;

ポリシーのアカウントへの適用(有効化)
作成したポリシーを ALTER ACCOUNT でアカウントに適用します。MPA が有効になる前の初回適用のため、この操作自体はブロックされない想定です(有効化後の差し替え・解除は MODIFY_MULTI_PARTY_APPROVAL の保護対象になります)。
ALTER ACCOUNT SET MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy;

Snowsight から操作する場合は、Governance & Security » Requests & approvals » Multi-party configuration からポリシーの作成・有効化(Activate)ができます。

基本フローを試してみた
保護対象操作がブロックされることの確認
リクエスター(KAWABATA_ADMIN)で、アクティブなネットワークポリシーの変更を実行してみます。
ALTER NETWORK POLICY mpa_test_network_policy SET ALLOWED_IP_LIST = ('0.0.0.0/0', '10.0.0.0/8');

ドキュメントによると、次のような形式のエラーが返却され、justification 登録用とキャンセル用の SQL がそのまま案内されます。
Blocked by Multi-party Approval. A request has been created. To proceed, add a justification: "select SYSTEM$UPDATE_MULTI_PARTY_APPROVAL_JUSTIFICATION('94ceb31d-4ee0-4a14-b470-f5036eac52cb', '<reason>');". To cancel: "select SYSTEM$CAST_MULTI_PARTY_APPROVAL_VOTE('94ceb31d-4ee0-4a14-b470-f5036eac52cb', 'REJECT');". Expires: August 14, 2026 at 12:42:56 PM UTC. Request-ID: '94ceb31d-4ee0-4a14-b470-f5036eac52cb'
正当化理由(justification)の送信
エラーメッセージに含まれる request_id を使って、操作の業務上の理由を送信します。これによりリクエストが PENDING となり、承認者に通知されます。
SELECT SYSTEM$UPDATE_MULTI_PARTY_APPROVAL_JUSTIFICATION(
'<request_id>',
'MPA verification: adding 10.0.0.0/8 to the allowed IP list of the test network policy.'
);

リクエストが PENDING の間は、justification を何度でも更新できます。リクエスター自身のリクエスト状態は、Snowsight の Governance & Security » Requests & approvals » Pending » Created by me から確認できます。

承認者による承認
承認者(APPROVER_ADMIN)で Snowsight にログインし、Governance & Security » Requests & approvals » Pending » Sent to me を開くと、承認待ちのリクエストが表示されます。

リクエストを開くと、対象操作・リクエスター・justification を確認して Approve / Reject を選択できます。ここでは Approve します。

required_approvals を 1 にしているため、1 票の承認でリクエストが APPROVED になります。
元の SQL の再実行
リクエスター(KAWABATA_ADMIN)に戻り、最初にブロックされた SQL を再実行します。承認済みリクエストとマッチし、今度は実行に成功します。
ALTER NETWORK POLICY mpa_test_network_policy SET ALLOWED_IP_LIST = ('0.0.0.0/0', '10.0.0.0/8');

承認後に実行できるのは、承認リクエスト作成時にブロックされた SQL と完全に同一の文のみです。対象オブジェクトや設定値を変更した SQL は承認済みリクエストにはマッチせず、新しい操作として扱われます。実際に、一部変更した ALTER を実行して確認してみます。
ALTER NETWORK POLICY mpa_test_network_policy SET ALLOWED_IP_LIST = ('0.0.0.0/0', '10.0.0.0/9');

注意: 再実行は承認後3日以内に行う必要があります。期限を過ぎるとリクエストは EXPIRED になり、再度リクエストからやり直しです。実行が完了するとリクエストは EXECUTED(終了状態)になります。
異常系の挙動も確認してみた
承認者による拒否(REJECTED)
もう一度ネットワークポリシーの変更でリクエストを作成し、justification を送信したうえで、今度は承認者が Reject してみます。拒否にはコメントが必須です。

承認者が1名でも拒否すると、その時点でリクエストは REJECTED となり終了します。
リクエスターによるキャンセル(CANCELLED)
リクエスターは、PENDING 状態である自分のリクエストに対して SYSTEM$CAST_MULTI_PARTY_APPROVAL_VOTE で REJECT を投票することでキャンセルできます。この場合に限り、コメントは省略できます。承認済み・拒否済み・期限切れのリクエストはキャンセルできません。
SELECT SYSTEM$CAST_MULTI_PARTY_APPROVAL_VOTE(
'<request_id>',
'REJECT'
);

自己承認の挙動(任意の追加検証)
self_approval_allowed はデフォルト true のため、リクエスターが承認者リストに含まれていると、自分のリクエストを自分で承認できてしまいます。この挙動を確認するため、network_policy_rule だけ承認者にリクエスターを加え、self_approval_allowed をデフォルト(true)に戻したポリシーに差し替えてみます。
注意: この構成は自己承認の動作確認専用です。リクエスターが単独で承認まで完結できるため、four-eyes 原則は実現できません。
ポイントは、ポリシーの差し替え自体が MODIFY_MULTI_PARTY_APPROVAL の保護対象であるため、この変更にも APPROVER_ADMIN の承認が必要になることです。self-protecting ルールが機能していることの確認も兼ねられます。
ALTER MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy
AS $$
description: 'MPA verification policy (self approval test)'
rules:
- name: self_protection_rule
description: 'Protect MPA configuration changes'
operations: [MODIFY_MULTI_PARTY_APPROVAL]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
- name: network_policy_rule
description: 'Protect network policy changes (self approval test)'
operations: [MODIFY_NETWORK_POLICY]
approvers:
users: ['KAWABATA_ADMIN', 'APPROVER_ADMIN']
required_approvals: 1
$$;

差し替え後、KAWABATA_ADMIN でネットワークポリシー変更のリクエストを作成し、SYSTEM$UPDATE_MULTI_PARTY_APPROVAL_JUSTIFICATION で justification を登録しました。すると本検証環境では、Snowsight の承認画面で Approve を投票することなく、元の SQL の再実行に成功しました。

注意: 公式ドキュメント上のフローでは、justification の登録はリクエストを PENDING に遷移させるだけで、自己承認が許可されている場合でもリクエスター自身が Snowsight で Approve を投票し、APPROVED になってから元の SQL を再実行する手順とされています。本検証で観測された「投票なしで再実行に成功する」挙動はこの記述と異なるため、自己承認許可時の一般的な仕様と断定はできません。過去に APPROVED となった同一 SQL のリクエストが3日間のリプレイ期限内に残っていた場合も同様の挙動になり得るため、試す際は利用中のアカウントで確認してください。
注意: 実運用では self_approval_allowed: false と required_approvals: 2 以上の組み合わせが推奨されます。自己承認を許可した構成では、単一の管理者アカウントの侵害に対する防御になりません。
自己承認の動作確認が済んだら、安全なポリシー定義(両ルールとも self_approval_allowed: false)へ戻しておきます。この ALTER 自体も MODIFY_MULTI_PARTY_APPROVAL の保護対象のため、APPROVER_ADMIN の承認が必要です。
-- 自己承認テスト後は、安全なポリシー定義へ戻す
-- この ALTER 自体も MODIFY_MULTI_PARTY_APPROVAL の承認対象
ALTER MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy
AS $$
description: 'MPA verification policy'
rules:
- name: self_protection_rule
description: 'Protect MPA configuration changes'
operations: [MODIFY_MULTI_PARTY_APPROVAL]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
- name: network_policy_rule
description: 'Protect network policy changes'
operations: [MODIFY_NETWORK_POLICY]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
$$;
ポリシーとリクエストの確認方法
SHOW / DESCRIBE コマンド
ポリシーの一覧と定義は SQL で確認できます。
-- ポリシーの一覧
SHOW MULTI PARTY APPROVAL POLICIES;
-- アカウントに適用中のポリシー
SHOW MULTI PARTY APPROVAL POLICIES ON ACCOUNT;
-- ポリシー定義(YAML 全文)の確認
DESC MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy;



Account Usage ビューでの監査
承認リクエストの履歴は Account Usage ビューで確認できます。誰が・いつ・どの操作をリクエストし、誰が投票したかまで追跡できるため、監査対応にも使えます。
SELECT
request_id,
requester_user_name,
operation,
status,
request_justification,
required_approvals_count,
approvers,
created_time,
resolved_time
FROM snowflake.account_usage.multi_party_approval_requests
ORDER BY created_time DESC;

ポリシー自体の変更履歴は MULTI_PARTY_APPROVAL_POLICIES ビューで確認できます。
SELECT name, database, schema, policy_definition, created, last_altered, deleted
FROM snowflake.account_usage.multi_party_approval_policies;

注意: どちらのビューもレイテンシは最大 120 分です。検証直後は反映されていない場合があります。
制限事項・注意点
検証と公式ドキュメントから確認できた制限事項・注意点をまとめます。
制限事項・注意点
- 承認者はローカル Snowflake ユーザーまたは SCIM 管理ユーザーで、MFA 登録・メールアドレス検証が必須です(サービスユーザー不可)。ACCOUNTADMIN の付与は不要です
- 承認者の投票は Snowsight のアクティブセッションから行います
- 承認後の再実行は、ブロックされたときと完全に同一の SQL 文を3日以内に実行する必要があります
- リクエスターによるキャンセルは PENDING 状態のリクエストに対してのみ可能です
- 1 つの操作は同一ポリシー内で 1 つのルールにしか含められません。また required_approvals は承認者リストの人数以下である必要があります
- self_approval_allowed はデフォルト true です。false を明示するとリクエスター本人の投票は承認数に算入されません。true のまま required_approvals: 2 以上にしても単独実行は防げますが、リクエスター自身の投票は承認数に含まれます
- Account Usage ビューのレイテンシは最大 120 分です
- ポリシーを変更すると、PENDING 中のリクエストは新しいルール構成に対して自動的に再評価(reconcile)されます
- 承認者が全員不在になるなどのデッドロック時は、Snowflake サポートへの正式なチケットで対応(ブレークグラス)となります。ACCOUNTADMIN を複数名配置し、承認者リストを定期的に見直すことが推奨されています
最後に
Multi-party Approval を使うと、これまで運用ルールでしか縛れなかった「重要操作は必ず2人でレビューする」という統制を、Snowflake の機能として強制できるようになります。ただし、self_approval_allowed がデフォルト true である点には注意が必要で、推奨はself_approval_allowed: false + required_approvals: 2 以上 + リクエスターと分離した承認者、という構成を意識する必要があります。ACCOUNTADMIN の単独犯行・侵害への対策として、まず self-protection ルール + MFA 無効化・ネットワークポリシー変更あたりから保護を始めるのがよさそうです。
この記事が何かの参考になれば幸いです!







