Cloud Asset Inventory で一般公開されたリソースを自動検出してみた。
こんにちは、みかみです。
人は間違える生き物です。 BigQuery や GCS バケットなど、大切なデータが置いてあるサービスに誰でもアクセスできるような設定がされていたら一大事! リスクはできる限り抑えたいものです。 _(:3」∠)_
やりたいこと
- 一般公開されている Google Cloud プロジェクト内のリソースを自動検出したい
- 一般公開リソースがあったらメールで通知したい
Cloud Asset Inventory とは
Google Cloud のプロジェクトやフォルダ、組織に紐づくリソースやポリシー、ランタイム情報などのメタデータを検索、分析できるサービスです。 アセットデータをエクスポートした場合などにはデータ保存先の GCS や BigQuery のストレージ料金がかかりますが、基本的には無料で利用できます。
- Cloud Asset Inventory | Cloud Asset Inventory ドキュメント
- Cloud Asset Inventory の概要 | Cloud Asset Inventory ドキュメント
前提
Google Cloud SDK(gcloud
コマンド)の実行環境は準備済みであるものとします。
本エントリでは、Cloud Shell を使用ました。
事前準備
ちゃんと検出できるか確認するために、一般公開された BigQuery データセットを準備しておきます。
データセットの権限設定から、allUsers
に「データ閲覧者」ロールを追加しました。
Pub/Sub トピックを作成
Cloud Shell から以下のコマンドを実行して、Pub/Sub トピックを作成します。 Cloud Scheduler からこの Pub/Sub トピックを経由して、Cloud Functions 関数を実行する予定です。
gcloud pubsub topics create check_public_access
管理コンソールから、トピックが作成されたことを確認しました。
Cloud Functions 関数を作成
Cloud Asset Inventory から一般公開されたリソースを取得する、Clooud Functions 関数を作成します。
以下の Python コードを main.py
というファイル名で保存しました。
from google.cloud import asset_v1 import os def check_public_access_resources(event, context): GCP_PROJECT = os.getenv('GCP_PROJECT', None) scope = f'projects/{GCP_PROJECT}' query = 'policy:(allAuthenticatedUsers OR allUsers)' client = asset_v1.AssetServiceClient() response = client.search_all_iam_policies( request={"scope": scope, "query": query} ) for policy in response: print(f'Open to the public!! resource: {policy.resource}') bindings = policy.policy.bindings for item in bindings: print(f'{item.role} is attached.') break
合わせて、以下の requirements.txt
も、同じディレクトリに保存しました。
google-cloud-asset>=3.9.0
以下の gcloud
コマンドで、main.py
と requirements.txt
を Cloud Functions にデプロイします。
gcloud functions deploy check_public_access_resources \ --region asia-northeast1 \ --runtime python37 \ --trigger-resource check_public_access \ --trigger-event google.pubsub.topic.publish
管理コンソールからも、Cloud Functions 関数が無事デプロイできたことが確認できました。
Cloud Scheduler から Cloud Functions を実行
先ほどデプロイした Cloud Functions をスケジュール実行するために、Cloud Scheduler ジョブを作成します。
Cloud Shell から以下のコマンドを実行します。
gcloud scheduler jobs create pubsub check_public_access \ --schedule="*/5 * * * *" \ --topic=check_public_access \ --message-body="{}" \ --time-zone="Asia/Tokyo"
5分ごとに Cloud Functions を実行するジョブが作成できました。
そのまま5分待ちます..._(:3」∠)_
5分後、ジョブが正常に実行されたようなので、Cloud Functions のログを確認してみると...
bigquery.googleapis.com/(省略)/datasets/test_public
が roles/bigquery.dataViewer
ロールで一般公開されてしまっている旨、期待通りログ出力されました。
アラート通知を追加
せっかく Cloud Functions が5分おきにチェックしてくれていても、ログ出力するだけでは人が認識&対応するまでに時間がかかってしまう可能性があります。
一般公開されたリソースが見つかったら、通知してくれる仕組みも作っておきます。
通知用の別の Cloud Functions を作成して検出結果を Pub/Sub 経由で渡して通知、など、通知方法の実装はいろいろ考えられますが、今回はお手軽に Cloud Monitoring のアラートポリシーを作成して、指定したメールアドレス宛にアラートメールを送信してみます。
ログに特定の文字列が出力されていたらアラートを送信する、ログベースのアラートを作成します。 なお、ログベースのアラートは、2022/05/31 現在まだプレビューなので、ご使用の際にはご留意ください。
まずは Cloud Shell から以下のコマンドを実行して、アラート通知先のチャンネルを作成します。
gcloud alpha monitoring channels create \ --display-name="channel secd mail to me" \ --description="send mail to me" \ --type=email \ [email protected]
※メールアドレスは一部伏字に変更しています。
以下のポリシー定義を、policy_check_public_access.json
というファイル名で保存します。
{ "displayName": "Check public access resources.", "documentation": { "content": "一般公開されているリソースが見つかりました!至急確認してください!!", "mimeType": "text/markdown" }, "conditions": [ { "displayName": "Check public access resources.", "conditionMatchedLog": { "filter": "resource.type=\"cloud_function\" resource.labels.function_name=\"check_public_access_resources\" resource.labels.region=\"asia-northeast1\" severity\u003e=DEFAULT \"Open to the public!!\"" } } ], "alertStrategy": { "notificationRateLimit": { "period": "300s" } }, "combiner": "OR", "enabled": true, "notificationChannels": [ "projects/cm-da-mikami-yuki-258308/notificationChannels/1663xxxxxxxxxxxx8583" ] }
※一部伏字に変更しています。
以下のコマンドで、保存した定義ファイルを指定して、アラートポリシーを作成しました。
gcloud alpha monitoring policies create \ --policy-from-file="policy_check_public_access.json"
Cloud Functions が実行されるのを待って、メールを確認してみると...
設定した通り、アラートメールが受信できました。
データセットが一般公開されてるなんて一大事!すぐに対応せねばっ!!(( ;゚Д゚))
まとめ(所感)
Security Command Center などのマネージドサービスや、サードパーティーツールの導入など、脅威検知の仕組みはいろいろ考えられますが、監視対象が少ない場合には、Cloud Asset Inventory を利用したスクラッチも選択肢になるのではないかと思います。
今回は検出のみでしたが、間違って設定したポリシーの自動修正など、要件に合わせて自由に実装できるかと。
リスクとコストのトレードオフは、いつでも辛いところです。。_(:3」∠)_