📩

Snowflakeのネットワークポリシー変更を検知してメール通知してみる

2024/10/14に公開


はじめに

Snowflakeのネットワークポリシーはアカウントへの不正アクセスを防ぐうえで非常に重要です。しかし、ACCOUNTADMINのような強い権限を持ったユーザーが故意に(故意でなくても)ネットワークポリシーを変更してしまうと、意図しないインターネットアクセスを許可することになってしまいます。

こうした事態を未然に防ぐことは難しいですが、事故が起きたことを素早く知らせるための仕組み(発見的統制)を作ることができないか、調べてみました。
※今回はSnowflake内の機能で完結するように処理を組んでいます。

QUERY_HISTORYビューの活用

ネットワークポリシーはSQLのDDL文で作成・変更・削除されるため、ACCOUNT_USAGEスキーマのQUERY_HISTORYビューに記録されます。
https://docs.snowflake.com/ja/sql-reference/account-usage/query_history

ネットワークポリシーに関わるDDL文のみを拾おうとすると、以下のようなSQLで取得できます。

select
    user_name || ' がネットワークポリシーを変更しました' || '\n時刻:' || end_time || '\nクエリID:' || query_id || '\nクエリ内容[' ||  query_text || ']' as Events
from
    snowflake.account_usage.query_history
where
    execution_status = 'SUCCESS'
    and query_type in ('CREATE_NETWORK_POLICY', 'ALTER_NETWORK_POLICY', 'DROP_NETWORK_POLICY')
    or (query_text ilike '% set network_policy%' 
    or query_text ilike '% unset network_policy%')
    and query_type != 'SELECT' 
    and query_type != 'UNKNOWN'
order by 
    end_time desc;

↑のクエリをSQLワークシート上で実行すると、以下のような結果が得られます。
(中身は適当です)
alt text

これで、SQLでネットワークポリシーの変更記録を取得できることは分かりました。

※クエリの内容は以下のQuickStartを参考にさせていただきました。
https://quickstarts.snowflake.com/guide/security_dashboards_for_snowflake/index.html?index=..%2F..index&_ga=2.155470331.1768987922.1720517104-1988664807.1684231588&_fsi=PWAYqJkf#7

Snowflakeアラートでメール送信

先ほどのクエリを活用して、ネットワークポリシーが変更されたらSnowflakeアラートでメール通知する仕組みを作ってみます。
やること:

  • 通知統合を作成
  • Snowflakeアラートを作成
  • Snowflakeアラートを起動

以下は具体的なSQLです。サンプルなので内容はシンプルにしています。

-- 通知統合の作成
create notification integration <セキュリティ統合名>
    type=email
    enabled=true
    allowed_recipients=('<メールアドレス>')
;

-- ALERT の作成
create or replace alert <データベース名>.<スキーマ名>.<アラート名>
  warehouse = <ウェアハウス名>
  schedule = '5 minute' --実行間隔を設定
if
    (exists
        (
            select 
	           user_name || ' がネットワークポリシーを変更しました - ' || end_time || ' [' ||  query_text || ']' as Events
            from
	           snowflake.account_usage.query_history
            where
                execution_status = 'SUCCESS'
            	and query_type in ('CREATE_NETWORK_POLICY', 'ALTER_NETWORK_POLICY', 'DROP_NETWORK_POLICY')
            	or (query_text ilike '% set network_policy%' 
            	or query_text ilike '% unset network_policy%')
            	and query_type != 'SELECT' 
            	and query_type != 'UNKNOWN'
                and end_time >= timestampadd(minute, -50, current_timestamp())
            order by 
            	end_time desc
	   )
    )
then call system$send_email(
    '<セキュリティ統合名>',
    '<メールアドレス>',
    -- メール件名
    '【Snowflake】ネットワークポリシーが変更されました',
    -- メール本文 →ここにSQLクエリ結果を良い感じに書けない
    'Snowflakeのネットワークポリシーが変更されました。アカウントを確認してください。'
);
-- 作成した ALERT を起動
alter alert <データベース名>.<スキーマ名>.<アラート名> resume;

これで実際にネットワークポリシーが変更されると、以下のようなメールが飛ぶようになります。
alt text

参考ドキュメント:
https://docs.snowflake.com/ja/user-guide/alerts
https://docs.snowflake.com/ja/user-guide/email-stored-procedures

注意点

  • ACCOUNT_USAGEのQUERY_HISTORYビューは最大45分の遅延があり、Snowflakeアラートの実行間隔も考慮する必要があるため、リアルタイムな検知にはなりません。
    なお、Information Schemaのテーブル関数にもQUERY_HISTORYビューがあり、こちらは遅延はありませんが、自身のユーザーが実行したクエリ履歴しか取得できないため、今回の目的(他ユーザーによる不正検知)を達成できません。
    https://docs.snowflake.com/ja/sql-reference/functions/query_history#usage-notes

  • そもそも、通知先を他ユーザーから編集されたりアラートを止められたりしたら、この仕組みは破綻します。この辺りも厳密に管理したい場合、今回のクエリを活用しつつメール通知の仕組みは別で組んだほうが良いです。Snowflakeアラートは細かいクレジット消費量通知や処理完了通知など、セキュリティに関与しない通知で有効活用するのがベストだと思います。(今回は簡易検証ということで使用しました)

Discussion