こんにちは、最近はGoogle Cloudの記事を書いている上野です。(AWSももちろんやってます) 今回はCloud Asset Inventoryを見ていきます。
Cloud Asset Inventoryとは?
Google Cloud上の、アセットを管理できるサービスです。アセットとは、大きく以下の2種類を指します。
リソース
Compute Engine 仮想マシン(VM)やCloud Storage バケットなどのGoogle Cloud上で作成されたリソースのメタデータ
ポリシー
IAMポリシー、Organizationsポリシーなど、誰が何にアクセスできるかという情報(ポリシーのメタデータ)
Google Cloud上に5 週間分の履歴情報が保管されています。
AWSで言うとAWS Configに近いサービスになります。
Cloud Asset Inventoryの開始方法
開始方法は簡単で、Cloud Asset API の有効化すればOKです。
使用したいプロジェクトを選択し、Cloud Asset API の有効化ページから有効化できます。
Cloud Asset Inventoryで色々見てみる
Cloud Asset Inventory用の権限としては、roles/cloudasset.owner、roles/cloudasset.viewerの2種類あり、フルで使用するにはroles/cloudasset.owner権限を付与する必要があります。
何ができるかは、実際に触ってみたほうがわかりやすいのでいくつかサンプルを実行していきます。
画面上で見る
現状プレビュー状態ですが、アセット インベントリ画面が存在します。
シンプルにリソースの一覧を見る場合はこの画面でも充分そうです。
ただし、公式ドキュメントを見ると、多くの操作はgcloudコマンドかAPIとなっているため、機能をフル活用するという意味ではコマンドもしくはプログラム経由で使用したほうが良いでしょう。
各機能をコマンド例と共に見ていきます。
※プロジェクトID、組織ID、ユーザーメールアドレス等の情報は実際の情報から変更していますので、参考にする場合は環境に合わせて修正してください。
アセットの一覧表示
FWの一覧を取得するコマンドです。
# 実行コマンド(FW一覧) gcloud beta asset list \ --project=[プロジェクトID] \ --asset-types=compute.googleapis.com/Firewall \ --content-type=resource
# 結果例(デフォルトのFW) ancestors: - projects/[プロジェクトID] - organizations/[組織ID] assetType: compute.googleapis.com/Firewall name: //compute.googleapis.com/projects/[プロジェクトID]/global/firewalls/default-allow-ssh resource: data: allowed: - IPProtocol: tcp ports: - '22' creationTimestamp: '2021-01-01T00:00:00.000-08:00' description: Allow SSH from anywhere direction: INGRESS disabled: false id: 'xxxxxxxx' logConfig: enable: false name: default-allow-ssh network: https://www.googleapis.com/compute/v1/projects/[プロジェクトID]/global/networks/default priority: 65534 selfLink: https://www.googleapis.com/compute/v1/projects/[プロジェクトID]/global/firewalls/default-allow-ssh sourceRanges: - 0.0.0.0/0 discoveryDocumentUri: https://www.googleapis.com/discovery/v1/apis/compute/v1/rest discoveryName: Firewall location: global parent: //cloudresourcemanager.googleapis.com/projects/[プロジェクトNo] version: v1 updateTime: '2021-01-01T00:00:00.000-08:00Z'
以下のように組織IDを指定して組織は以下のアセットも表示できます。
gcloud beta asset list \ --organization=[組織ID] \ --asset-types=compute.googleapis.com/Firewall \ --content-type=resource
GCSバケットであれば--asset-types
にstorage.googleapis.com/Bucket
、GCEインスタンスであればcompute.googleapis.com/Instance
を指定すれば取得できます。
IAMポリシーの検索
ユーザーやリソース単位でどんな権限付いているの?という検索ができます。
特定のユーザーに付与された権限
# 特定ユーザーについている権限一覧 # --scppeはprojects/[PROJECT_ID]でもOK gcloud asset search-all-iam-policies \ --scope=organizations/[組織ID] \ --query=policy:ueno@example.com
#結果サンプル ## 組織権限(Admin) assetType: cloudresourcemanager.googleapis.com/Organization organization: organizations/[組織ID] policy: bindings: - members: - user:ueno@example.com role: roles/accesscontextmanager.policyAdmin - members: - user:ueno@example.com role: roles/owner - members: - user:ueno@example.com role: roles/resourcemanager.organizationAdmin resource: //cloudresourcemanager.googleapis.com/organizations/[組織ID] --- ## プロジェクト権限(Owner) assetType: cloudresourcemanager.googleapis.com/Project organization: organizations/[組織ID] policy: bindings: - members: - user:ueno@example.com role: roles/owner project: projects/[プロジェクトNo] resource: //cloudresourcemanager.googleapis.com/projects/[プロジェクトID]
特定リソースに付与された権限
# 特定リソース(audit_log_sink_projectというデータセット)についている権限一覧 gcloud asset search-all-iam-policies \ --scope projects/[プロジェクトID] \ --query=resource:datasets/audit_log_sink_project
#結果サンプル assetType: bigquery.googleapis.com/Dataset organization: organizations/[組織ID] policy: bindings: - members: - projectEditor:[プロジェクトID] - serviceAccount:pxxxxxxxxxx-xxxxx@gcp-sa-logging.iam.gserviceaccount.com role: roles/bigquery.dataEditor - members: - projectOwner:[プロジェクトID] - user:ueno@example.com role: roles/bigquery.dataOwner - members: - projectViewer:[プロジェクトID] role: roles/bigquery.dataViewer project: projects/[プロジェクトNo] resource: //bigquery.googleapis.com/projects/[プロジェクトID]/datasets/audit_log_sink_project
外部公開されているリソース
# 外部公開されているリソース一覧 gcloud asset search-all-iam-policies \ --scope projects/[プロジェクトID] \ --query "policy:(allAuthenticatedUsers OR allUsers)"
#結果サンプル(GCSバケット) assetType: storage.googleapis.com/Bucket policy: bindings: - members: - allAuthenticatedUsers - allUsers role: roles/storage.objectViewer project: projects/[プロジェクトNo] resource: //storage.googleapis.com/testbucket
アセット履歴の表示
特定のリソースに対して、いつどのように変更があったかを表示できます。
次の例では、過去1日間でファイアウォールにどのような変更があったか表示しています。
# 特定のFW「default-allow-ssh」について、過去1日分の変更履歴表示 YESTERDAY=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ" -d "yesterday") NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ") gcloud asset get-history --project=[プロジェクトID] \ --asset-names='//compute.googleapis.com/projects/[プロジェクトID]/global/firewalls/default-allow-ssh' \ --start-time=$YESTERDAY \ --end-time=$NOW --content-type='resource'
結果は長いため一部抜粋しますが、8/24にsourceRangesが0.0.0.0/0
から10.0.0.0/16
に変わっていることがわかります。
# 結果サンプル(一部抜粋) asset: assetType: compute.googleapis.com/Firewall name: //compute.googleapis.com/projects/[プロジェクトID]/global/firewalls/default-allow-ssh resource: data: allowed: - IPProtocol: tcp ports: - '22' creationTimestamp: '2021-06-24T17:58:06.325-07:00' description: Allow SSH from anywhere direction: INGRESS name: default-allow-ssh priority: 65534 sourceRanges: - 10.0.0.0/16 ##ここが変わっている discoveryName: Firewall updateTime: '2021-08-24T10:06:06.495844Z' window: endTime: '2262-04-11T23:47:16.854775807Z' startTime: '2021-08-24T10:06:06.495844Z' #変更日時 --- asset: assetType: compute.googleapis.com/Firewall name: //compute.googleapis.com/projects/[プロジェクトID]/global/firewalls/default-allow-ssh resource: data: allowed: - IPProtocol: tcp ports: - '22' creationTimestamp: '2021-06-24T17:58:06.325-07:00' description: Allow SSH from anywhere direction: INGRESS name: default-allow-ssh priority: 65534 sourceRanges: - 0.0.0.0/0 #変更前の情報 discoveryName: Firewall updateTime: '2021-06-25T00:58:06.622282Z' window: endTime: '2021-08-24T10:06:06.495844Z' #変更日時 startTime: '2021-06-25T00:58:06.622282Z'
BigQueryへエクスポート
BigQueryへCAIの情報をエクスポートできます。
エクスポート後、指定条件で検索を行い検知、といった発見的ガードレールの実装も可能です。
gcloud asset export \ --content-type resource \ --project [プロジェクトID] \ --bigquery-table projects/[プロジェクトID]/datasets/[データセットID]/tables/[テーブル名] \ --output-bigquery-force
--content-typeでアセットのコンテンツタイプを指定しています。iam-policy
を指定するとIAMポリシーをすべてエクスポートできます。
--output-bigquery-forceは既存テーブルへ上書きを行うオプションです。
コンテンツタイプがresource
の場合、テーブルのスキーマは以下のようになっています。
resource.dataにリソースごとの詳細情報がJSONで格納されており、バケットでは以下のようになっています。
{ "acl": [], "billing": {}, "cors": [], "defaultObjectAcl": [], "encryption": {}, "etag": "CAE=", "iamConfiguration": { "bucketPolicyOnly": { "enabled": true, "lockedTime": "2021-08-20T02:58:06.027Z" }, "uniformBucketLevelAccess": { "enabled": true, "lockedTime": "2021-08-20T02:58:06.027Z" } }, "id": "[バケット名]", "kind": "storage#bucket", "labels": {}, "lifecycle": { "rule": [] }, "location": "ASIA-NORTHEAST1", "locationType": "region", "logging": {}, "metageneration": 1, "name": "[バケット名]", "owner": {}, "projectNumber": [プロジェクトNo], "retentionPolicy": {}, "satisfiesPZS": false, "selfLink": "https://www.googleapis.com/storage/v1/b/[バケット名]", "storageClass": "STANDARD", "timeCreated": "2021-05-22T02:58:06.027Z", "updated": "2021-05-22T02:58:06.027Z", "versioning": {}, "website": {}, "zoneAffinity": [] }
エクスポートはGCSバケットへも可能です。
IAMポリシーの分析
「IAMポリシーの検索」と少し似ているのですが、分析ではサービスアカウントやデータセットなどのリソースに対して、誰が、どの権限を持ってアクセスできるのか、といった観点で確認ができます。
たとえば以下のコマンドでは、データセットaudit_log_sink_project
に対してbigquery.datasets.get
またはbigquery.tables.get
権限を持つプリンシパル(IAMユーザーやサービスアカウント)を検索できます。
gcloud asset analyze-iam-policy --project=[プロジェクトID] \ --full-resource-name="//bigquery.googleapis.com/projects/[プロジェクトID]/datasets/audit_log_sink_project" \ --permissions="bigquery.datasets.get,bigquery.tables.get"
#結果サンプル、複数の一致するACLが表示される ACLs: - accesses: - permission: bigquery.datasets.get identities: - name: user:ueno@example.com resources: - fullResourceName: //bigquery.googleapis.com/projects/[プロジェクトID] /datasets/audit_log_sink_project policy: attachedResource: //cloudresourcemanager.googleapis.com/projects/[プロジェクトID] binding: members: - user:ueno@example.com role: roles/owner
「IAMポリシーの検索」と同じように、特定ユーザーに付与されている権限を調べることもできます。
gcloud asset analyze-iam-policy --organization=[組織ID] \ --identity="user:ueno@example.com"
#結果サンプル ## 組織権限(Admin) --- ACLs: - accesses: - role: roles/resourcemanager.organizationAdmin identities: - name: user:ueno@example.com resources: - fullResourceName: //cloudresourcemanager.googleapis.com/organizations/[組織ID] policy: attachedResource: //cloudresourcemanager.googleapis.com/organizations/[組織ID] binding: members: - user:ueno@example.com role: roles/resourcemanager.organizationAdmin --- ## プロジェクト権限(Owner) ACLs: - accesses: - role: roles/owner identities: - name: user:ueno@example.com resources: - fullResourceName: //cloudresourcemanager.googleapis.com/projects/[プロジェクトID] policy: attachedResource: //cloudresourcemanager.googleapis.com/projects/[プロジェクトID] binding: members: - user:ueno@example.com role: roles/owner
ほかにも色々な分析方法が公式ドキュメントで紹介されています。
また、 IAMポリシーの分析コンソール画面(GUI)もあるので、慣れない方はこちらがやりやすい場合もあると思います。
ただし現時点ではプレビュー状態で、組織の指定が必要です。(プロジェクト指定で利用不可)
アセットの変更のモニタリング
フィードとPub/Subを使用して、リソースの変更が発生したら通知するという運用も可能です。
実際の通知まで設定内容を紹介すると長くなってしまうので、本記事ではフィードの作成例を1つだけ紹介しておきます。
以下のコマンドでは、BigQuery テーブル内のコンテンツが変更されたときにtopic_nameという Pub/Sub トピックから通知を作成します。
gcloud asset feeds create quick_start_feed \ --project=[プロジェクトID] \ --content-type=resource --asset-types="bigquery.googleapis.com/Table" \ --pubsub-topic="projects/[プロジェクトID] /topics/topic_name"
その他通知方法の詳細内容は公式ドキュメントを参照してください。
まとめ
Cloud Asset Inventoryでできることをgcloudコマンドベースでざっと整理してみました。APIをONにするだけで色々検索できるのはありがたいですね。
セキュリティガードレールなど、特定の設定を検知したい場合はBigQueryに一度入れて条件でひっかけるやり方が良いかなと思います。Security Command Centerでリアルタイム検知できる内容もあるので、そちらでできることも確認して、Cloud Asset InventoryとSecurity Command Centerを使い分けると良いと思います。