🐷
External Network Access:GitActionの動的IPを取得し、Network Policy を都度更新する
がく@ちゅらデータです。
秋はどこにいってしまったのでしょうか・・・・
さて、先日、沖縄SnowVillageにて下記のようなLTをさせていただきました。
で、
として、Slack通知(デコ版)ってのを作って、ふぅ〜これで完成じゃ・・・と思っていました。
でもね、External Network Access、もっとできることがあると思うんですよ
その中で、仕事してて
「Snowflakeのセキュリティ対策として、GitActionからのアクセスもアクセス制限をIPでかけたい」
って話が上がりました
GitのIPってのは、比較的よく変更されるそうです。
なんかいい方法ない? って相談を受けて・・・・・・
あ!External Network Accessを使えば、比較的簡単に実装できるんでね?
外部API叩いて、Network Policyを作れば・・・・・・GitActionからアクセスする都度、動的にNetwork Policyを設定でできれば・・・・
※ただ、GitAction都度動かすのはちとつらいので、毎日一回Taskで動かすとかするのが、セキュリティ的にも妥協点ぁなと
で、作ってみました!
作ってみた
Network Rule
まず、network ruleを作ります
-- https://api.github.com/meta
CREATE OR REPLACE NETWORK RULE github_meta_network_rule
MODE = EGRESS
TYPE = HOST_PORT
VALUE_LIST = ('api.github.com');
Snowflake Secret
今回のURL https://api.github.com/meta は、APIキーなどないので
secretは必要なし
external access integrationを作ります
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION github_meta_access_integration
ALLOWED_NETWORK_RULES = (github_meta_network_rule)
ENABLED = true;
ストアドを作る
- Snowpark(Python)でストアドを作る
- gitのAPIからJSONでIPリストを取得する
- network policyを作る
って機能を実装します
※ただ、今回のはエラーハンドリングとか全然してないので、プロトタイプと捉えてくれれば
※改善したら教えて下さいね!!!!
CREATE OR REPLACE PROCEDURE get_github_meta()
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = 3.10
HANDLER = 'main'
EXTERNAL_ACCESS_INTEGRATIONS = (github_meta_access_integration)
PACKAGES = ('snowflake-snowpark-python', 'requests')
EXECUTE AS CALLER
AS
$$
import snowflake.snowpark as snowpark
import json
import requests
import _snowflake
from datetime import date
def main(session):
# Retrieve the Webhook URL from the SECRET object
github_meta_url = "https://api.github.com/meta"
headers = {"content-type": "application/json"}
response = requests.get(github_meta_url,headers = {"content-type": "application/json"})
if response.status_code != 200:
raise ValueError(
'Request to slack returned an error %s, the response is:\n%s'
% (response.status_code, response.text)
)
data = response.json()
actions = data["actions"]
ip_list_str = ",".join([f"'{s}'"for s in actions if ":" not in s])
create_network_policy = f"CREATE OR REPLACE NETWORK POLICY network_policy_git_action ALLOWED_IP_LIST=({ip_list_str});"
session.sql(create_network_policy).collect()
return create_network_policy
$$;
use role accountadmin;
call get_github_meta();
show network policies;
describe network policy NETWORK_POLICY_GIT_ACTION;
これを、GitActionからアクセスされるサービスアカウント?的なのに
ALTER USER GIT_ACTION_USER SET NETWORK_POLICY = NETWORK_POLICY_GIT_ACTION;
な感じで設定しておく。
新しく更新する際
call get_github_meta();
で、やれば最新のをユーザにアタッチすることができたはず
Discussion