Security Command Centerのセキュリティポスチャー機能を使ってみた

Security Command Centerのセキュリティポスチャー機能を使ってみた

2025.12.25

はじめに

メリークリスマス!
クラウド事業本部コンサルティング部の渡邉です。

Security Command Center Premiumについて、以下の記事で解説・有効化していきました。

https://dev.classmethod.jp/articles/enable-security-command-center-premium-tier/

クラウド環境のセキュリティ管理は、組織の規模が大きくなるにつれて複雑さを増していきます。Google CloudのSecurity Command Center Premiumが提供するセキュリティポスチャー機能は、組織全体のセキュリティ状態を一元的に定義・管理・監視できる強力なソリューションです。

本記事では、セキュリティポスチャーの概要から実際の利用方法まで解説します。

セキュリティポスチャーの概要

セキュリティポスチャーとは

セキュリティポスチャーは、クラウド資産のセキュリティ状態を定義・管理する機能です。組織が定義したセキュリティベンチマークに対して、現在のクラウド環境がどの程度準拠しているかを継続的に評価できます。Google Cloudでは、Security Command Centerのセキュリティポスチャーサービスを利用することで、Google Cloud組織で準拠したいセキュリティポスチャーを定義・デプロイすることができ、定義したポスチャーからの変更を検知・対処することができます。

主な利点

セキュリティポスチャーサービスを活用することで、以下の目標を達成できます

利点 説明
基準への準拠確認 ワークロードがセキュリティ基準、コンプライアンス規制、組織のカスタム要件に適合していることを確認
事前のコントロール適用 リソースのデプロイ前にセキュリティ管理を実装(予防的コントロール)
継続的な監視 定義されたポスチャーからの逸脱(ドリフト)を検出・解決

サービスコンポーネント

セキュリティポスチャーサービスは、4つの主要コンポーネントで構成されています。

alt text

ポスチャー(Posture)

ポスチャーは、組織が必要とする予防的・検出的コントロールのポリシーセットです。セキュリティ要件を定義する最上位の単位となります。

ポリシーセット(Policy Set)

ポリシーセットは、特定のセキュリティ基準に必要なすべてのポリシーをグループ化したものです。例えば、「ISO 27001準拠用ポリシーセット」や「Cloud Storage用ポリシーセット」などがあります。

ポリシー(Policy)

ポリシーは、実際のセキュリティルールを定義する最小単位です。以下の2種類があります。

ポリシー種別 説明
Organization Policy制約 リソースの設定を強制する予防的コントロール パブリックアクセスの禁止、サービスアカウントキー作成の禁止
Security Health Analytics検出機能 セキュリティ問題を検出する検出的コントロール 暗号化の未設定検出、過剰な権限の検出

ポスチャーデプロイメント(Posture Deployment)

ポスチャーデプロイメントは、定義したポスチャーを組織・フォルダ・プロジェクトに適用するプロセスです。

alt text


ポスチャーテンプレート

Security Command Centerでは、セキュリティポスチャーをすぐに利用できる事前定義されたポスチャーテンプレートを提供しています。事前定義されたテンプレートを利用するだけでもかなり充実したガードレールを敷くことができると思います。
ここではいくつかのテンプレートを紹介したいと思います。

テンプレートの種類

secure_by_default_essential

一般的な設定ミスと既定設定によるセキュリティ問題を防止するテンプレートです。

Security Command Centerのコンソール上から確認することもできますし、以下のコマンドで確認することもできます。

gcloudコマンドでの確認
# テンプレートの内容を確認
gcloud scc posture-templates describe \
  organizations/OrganizationId/locations/global/postureTemplates/secure_by_default_essential \
  --revision-id=v.1.0

alt text
secure_by_default_essentialのテンプレート

含まれる主要ポリシー(16個)
secure_by_default_essentialポスチャーテンプレートの中には、各ポリシーが組織ポリシーで構成された1つのポリシーセット(Policy Set) が存在します。

policyId cannedConstraintId description
Disable service account key creation iam.disableServiceAccountKeyCreation サービスアカウントの認証情報が漏洩するリスクを減らすため、ユーザーがサービスアカウントの永続的なキーを作成できないようにします。
Disable Automatic IAM Grants for Default Service Accounts iam.automaticIamGrantsForDefaultServiceAccounts デフォルトのサービスアカウントが作成時に過度に権限の大きいIAMロール「編集者」を受け取らないようにします。
Disable Service Account Key Upload iam.disableServiceAccountKeyUpload サービスアカウントキーにおけるカスタムキーマテリアルの漏洩と再利用のリスクを回避します。
Enforce Public Access Prevention storage.publicAccessPrevention ストレージバケットが認証されていない公開アクセスに開放されるように設定できないようにします。
Enforce uniform bucket-level access storage.uniformBucketLevelAccess GCSバケットがアクセス提供にオブジェクト単位のACL(IAMポリシーとは別のシステム)を使用できないようにし、アクセス管理と監査の一貫性を強制します。
Require OS Login compute.requireOsLogin 新しく作成されるVMでOS Loginを必須にし、SSHキーの管理を容易にし、IAMポリシーによるリソースレベルの権限付与を提供し、ユーザーアクセスをログに記録します。
Disable VM serial port access compute.disableSerialPortAccess Compute Engine APIコントロールプレーンからのバックドアアクセスに使用される可能性のあるVMシリアルポートへのユーザーアクセスを防止します。
Restrict shared VPC project lien removal compute.restrictXpnProjectLienRemoval プロジェクトリーエンの削除を制限することで、共有VPCホストプロジェクトの誤削除を防止します。
Define allowed external IPs for VM instances compute.vmExternalIpAccess インターネットの受信と送信にさらされる可能性のある、パブリックIPを持つComputeインスタンスの作成を防止します。
Skip default network creation compute.skipDefaultNetworkCreation 各新規プロジェクトでのデフォルトVPCネットワークとデフォルトファイアウォールルールの自動作成を無効にし、ネットワークとファイアウォールルールが意図的に作成されるようにします。
Sets the internal DNS setting for new projects to Zonal DNS Only compute.setNewProjectDefaultToZonalDNSOnly アプリケーション開発者が、最新のDNS設定よりもサービス信頼性の低いレガシーDNS設定をコンピュートインスタンスに選択できないようにガードレールを設定します。
Restrict Public IP access on Cloud SQL instances sql.restrictPublicIp インターネットの受信と送信にさらされる可能性のある、パブリックIPを持つCloud SQLインスタンスの作成を防止します。
Restrict Authorized Networks on Cloud SQL instances sql.restrictAuthorizedNetworks パブリックまたは非RFC1918ネットワーク範囲からCloud SQLデータベースへのアクセスを防止します。
Restrict Protocol Forwarding Based on type of IP Address compute.restrictProtocolForwardingCreationForTypes 内部IPアドレスのみに対してVMプロトコル転送を許可します。
Disable VPC External IPv6 usage compute.disableVpcExternalIpv6 インターネットの受信と送信にさらされる可能性のある、外部IPv6サブネットの作成を防止します。
Disable VM nested virtualization compute.disableNestedVirtualization 監視されていないネストされたインスタンスによるセキュリティリスクを減らすため、ネストされた仮想化を無効にします。

ISO 27001テンプレート

ISO 27001国際標準に準拠する必要があるワークロード向けのテンプレートです。

こちらも同様にSecurity Command Centerのコンソール上から確認することもできますし、以下のコマンドで確認することもできます。

gcloudコマンドでの確認
# テンプレートの内容を確認
gcloud scc posture-templates describe \
  organizations/OrganizationId/locations/global/postureTemplates/iso_27001 \
  --revision-id=v.1.0

alt text
iso_27001のテンプレート

含まれる主要ポリシー(68個)
iso_27001ポスチャーテンプレートの中には、各ポリシーがSecurity health analyticsで構成された1つのポリシーセット(Policy Set) が存在します。

moduleName policyId
SQL_CROSS_DB_OWNERSHIP_CHAINING SQLクロスDB所有権チェーン
INSTANCE_OS_LOGIN_DISABLED インスタンスOSログイン無効
SQL_SKIP_SHOW_DATABASE_DISABLED SQLスキップショーデータベース無効
ESSENTIAL_CONTACTS_NOT_CONFIGURED 重要な連絡先が未設定
AUDIT_LOGGING_DISABLED 監査ログ無効
VPC_FLOW_LOGS_SETTINGS_NOT_RECOMMENDED VPCフローログ設定が非推奨
API_KEY_EXISTS APIキーが存在
SQL_LOG_MIN_ERROR_STATEMENT_SEVERITY SQLログ最小エラーステートメント重大度
LOCKED_RETENTION_POLICY_NOT_SET ロック済み保持ポリシー未設定
SQL_LOG_DISCONNECTIONS_DISABLED SQL切断ログ無効
COMPUTE_SERIAL_PORTS_ENABLED Computeシリアルポート有効
COMPUTE_PROJECT_WIDE_SSH_KEYS_ALLOWED Computeプロジェクト全体のSSHキー許可
KMS_KEY_NOT_ROTATED KMSキー未ローテーション
DNS_LOGGING_DISABLED DNSログ無効
SQL_LOCAL_INFILE SQLローカルインファイル
SQL_LOG_MIN_DURATION_STATEMENT_ENABLED SQLログ最小期間ステートメント有効
PUBLIC_DATASET 公開データセット
DISK_CSEK_DISABLED ディスクCSEK無効
SQL_USER_CONNECTIONS_CONFIGURED SQLユーザー接続設定済み
SERVICE_ACCOUNT_ROLE_SEPARATION サービスアカウントロール分離
AUDIT_CONFIG_NOT_MONITORED 監査設定が監視されていない
BUCKET_IAM_NOT_MONITORED バケットIAMが監視されていない
PUBLIC_SQL_INSTANCE 公開SQLインスタンス
AUTO_BACKUP_DISABLED 自動バックアップ無効
DATAPROC_CMEK_DISABLED Dataproc CMEK無効
LOG_NOT_EXPORTED ログがエクスポートされていない
KMS_PROJECT_HAS_OWNER KMSプロジェクトにオーナーが存在
KMS_ROLE_SEPARATION KMSロール分離
API_KEY_APIS_UNRESTRICTED APIキーのAPI制限なし
SQL_LOG_MIN_MESSAGES SQLログ最小メッセージ
SQL_PUBLIC_IP SQL公開IP
DATASET_CMEK_DISABLED データセットCMEK無効
FIREWALL_NOT_MONITORED ファイアウォールが監視されていない
SQL_LOG_STATEMENT SQLログステートメント
BIGQUERY_TABLE_CMEK_DISABLED BigQueryテーブルCMEK無効
CONFIDENTIAL_COMPUTING_DISABLED コンフィデンシャルコンピューティング無効
SQL_INSTANCE_NOT_MONITORED SQLインスタンスが監視されていない
KMS_PUBLIC_KEY KMS公開キー
DEFAULT_NETWORK デフォルトネットワーク
SQL_TRACE_FLAG_3625 SQLトレースフラグ3625
API_KEY_NOT_ROTATED APIキー未ローテーション
DNSSEC_DISABLED DNSSEC無効
SQL_LOG_CONNECTIONS_DISABLED SQL接続ログ無効
LEGACY_NETWORK レガシーネットワーク
PUBLIC_IP_ADDRESS 公開IPアドレス
FULL_API_ACCESS 完全なAPIアクセス
SQL_CONTAINED_DATABASE_AUTHENTICATION SQL包含データベース認証
OS_LOGIN_DISABLED OSログイン無効
SQL_USER_OPTIONS_CONFIGURED SQLユーザーオプション設定済み
ADMIN_SERVICE_ACCOUNT 管理者サービスアカウント
DEFAULT_SERVICE_ACCOUNT_USED デフォルトサービスアカウント使用
NETWORK_NOT_MONITORED ネットワークが監視されていない
PUBLIC_BUCKET_ACL 公開バケットACL
CUSTOM_ROLE_NOT_MONITORED カスタムロールが監視されていない
SQL_LOG_ERROR_VERBOSITY SQLログエラー詳細度
LOAD_BALANCER_LOGGING_DISABLED ロードバランサーログ無効
OVER_PRIVILEGED_SERVICE_ACCOUNT_USER 過剰権限サービスアカウントユーザー
SQL_REMOTE_ACCESS_ENABLED SQLリモートアクセス有効
RSASHA1_FOR_SIGNING 署名用RSASHA1
CLOUD_ASSET_API_DISABLED Cloud Asset API無効
BUCKET_POLICY_ONLY_DISABLED バケットポリシーのみ無効
ROUTE_NOT_MONITORED ルートが監視されていない
OWNER_NOT_MONITORED オーナーが監視されていない

ポスチャーを試してみた

実際にセキュリティポスチャーを作成・デプロイしてどのような動きをするのか確認してみたいと思います。

必要なAPIの有効化

まずは、セキュリティポスチャーを作成・デプロイするために以下のAPIを有効化していきます。

# Organization Policy ServiceとSecurity Posture APIを有効化
gcloud services enable orgpolicy.googleapis.com securityposture.googleapis.com

必要なIAMロール

ポスチャーの作成には以下のIAMロールが必要です。

  • セキュリティポスチャー管理者:roles/securityposture.admin

ポスチャーの作成方法

ポスチャーは3つの方法で作成できます。

  • ポスチャーテンプレートから作成
  • 既存環境から抽出
  • Terraformを利用して作成

今回は、ポスチャーテンプレートから作成していきたいと思います。

ポスチャーテンプレートから作成

# テンプレートの内容を確認し、yamlファイルに吐き出す。
gcloud scc posture-templates describe \
  organizations/OrganizationId/locations/global/postureTemplates/secure_by_default_essential \
  --revision-id=v.1.0 > posture.yaml

# テンプレートをベースにポスチャーを作成
gcloud scc postures create \
  organizations/OrganizationId/locations/global/postures/my-posture \
  --posture-from-file=posture.yaml

[Security Command Center] → [ポスチャー管理]を確認すると、コマンドで作成したmy-postureが作成されていることが確認できました。

alt text

my-postureをクリックすると、

  • 作成日
  • 更新日
  • ポリシーセット数
  • ポリシー数
  • 状態

等の情報を確認することができました。

alt text

ポスチャーのデプロイ

作成したポスチャーはプロジェクトフォルダ組織にデプロイすることができます。
デプロイすることにより、ポリシーとその定義を組織内の特定のリソースに適用し、ずれをモニタリングできるようになります。プロジェクト、フォルダ、組織にデプロイできるポスチャーは1つのみという制約があります。

今回は特定のプロジェクトにポスチャーをデプロイしてみたいと思います。

# 特定のプロジェクトにデプロイ
gcloud scc posture-deployments create \
  organizations/OrganizationId/locations/global/postureDeployments/postureDeployment \
  --posture-name=organizations/OrganizationId/locations/global/postures/my-posture \
  --posture-revision-id=c2248ea0 \
  --target-resource=projects/ProjectId

デプロイ後、my-postureのリソースタブにプロジェクトが紐づいていることが確認できます。
alt text

デプロイ状態の確認

ポスチャーのデプロイ状況は以下のコマンドで確認することができます。

# ポスチャーの状態を確認
gcloud scc postures describe \
  organizations/OrganizationId/locations/global/postures/my-posture

# デプロイメントの状態を確認
gcloud scc posture-deployments list \
  --location=global \
  --organization=OrganizationId

プロジェクトの適用状態の確認

my-postureを特定プロジェクトにデプロイした後に、特定プロジェクトの組織ポリシーを確認してみました。
my-postureのポリシーで設定してある組織ポリシーがすべて特定プロジェクトに親のポリシーをオーバライドする形で適用されていました。
このことから、ポスチャーを特定リソースにデプロイした際には、ポリシーで設定している組織ポリシーがデプロイ先に適用されることがわかりました。

alt text

ドリフト検出

ポスチャーをデプロイすると、定義されたポリシーからの逸脱(ドリフト)が自動的に検出されます。

my-postureのポリシーをデプロイしたプロジェクトに適用された組織ポリシー「compute.vmExternalIpAccess」を変更してみたいと思います。現状は、組織ポリシー「compute.vmExternalIpAccess」は親のポリシーをオーバライドする形で適用されており、プロジェクト内で新規に作成するVMはパブリックIPが付与できない状態です。

alt text

組織ポリシー「compute.vmExternalIpAccess」をクリックし、[ポリシーを管理]をクリックします。

alt text

ポリシーのソースを[親のポリシーを継承する]に変更し、[ポリシーを設定]をクリックします。

alt text

ポリシーのソースが[親のポリシーを継承する]に変更になっています。
これにより、プロジェクト内で新規に作成するVMはパブリックIPが付与できてしまう状態になってしまいました。

alt text

この状態で、Security Command Centerの[検出結果]のコンソールに移動し、以下のクエリを実行してセキュリティポスチャーのポリシーに違反(ドリフト)したものが確認できます。
[Security posture policy delete]というカテゴリでドリフトが検出されていました。

state="ACTIVE" AND NOT mute="MUTED" AND finding_class="POSTURE_VIOLATION"

alt text

詳細を確認すると、「compute.vmExternalIpAccess」が変更されたログがJson形式で確認することができます。

{
  "finding": {
    "name": "organizations/***MASKED***/sources/***MASKED***/locations/global/findings/***MASKED***",
    "parent": "organizations/***MASKED***/sources/***MASKED***/locations/global",
    "resourceName": "//cloudresourcemanager.googleapis.com/projects/***MASKED***",
    "state": "INACTIVE",
    "category": "SECURITY_POSTURE_POLICY_DELETE",
    "externalUri": "",
    "sourceProperties": [
      {
        "key": "changed_policy",
        "value": "//orgpolicy.googleapis.com/projects/***MASKED***/policies/compute.vmExternalIpAccess"
      },
      {
        "key": "policy_drift_details",
        "value": []
      },
      {
        "key": "name",
        "value": "my-posture"
      },
      {
        "key": "revision_id",
        "value": "***MASKED***"
      },
      {
        "key": "posture_deployment_resource",
        "value": "projects/***MASKED***"
      },
      {
        "key": "posture_deployment",
        "value": "postureDeployment"
      }
    ],
    "securityMarks": {
      "name": "organizations/***MASKED***/sources/***MASKED***/locations/global/findings/***MASKED***/securityMarks",
      "marks": []
    },
    "eventTime": "2025-12-23T01:05:14.700Z",
    "createTime": "2025-12-23T00:57:16.726Z",
    "severity": "MEDIUM",
    "canonicalName": "projects/***MASKED***/sources/***MASKED***/locations/global/findings/***MASKED***",
    "mute": "UNDEFINED",
    "findingClass": "POSTURE_VIOLATION",
    "launchState": "LAUNCH_STATE_GENERAL_AVAILABILITY",
    "indicator": {
      "ipAddresses": [],
      "domains": [],
      "signatures": [],
      "uris": []
    },
    "dataProtectionKeyGovernance": {
      "violations": []
    },
    "vertexAi": {
      "datasets": [],
      "pipelines": []
    },
    "muteUpdateTime": "1970-01-01T00:00:00Z",
    "muteInitiator": "",
    "muteInfo": {
      "staticMute": {
        "state": "UNDEFINED",
        "applyTime": "1970-01-01T00:00:00Z"
      },
      "dynamicMuteRecords": []
    },
    "contacts": [],
    "externalSystems": [],
    "access": {
      "principalEmail": "",
      "callerIp": "",
      "callerIpGeo": {
        "regionCode": ""
      },
      "userAgent": "",
      "userAgentFamily": "",
      "serviceName": "",
      "methodName": "",
      "principalSubject": "",
      "serviceAccountKeyName": "",
      "serviceAccountDelegationInfo": [],
      "userName": ""
    },
    "mitreAttack": {
      "primaryTactic": "TACTIC_UNSPECIFIED",
      "primaryTechniques": [],
      "additionalTactics": [],
      "additionalTechniques": [],
      "version": ""
    },
    "description": "",
    "compliances": [],
    "iamBindings": [],
    "nextSteps": "",
    "connections": [],
    "exfiltration": {
      "sources": [],
      "targets": [],
      "totalExfiltratedBytes": "0"
    },
    "processes": [],
    "containers": [],
    "kubernetes": {
      "pods": [],
      "nodes": [],
      "nodePools": [],
      "roles": [],
      "bindings": [],
      "accessReviews": [],
      "objects": []
    },
    "parentDisplayName": "Security Posture",
    "moduleName": "",
    "vulnerability": {
      "cve": {
        "id": "",
        "references": [],
        "cvssv3": {
          "baseScore": 0,
          "attackVector": "ATTACK_VECTOR_UNSPECIFIED",
          "attackComplexity": "ATTACK_COMPLEXITY_UNSPECIFIED",
          "privilegesRequired": "PRIVILEGES_REQUIRED_UNSPECIFIED",
          "userInteraction": "USER_INTERACTION_UNSPECIFIED",
          "scope": "SCOPE_UNSPECIFIED",
          "confidentialityImpact": "IMPACT_UNSPECIFIED",
          "integrityImpact": "IMPACT_UNSPECIFIED",
          "availabilityImpact": "IMPACT_UNSPECIFIED"
        },
        "upstreamFixAvailable": false,
        "impact": "RISK_RATING_UNSPECIFIED",
        "exploitationActivity": "EXPLOITATION_ACTIVITY_UNSPECIFIED",
        "observedInTheWild": false,
        "zeroDay": false,
        "exploitReleaseDate": "1970-01-01T00:00:00Z",
        "firstExploitationDate": "1970-01-01T00:00:00Z"
      },
      "offendingPackage": {
        "packageName": "",
        "cpeUri": "",
        "packageType": "",
        "packageVersion": ""
      },
      "fixedPackage": {
        "packageName": "",
        "cpeUri": "",
        "packageType": "",
        "packageVersion": ""
      },
      "securityBulletin": {
        "bulletinId": "",
        "submissionTime": "1970-01-01T00:00:00Z",
        "suggestedUpgradeVersion": ""
      }
    },
    "database": {
      "name": "",
      "displayName": "",
      "userName": "",
      "query": "",
      "grantees": [],
      "version": ""
    },
    "dataAccessEvents": [],
    "dataFlowEvents": [],
    "dataRetentionDeletionEvents": [],
    "attackExposure": {
      "score": 0,
      "latestCalculationTime": "1970-01-01T00:00:00Z",
      "attackExposureResult": "",
      "state": "STATE_UNSPECIFIED",
      "exposedHighValueResourcesCount": 0,
      "exposedMediumValueResourcesCount": 0,
      "exposedLowValueResourcesCount": 0
    },
    "files": [],
    "orgPolicies": [],
    "ipRules": {
      "direction": "DIRECTION_UNSPECIFIED",
      "allowed": {
        "ipRules": []
      },
      "denied": {
        "ipRules": []
      },
      "sourceIpRanges": [],
      "destinationIpRanges": [],
      "exposedServices": []
    },
    "kernelRootkit": {
      "name": "",
      "unexpectedCodeModification": false,
      "unexpectedReadOnlyDataModification": false,
      "unexpectedFtraceHandler": false,
      "unexpectedKprobeHandler": false,
      "unexpectedKernelCodePages": false,
      "unexpectedSystemCallHandler": false,
      "unexpectedInterruptHandler": false,
      "unexpectedProcessesInRunqueue": false
    },
    "backupDisasterRecovery": {
      "backupTemplate": "",
      "policies": [],
      "host": "",
      "applications": [],
      "storagePool": "",
      "policyOptions": [],
      "profile": "",
      "appliance": "",
      "backupType": "",
      "backupCreateTime": "1970-01-01T00:00:00Z"
    },
    "apigee": {
      "organization": "",
      "environment": "",
      "securityProfileId": ""
    },
    "disk": {
      "name": ""
    },
    "risks": [],
    "loadBalancers": [],
    "deactivationReason": {
      "reason": "REASON_UNSPECIFIED"
    },
    "domains": [],
    "affectedResources": {
      "count": "0"
    },
    "aiModel": {
      "name": "",
      "domain": "",
      "library": "",
      "location": "",
      "publisher": "",
      "deploymentPlatform": "DEPLOYMENT_PLATFORM_UNSPECIFIED",
      "displayName": "",
      "usageCategory": ""
    },
    "cloudDlpInspection": {
      "inspectJob": "",
      "infoType": "",
      "infoTypeCount": "0",
      "fullScan": false
    },
    "caiResource": "",
    "cloudDlpDataProfile": {
      "dataProfile": ""
    },
    "application": {
      "baseUri": "",
      "fullUri": ""
    },
    "securityPosture": {
      "name": "my-posture",
      "revisionId": "***MASKED***",
      "policyDriftDetails": [],
      "policySet": "SecureByDefault preventative policy set",
      "postureDeploymentResource": "projects/***MASKED***",
      "postureDeployment": "postureDeployment",
      "changedPolicy": "//orgpolicy.googleapis.com/projects/***MASKED***/policies/compute.vmExternalIpAccess"
    },
    "logEntries": [],
    "cloudArmor": {
      "securityPolicy": {
        "name": "",
        "type": "",
        "preview": false
      },
      "requests": {
        "ratio": 0,
        "shortTermAllowed": 0,
        "longTermAllowed": 0,
        "longTermDenied": 0
      },
      "adaptiveProtection": {
        "confidence": 0
      },
      "attack": {
        "volumePps": 0,
        "volumeBps": 0,
        "classification": ""
      },
      "threatVector": "",
      "duration": "0s"
    },
    "notebook": {
      "name": "",
      "service": "",
      "lastAuthor": "",
      "notebookUpdateTime": "1970-01-01T00:00:00Z"
    },
    "toxicCombination": {
      "attackExposureScore": 0,
      "relatedFindings": []
    },
    "groupMemberships": [],
    "networks": [],
    "chokepoint": {
      "relatedFindings": []
    },
    "remediationDetails": {
      "remediationIntent": "",
      "repositoryUri": "",
      "pullRequestUri": "",
      "remediationExplanation": "",
      "remediationState": "REMEDIATION_STATE_UNSPECIFIED",
      "remediationError": "",
      "prGenerationTime": "1970-01-01T00:00:00Z",
      "owner": ""
    },
    "artifactGuardPolicies": {
      "resourceId": "",
      "failingPolicies": []
    },
    "secret": {
      "type": "",
      "status": {
        "lastUpdatedTime": "1970-01-01T00:00:00Z",
        "validity": "SECRET_VALIDITY_UNSPECIFIED"
      },
      "environmentVariable": {
        "key": ""
      },
      "filePath": {
        "path": ""
      }
    },
    "complianceDetails": {
      "frameworks": [],
      "cloudControl": {
        "cloudControlName": "",
        "type": "CLOUD_CONTROL_TYPE_UNSPECIFIED",
        "policyType": "",
        "version": 0
      },
      "cloudControlDeploymentNames": []
    }
  },
  "resource": {
    "name": "//cloudresourcemanager.googleapis.com/projects/***MASKED***",
    "displayName": "***MASKED***",
    "type": "google.cloud.resourcemanager.Project",
    "cloudProvider": "GOOGLE_CLOUD_PLATFORM",
    "service": "cloudresourcemanager.googleapis.com",
    "location": "",
    "gcpMetadata": {
      "project": "//cloudresourcemanager.googleapis.com/projects/***MASKED***",
      "projectDisplayName": "***MASKED***",
      "parent": "//cloudresourcemanager.googleapis.com/folders/***MASKED***",
      "parentDisplayName": "***MASKED***",
      "folders": [
        {
          "resourceFolder": "//cloudresourcemanager.googleapis.com/folders/***MASKED***",
          "resourceFolderDisplayName": "***MASKED***"
        }
      ],
      "organization": "organizations/***MASKED***"
    },
    "awsMetadata": {
      "organization": {
        "id": ""
      },
      "organizationalUnits": [],
      "account": {
        "id": "",
        "name": ""
      }
    },
    "azureMetadata": {
      "tenant": {
        "id": "",
        "displayName": ""
      },
      "managementGroups": [],
      "subscription": {
        "id": "",
        "displayName": ""
      },
      "resourceGroup": {
        "name": ""
      }
    },
    "resourcePath": {
      "nodes": [
        {
          "nodeType": "GCP_PROJECT",
          "id": "projects/***MASKED***",
          "displayName": "***MASKED***"
        },
        {
          "nodeType": "GCP_FOLDER",
          "id": "folders/***MASKED***",
          "displayName": "***MASKED***"
        },
        {
          "nodeType": "GCP_ORGANIZATION",
          "id": "organizations/***MASKED***",
          "displayName": ""
        }
      ]
    },
    "resourcePathString": "organizations/***MASKED***/folders/***MASKED***/projects/***MASKED***",
    "application": {
      "name": "",
      "attributes": {
        "criticality": {
          "type": "CRITICALITY_TYPE_UNSPECIFIED"
        },
        "environment": {
          "type": "ENVIRONMENT_TYPE_UNSPECIFIED"
        },
        "developerOwners": [],
        "operatorOwners": [],
        "businessOwners": []
      }
    }
  }
}

ポスチャーの削除

ポスチャーを削除したい場合は、まずリソースに対するデプロイを削除する必要があります。
以下のコマンドで、デプロイを削除することができます。

gcloud scc posture-deployments delete \
    organizations/OrganizationId/locations/global/postureDeployments/postureDeployment

コンソール上では、my-postureのリソースタブから削除することができます。
alt text

次に、ポスチャー自体を削除していきます。
以下のコマンドで、ポスチャーを削除します。

 gcloud scc postures delete \
     organizations/OrganizationId/locations/global/postures/my-posture

コンソール上では、my-postureの詳細画面から削除することができます。
alt text

IaC検証との連携

セキュリティポスチャーは、IaC(Infrastructure as Code)検証機能とも連携できます。この機能を使うことで、Terraformコードをデプロイする前に、ポスチャーで定義したポリシーに違反していないかを事前に検証できます。こちらに関しては別の機会に検証してみたいと思います。

IaC検証の仕組み

IaC検証では、Terraform Planファイル(JSON形式)を入力として、組織にデプロイされているポスチャーのポリシー(Organization Policy制約およびSecurity Health Analytics検出器)と照合します。違反が検出された場合はレポートとして出力され、重要度に応じてビルドを失敗させることも可能です。

これにより、本番環境へのデプロイ前にセキュリティ問題を発見・修正できる「シフトレフト」アプローチを実現できます。

CI/CDパイプラインとの統合

IaC検証は、主要なCI/CDツールとの統合がサポートされています。

ツール 概要
Cloud Build cloudbuild.yamlにIaC検証ステップを追加することで、ビルドプロセスに組み込み可能
GitHub Actions Google公式のActionを使用して、プルリクエスト時に自動検証
Jenkins Google Analyze Code Securityプラグインを使用して統合

利用時の注意点

IaC検証を利用するには、Security Posture Shift-Left Validator(roles/securityposture.shiftLeftValidator)のIAMロールが必要です。また、現時点ではTerraform Planファイルのみが対応しており、他のIaCツール(Pulumiなど)には対応していません。

さいごに

今回は、Security Command Center Premiumが提供するセキュリティポスチャー機能についての解説と検証を行いました。

セキュリティポスチャー機能のテンプレートを使用して、リソースに適用することですぐにセキュリティ標準、コンプライアンス規制、組織のカスタム セキュリティ要件に準拠していることを確認できる点はよいと思いました。

既存の組織ポリシーを導入済みでSecurity Health Analyticsがうまく機能している場合、セキュリティポスチャーは「それらをまとめて宣言的に管理し、ドリフトを自動検知する上位レイヤー」として導入するのが効果的なのかなと思いました。

使いこなせる場合は非常に便利なサービスになると思います。

この記事が誰かの助けになれば幸いです。

以上、クラウド事業本部コンサルティング部の渡邉でした!

この記事をシェアする

FacebookHatena blogX

関連記事