Security Command Centerのセキュリティポスチャー機能を使ってみた
はじめに
メリークリスマス!
クラウド事業本部コンサルティング部の渡邉です。
Security Command Center Premiumについて、以下の記事で解説・有効化していきました。
クラウド環境のセキュリティ管理は、組織の規模が大きくなるにつれて複雑さを増していきます。Google CloudのSecurity Command Center Premiumが提供するセキュリティポスチャー機能は、組織全体のセキュリティ状態を一元的に定義・管理・監視できる強力なソリューションです。
本記事では、セキュリティポスチャーの概要から実際の利用方法まで解説します。
セキュリティポスチャーの概要
セキュリティポスチャーとは
セキュリティポスチャーは、クラウド資産のセキュリティ状態を定義・管理する機能です。組織が定義したセキュリティベンチマークに対して、現在のクラウド環境がどの程度準拠しているかを継続的に評価できます。Google Cloudでは、Security Command Centerのセキュリティポスチャーサービスを利用することで、Google Cloud組織で準拠したいセキュリティポスチャーを定義・デプロイすることができ、定義したポスチャーからの変更を検知・対処することができます。
主な利点
セキュリティポスチャーサービスを活用することで、以下の目標を達成できます
| 利点 | 説明 |
|---|---|
| 基準への準拠確認 | ワークロードがセキュリティ基準、コンプライアンス規制、組織のカスタム要件に適合していることを確認 |
| 事前のコントロール適用 | リソースのデプロイ前にセキュリティ管理を実装(予防的コントロール) |
| 継続的な監視 | 定義されたポスチャーからの逸脱(ドリフト)を検出・解決 |
サービスコンポーネント
セキュリティポスチャーサービスは、4つの主要コンポーネントで構成されています。

ポスチャー(Posture)
ポスチャーは、組織が必要とする予防的・検出的コントロールのポリシーセットです。セキュリティ要件を定義する最上位の単位となります。
ポリシーセット(Policy Set)
ポリシーセットは、特定のセキュリティ基準に必要なすべてのポリシーをグループ化したものです。例えば、「ISO 27001準拠用ポリシーセット」や「Cloud Storage用ポリシーセット」などがあります。
ポリシー(Policy)
ポリシーは、実際のセキュリティルールを定義する最小単位です。以下の2種類があります。
| ポリシー種別 | 説明 | 例 |
|---|---|---|
| Organization Policy制約 | リソースの設定を強制する予防的コントロール | パブリックアクセスの禁止、サービスアカウントキー作成の禁止 |
| Security Health Analytics検出機能 | セキュリティ問題を検出する検出的コントロール | 暗号化の未設定検出、過剰な権限の検出 |
ポスチャーデプロイメント(Posture Deployment)
ポスチャーデプロイメントは、定義したポスチャーを組織・フォルダ・プロジェクトに適用するプロセスです。

ポスチャーテンプレート
Security Command Centerでは、セキュリティポスチャーをすぐに利用できる事前定義されたポスチャーテンプレートを提供しています。事前定義されたテンプレートを利用するだけでもかなり充実したガードレールを敷くことができると思います。
ここではいくつかのテンプレートを紹介したいと思います。
テンプレートの種類
secure_by_default_essential
一般的な設定ミスと既定設定によるセキュリティ問題を防止するテンプレートです。
Security Command Centerのコンソール上から確認することもできますし、以下のコマンドで確認することもできます。
# テンプレートの内容を確認
gcloud scc posture-templates describe \
organizations/OrganizationId/locations/global/postureTemplates/secure_by_default_essential \
--revision-id=v.1.0

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 scc posture-templates describe \
organizations/OrganizationId/locations/global/postureTemplates/iso_27001 \
--revision-id=v.1.0

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が作成されていることが確認できました。

my-postureをクリックすると、
- 作成日
- 更新日
- ポリシーセット数
- ポリシー数
- 状態
等の情報を確認することができました。

ポスチャーのデプロイ
作成したポスチャーはプロジェクト、フォルダ、組織にデプロイすることができます。
デプロイすることにより、ポリシーとその定義を組織内の特定のリソースに適用し、ずれをモニタリングできるようになります。プロジェクト、フォルダ、組織にデプロイできるポスチャーは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のリソースタブにプロジェクトが紐づいていることが確認できます。

デプロイ状態の確認
ポスチャーのデプロイ状況は以下のコマンドで確認することができます。
# ポスチャーの状態を確認
gcloud scc postures describe \
organizations/OrganizationId/locations/global/postures/my-posture
# デプロイメントの状態を確認
gcloud scc posture-deployments list \
--location=global \
--organization=OrganizationId
プロジェクトの適用状態の確認
my-postureを特定プロジェクトにデプロイした後に、特定プロジェクトの組織ポリシーを確認してみました。
my-postureのポリシーで設定してある組織ポリシーがすべて特定プロジェクトに親のポリシーをオーバライドする形で適用されていました。
このことから、ポスチャーを特定リソースにデプロイした際には、ポリシーで設定している組織ポリシーがデプロイ先に適用されることがわかりました。

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

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

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

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

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

詳細を確認すると、「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のリソースタブから削除することができます。

次に、ポスチャー自体を削除していきます。
以下のコマンドで、ポスチャーを削除します。
gcloud scc postures delete \
organizations/OrganizationId/locations/global/postures/my-posture
コンソール上では、my-postureの詳細画面から削除することができます。

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がうまく機能している場合、セキュリティポスチャーは「それらをまとめて宣言的に管理し、ドリフトを自動検知する上位レイヤー」として導入するのが効果的なのかなと思いました。
使いこなせる場合は非常に便利なサービスになると思います。
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部コンサルティング部の渡邉でした!






