Governance, Security and Compliance

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

See the section bibliography for the reference material consulted while preparing these pages.

Commands and behaviour below are current for the gcloud CLI 586.x line and the product documentation as checked on 2026-09-30; launch stages, tier names and dates in this area change often, so re-verify them against gcloud version, the release notes and the linked reference pages before relying on them. Most of the controls on this page work at the organization level, so a standalone project (for example a personal one created from the free trial) can only try the project-scoped parts: audit logs, Cloud Asset Inventory and the project-level org policies.

Identity and Access Management decides who may call an API; this page is about the guard rails around that decision. Governance answers "what is allowed to exist here at all" (Organization Policy), "what do we have and who can reach it" (Cloud Asset Inventory), "who did what" (Cloud Audit Logs), "what is misconfigured or under attack" (Security Command Center), "can data leave" (VPC Service Controls) and "can we prove it to an auditor" (Assured Workloads and the compliance resources). For the Bookshelf application (see Google Cloud) these are the controls that stop a developer from creating a service-account key, a bucket in the wrong region or an unreviewed public service, and that tell the platform team when it happens anyway.

The layers of control

No single product covers all of it. The controls are preventive (they refuse an action), detective (they report it) or evidential (they prove what happened), and they stack on top of the IAM policies described in Identity and Access.

Control Question it answers Kind

Organization Policy

Which configurations may be created at all (regions, service-account keys, public IPs)?

Preventive

IAM deny policies and Principal Access Boundary

Which principals are denied even when a role would allow them?

Preventive

VPC Service Controls

Can data in a protected service be read or copied from outside a perimeter?

Preventive

Cloud Asset Inventory

What resources and IAM bindings exist, now and in the past?

Detective

Security Command Center

Which findings (misconfigurations, vulnerabilities, threats) are open?

Detective

Cloud Audit Logs

Which principal called which API, when and from where?

Evidential

Assured Workloads, Access Approval, compliance reports

Does the environment meet a stated regime, and what did Google staff access?

Evidential and preventive

flowchart LR DEV[Developer or pipeline] --> API[Google Cloud API request] API --> IAM{IAM allow and deny} IAM --> ORG{Organization Policy} ORG --> VPCSC{VPC Service Controls} VPCSC --> RES[Resource change] RES --> AUDIT[Cloud Audit Logs] RES --> CAI[Cloud Asset Inventory] AUDIT --> SCC[Security Command Center] CAI --> SCC

Each gate can refuse the request; every request that gets through is recorded. The order shown is conceptual: the services evaluate independently and a denial from any of them wins.

Organization Policy

The Organization Policy Service applies constraints to a node of the resource hierarchy (organization, folder or project) and everything below it. A constraint is not a permission: even a principal with roles/owner cannot create a resource that violates an enforced constraint. The basics (how policies inherit, the secure-by-default set that organizations created on or after 2024-05-03 receive, and the list of managed constraints) are in Resource Hierarchy and Projects. This section adds the parts that matter for a governance programme: dry-run mode and custom constraints.

Dry-run first

A policy has a spec (enforced) and a dryRunSpec (evaluated and logged, never enforced). Roll a new constraint out with dryRunSpec only, read the audit-log entries it would have refused, fix the offenders, and then promote it to spec.

Custom constraints

When no managed constraint expresses a rule, you define your own with a Common Expression Language (CEL) condition over the fields of one resource type, a list of methods (CREATE, UPDATE) and an action (ALLOW or DENY). Custom constraints exist at the organization level and are then enforced with an ordinary policy. Only some services and resource types support them; the supported list is in the documentation.

Tags for conditional enforcement

A policy rule can apply only to resources carrying a given tag (a key-value pair defined at the organization, as opposed to a label), so one folder can hold both a strict and a relaxed environment.

In the Google Cloud console

  1. Open IAM & Admin → Organization Policies and select the organization, folder or project in the picker.

  2. Filter the list for a constraint (for example Restrict resource service usage) and open it.

  3. Click Manage policy, choose Override parent’s policy (or Merge with parent), add a rule (Enforce, or the allowed and denied values for a list constraint) and optionally a condition on a tag.

  4. To test safely, click Test changes (or Set dry run policy) and save; the constraint is evaluated and logged but not enforced.

  5. For a custom constraint, open the Custom constraints tab, click Create custom constraint, pick the resource type and methods, write the CEL condition and choose Deny or Allow.

With the gcloud CLI

gcloud services enable orgpolicy.googleapis.com cloudresourcemanager.googleapis.com

PROJECT_ID=$(gcloud config get-value project)
ORG_ID=$(gcloud organizations list --format='value(ID)' --limit=1)

# Which constraints exist, and what is in force on the project?
gcloud org-policies list --project="$PROJECT_ID"
gcloud org-policies list-custom-constraints --organization="$ORG_ID"

# Roll out a location constraint in dry-run mode only
cat > location-dry-run.yaml <<YAML
name: projects/$PROJECT_ID/policies/gcp.resourceLocations
dryRunSpec:
  rules:
  - values:
      allowedValues:
      - in:us-locations
YAML
gcloud org-policies set-policy location-dry-run.yaml

# A custom constraint: Compute Engine instances must be named bookshelf-*
cat > constraint-name-prefix.yaml <<YAML
name: organizations/$ORG_ID/customConstraints/custom.vmNamePrefix
resourceTypes:
- compute.googleapis.com/Instance
methodTypes:
- CREATE
condition: "resource.name.startsWith('bookshelf-')"
actionType: ALLOW
displayName: Instances must be named bookshelf-*
description: Only instances whose name starts with bookshelf- may be created.
YAML
gcloud org-policies set-custom-constraint constraint-name-prefix.yaml

# Enforce it on one project
cat > policy-name-prefix.yaml <<YAML
name: projects/$PROJECT_ID/policies/custom.vmNamePrefix
spec:
  rules:
  - enforce: true
YAML
gcloud org-policies set-policy policy-name-prefix.yaml

# Reading what a policy resolves to after inheritance
gcloud org-policies describe gcp.resourceLocations \
  --project="$PROJECT_ID" --effective

Dry-run violations are written to the audit logs of the affected resource, so the audit-log query in the next sections finds them. The principal that manages policies needs roles/orgpolicy.policyAdmin; managing custom constraints needs roles/orgpolicy.policyAdmin as well, granted on the organization.

Cloud Asset Inventory

Cloud Asset Inventory keeps a time-series database of your resources and IAM policies, with about five weeks of history. It has four jobs: search, export, history and real-time notification, plus an analysis API that answers "who can reach this resource".

Search

search-all-resources finds resources across projects by name, label, location or free text, and search-all-iam-policies finds bindings, for example every policy granting access to allUsers. Both take a scope (an organization, folder or project) and use one query language, so a single call can span many projects.

Export

A snapshot of every resource or IAM policy at a point in time goes to a Cloud Storage object or to a BigQuery table, where it can be joined with other data. This is the usual feed for a compliance dashboard.

History and feeds

get-history returns how a resource changed over a window; a feed publishes a Pub/Sub message whenever a matching asset changes, which is how you trigger a function when someone creates a public bucket.

Policy analysis

analyze-iam-policy answers "which principals have this permission on this resource", expanding groups and inherited bindings.

In the Google Cloud console

  1. Open IAM & Admin → Asset Inventory (or search for Cloud Asset Inventory) with the scope picker set to the organization, folder or project.

  2. On the Resource tab, filter by asset type, location, label or free text; click a row to see its configuration.

  3. On the IAM policy tab, filter for a principal or role to see every resource where it holds a binding.

  4. Use Export to send the current view to a BigQuery table or a Cloud Storage object.

  5. Under IAM & Admin → Policy Analyzer, enter a principal or a resource and a permission to run an analysis query.

With the gcloud CLI

gcloud services enable cloudasset.googleapis.com bigquery.googleapis.com pubsub.googleapis.com

PROJECT_ID=$(gcloud config get-value project)
REGION=us-central1

# Which Cloud Storage buckets exist in the project, and where?
gcloud asset search-all-resources \
  --scope="projects/$PROJECT_ID" \
  --asset-types="storage.googleapis.com/Bucket" \
  --format="table(name,location,labels)"

# Which resources are publicly readable?
gcloud asset search-all-iam-policies \
  --scope="projects/$PROJECT_ID" \
  --query="policy:allUsers OR policy:allAuthenticatedUsers" \
  --format="table(resource,policy.bindings.role)"

# Snapshot every resource into BigQuery for reporting
bq mk --dataset --location=US "$PROJECT_ID:asset_export"
gcloud asset export \
  --project="$PROJECT_ID" \
  --content-type=resource \
  --bigquery-dataset="projects/$PROJECT_ID/datasets/asset_export" \
  --bigquery-table=resources \
  --output-bigquery-force

# A feed: publish every bucket or service-account change to a topic
gcloud pubsub topics create asset-changes
gcloud asset feeds create bookshelf-feed \
  --project="$PROJECT_ID" \
  --content-type=resource \
  --asset-types="storage.googleapis.com/Bucket,iam.googleapis.com/ServiceAccount" \
  --pubsub-topic="projects/$PROJECT_ID/topics/asset-changes"

# Who can read objects in the uploads bucket?
BUCKET=bookshelf-uploads-$PROJECT_ID
gcloud asset analyze-iam-policy \
  --project="$PROJECT_ID" \
  --full-resource-name="//storage.googleapis.com/projects/_/buckets/$BUCKET" \
  --permissions="storage.objects.get" \
  --expand-groups

The feed in the example is only a name; the Pub/Sub topic is the integration point, and a Cloud Run function subscribed to it (see Cloud Run Functions and Events) can revoke a public binding automatically. In the BigQuery export, a query such as "all buckets without the env label" is a plain SQL WHERE over the resource.data column.

Cloud Audit Logs

Cloud Audit Logs record administrative activity and data access for almost every Google Cloud service. They are the evidence layer for everything else on this page.

Log type What it records On by default Retention in its default bucket

Admin Activity

API calls that modify configuration or metadata (create a bucket, change an IAM policy)

Always on, cannot be disabled, no charge

400 days (_Required bucket)

System Event

Google-initiated changes (live migration, for example)

Always on, cannot be disabled, no charge

400 days (_Required bucket)

Data Access

Reads of configuration or user data (DATA_READ), writes of user data (DATA_WRITE) and ADMIN_READ

Off by default except for BigQuery; you enable it per service

30 days (_Default bucket), configurable

Policy Denied

Requests refused by a security policy (VPC Service Controls, an org policy, a deny policy)

On by default

30 days (_Default bucket)

Two consequences follow. First, Admin Activity logs answer most "who changed this" questions without any setup. Second, Data Access logs can be voluminous and are billed as ordinary log ingestion, so enable them selectively: for Secret Manager and Cloud KMS by default on any production project, and for Cloud Storage only on the buckets that hold regulated data.

Audit logs are ordinary log entries stored in Cloud Logging, so every logging feature applies: the Logs Explorer, log buckets with custom retention, sinks to Cloud Storage, BigQuery or Pub/Sub, and aggregated sinks that collect the logs of a whole organization. Logging in general, including log-based metrics, is in Monitoring and Observability.

In the Google Cloud console

  1. Open IAM & Admin → Audit Logs, select the project (or organization) and, in the table, tick a service such as Cloud Storage.

  2. In the side panel, tick Admin Read, Data Read and/or Data Write and optionally add exempted principals (for example a monitoring service account whose reads would otherwise dominate), then Save.

  3. To read the entries, open Logging → Logs Explorer, enter a query such as logName:"cloudaudit.googleapis.com" and a time range, or filter by Log name in the field panel.

  4. To keep them longer or elsewhere, open Logging → Log Router → Create sink and choose a Cloud Storage bucket, a BigQuery dataset or a log bucket as the destination.

With the gcloud CLI

gcloud services enable logging.googleapis.com

PROJECT_ID=$(gcloud config get-value project)

# Read the last Admin Activity entries, newest first
gcloud logging read \
  "logName=\"projects/$PROJECT_ID/logs/cloudaudit.googleapis.com%2Factivity\"" \
  --project="$PROJECT_ID" --freshness=1d --limit=20 \
  --format="table(timestamp,protoPayload.authenticationInfo.principalEmail,protoPayload.methodName,protoPayload.resourceName)"

# Who changed an IAM policy in the last week?
gcloud logging read \
  'protoPayload.methodName="SetIamPolicy" AND logName:"cloudaudit.googleapis.com%2Factivity"' \
  --project="$PROJECT_ID" --freshness=7d --limit=20

# Enable Data Access logs for Secret Manager and Cloud Storage
gcloud projects get-iam-policy "$PROJECT_ID" --format=yaml > policy.yaml
cat >> policy.yaml <<'YAML'
auditConfigs:
- service: secretmanager.googleapis.com
  auditLogConfigs:
  - logType: ADMIN_READ
  - logType: DATA_READ
  - logType: DATA_WRITE
- service: storage.googleapis.com
  auditLogConfigs:
  - logType: DATA_READ
    exemptedMembers:
    - serviceAccount:catalog-api@my-project-id.iam.gserviceaccount.com
YAML
gcloud projects set-iam-policy "$PROJECT_ID" policy.yaml

# Archive audit logs from the whole project into a locked-down bucket
AUDIT_BUCKET=bookshelf-audit-$PROJECT_ID
gcloud storage buckets create "gs://$AUDIT_BUCKET" --location=us-central1 \
  --uniform-bucket-level-access --public-access-prevention
gcloud logging sinks create audit-archive \
  "storage.googleapis.com/$AUDIT_BUCKET" \
  --log-filter='logName:"cloudaudit.googleapis.com"'
# Grant the sink's writer identity the right to write
WRITER=$(gcloud logging sinks describe audit-archive --format='value(writerIdentity)')
gcloud storage buckets add-iam-policy-binding "gs://$AUDIT_BUCKET" \
  --member="$WRITER" --role="roles/storage.objectCreator"

The get-iam-policy / set-iam-policy round trip replaces the whole project policy, so run it from the policy you just read, and keep the etag field in the file untouched; if someone changed the policy in between, the write fails instead of overwriting. For an organization, create the same sink with --organization=$ORG_ID --include-children so projects created tomorrow are covered too. Log buckets can additionally be locked with a retention policy so that no one, including project owners, can shorten the retention period; use that for regimes that require immutable evidence.

Security Command Center

Security Command Center (SCC) is the security posture and threat detection service: it aggregates findings from built-in detectors, from Cloud Asset Inventory and from partner products into one place, ranks them, and lets you mute, assign and export them. It is activated at the organization level.

Tiers

SCC is sold in three tiers. Standard is the free baseline (a limited set of vulnerability and misconfiguration findings, with the ability to see findings only). Premium adds the full detector set, compliance reporting and attack-path simulation, billed on the usage of the protected environment. Enterprise adds multicloud coverage (AWS and Azure), case management and SOAR playbooks. Google’s documentation states that the Enterprise tier is sunsetting, with 2027-05-21 as the date shown when this page was checked; re-verify the date and the tier you will actually be offered before you buy, because the packaging has changed several times since SCC launched.

Detectors

The built-in services group by what they look at. Security Health Analytics scans resources for misconfigurations such as a public bucket, an open firewall or a user-managed service-account key. Event Threat Detection reads Cloud Logging for suspicious activity (an anomalous IAM grant, data exfiltration to an external bucket). Container Threat Detection and VM Threat Detection watch GKE nodes and Compute Engine instances for malware and cryptominers. Web Security Scanner crawls a deployed application for XSS and similar issues. Rapid Vulnerability Detection probes for exposed administration interfaces.

Posture management

A posture is a set of org policies and detectors that you define as code and deploy to a folder, so the preventive and detective controls of a whole branch of the hierarchy are managed together and drift is reported.

Cloud Run Threat Detection

Cloud Run Threat Detection is a Premium and Enterprise detector, generally available since 2025-09-10, that instruments Cloud Run services and jobs at the platform level. It needs no agent or change to the container image and reports findings such as a malicious binary or library being executed, a reverse shell, a malicious script, or an unexpected process started from a web request. For Bookshelf it is the control that notices a compromised catalog-api revision running something it was never built to run. The deployment-side controls that pair with it (invoker IAM, a dedicated service account, ingress settings, Binary Authorization) are in Cloud Run.

Finding family Example detections (names vary by release; see the finding reference)

Execution

Malicious binary executed, added binary executed, added library loaded, reverse shell, unexpected child shell

Malicious code

Malicious script executed, malicious URL observed

Defence evasion

Process masquerading, attempts to disable or alter the sandbox

Findings appear in SCC and in Cloud Logging, and each carries the Cloud Run service, revision and container so you can roll back traffic (see Cloud Run Scaling, Traffic and Jobs) and redeploy a known-good image.

In the Google Cloud console

  1. Open Security → Security Command Center (it prompts you to pick an organization; activation needs roles/securitycenter.admin).

  2. On first use, choose a tier and, for Premium or Enterprise, enable the Security Health Analytics, Event Threat Detection and Cloud Run Threat Detection services under Settings → Tier details → Services.

  3. Open Findings, set the time range and use the quick filters (severity, category, project) to focus; click a finding for its description, affected resource, recommended steps and, for Premium, its attack path.

  4. Create Mute rules for known, accepted findings and Notifications or Exports to Pub/Sub, BigQuery or an external SIEM.

With the gcloud CLI

gcloud services enable securitycenter.googleapis.com

ORG_ID=$(gcloud organizations list --format='value(ID)' --limit=1)

# Active high-severity findings in the organization
gcloud scc findings list "$ORG_ID" --location=global \
  --filter='state="ACTIVE" AND severity="HIGH"' \
  --format="table(finding.category,finding.resourceName,finding.eventTime)"

# Everything Cloud Run Threat Detection found
gcloud scc findings list "$ORG_ID" --location=global \
  --filter='category:"Execution:" AND resource.type="run.googleapis.com/Service"'

# Mute a known, accepted finding family
gcloud scc muteconfigs create accept-public-web-bucket \
  --organization="$ORG_ID" --location=global \
  --description="Public static site bucket is intentional" \
  --filter='category="PUBLIC_BUCKET_ACL" AND resource.display_name:"bookshelf-web"'

The filters use the finding properties documented for the Findings API. Muting should be a conscious, reviewed decision, since a mute rule hides a category from every dashboard that reads SCC.

VPC Service Controls

VPC Service Controls (VPC SC) draws a service perimeter around Google Cloud projects and the services listed as restricted. Inside the perimeter, calls between those projects work as before; calls from outside to a restricted service are refused, even when the caller holds a valid IAM role or a stolen credential, and so are copies from inside to a destination outside. It is the control for data exfiltration, which IAM alone cannot stop.

Perimeter

The set of projects (or VPC networks) and the list of restricted services (for Bookshelf: storage.googleapis.com, secretmanager.googleapis.com, sqladmin.googleapis.com).

Access level

A reusable condition (an IP range, a device policy, a set of principals) that lets a request from outside the perimeter in. Created through Access Context Manager.

Ingress and egress rules

Fine-grained exceptions that allow a specific identity to call a specific method across the perimeter boundary, for example a CI service account deploying from outside.

Dry-run mode

A perimeter can be defined in a separate dry-run configuration that is evaluated and logged but not enforced. Violations appear in the audit logs as Policy Denied entries with a VpcServiceControlAuditMetadata payload. Always run a new perimeter in dry-run mode for a few days before enforcing it, because it breaks anything that was quietly crossing the boundary: a BI tool, a build pipeline, a developer’s laptop.

VPC SC is configured on an organization-level access policy; folder- and project-scoped policies exist for delegated administration. The service needs the organization, which is why this page cannot be reproduced in a personal free-trial project.

flowchart LR subgraph P[Service perimeter bookshelf-perimeter] direction TB RUN[catalog-api on Cloud Run] GCS[(Cloud Storage uploads)] SM[(Secret Manager)] RUN --> GCS RUN --> SM end ADM[Admin laptop on corporate IP] -- access level --> GCS ATK[Stolen key used from the internet] -. blocked .-> GCS RUN -. blocked egress .-> EXT[(Bucket in another organization)]

In the Google Cloud console

  1. Open Security → VPC Service Controls, select the organization, and click Manage policy if no access policy exists yet.

  2. On the Access levels tab (or Access Context Manager), click Create access level, name it and add a condition such as an IP subnet.

  3. Back on Service perimeters, click New perimeter, name it, choose Regular perimeter, and under Resources to protect add the Bookshelf project.

  4. Under Restricted services, choose the services to protect; under VPC accessible services keep the default.

  5. Add the access level under Access levels and any Ingress policy or Egress policy rules, and tick Dry run (or choose Create dry-run) so the perimeter is evaluated but not enforced.

  6. After a few days of clean logs, open the perimeter and click Enforce on the dry-run configuration.

With the gcloud CLI

gcloud services enable accesscontextmanager.googleapis.com cloudresourcemanager.googleapis.com

ORG_ID=$(gcloud organizations list --format='value(ID)' --limit=1)
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')

# The organization-wide access policy (one per organization)
POLICY=$(gcloud access-context-manager policies list \
  --organization="$ORG_ID" --format='value(name)' --limit=1)
if [ -z "$POLICY" ]; then
  gcloud access-context-manager policies create \
    --organization="$ORG_ID" --title="Bookshelf policy"
  POLICY=$(gcloud access-context-manager policies list \
    --organization="$ORG_ID" --format='value(name)' --limit=1)
fi

# An access level: requests from the office range
cat > office.yaml <<'YAML'
- ipSubnetworks:
  - 203.0.113.0/24
YAML
gcloud access-context-manager levels create office \
  --policy="$POLICY" --title="Office network" \
  --basic-level-spec=office.yaml

# A perimeter, created directly as a dry-run
gcloud access-context-manager perimeters dry-run create bookshelf_perimeter \
  --policy="$POLICY" \
  --perimeter-title="Bookshelf perimeter" \
  --perimeter-type=regular \
  --perimeter-resources="projects/$PROJECT_NUMBER" \
  --perimeter-restricted-services="storage.googleapis.com,secretmanager.googleapis.com" \
  --perimeter-access-levels="accessPolicies/${POLICY##*/}/accessLevels/office"

# Violations that WOULD have been blocked
gcloud logging read \
  'protoPayload.metadata.dryRun=true AND protoPayload.metadata.@type="type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"' \
  --project="$PROJECT_ID" --freshness=3d --limit=20

# When the logs are clean, enforce it
gcloud access-context-manager perimeters dry-run enforce bookshelf_perimeter \
  --policy="$POLICY"

Perimeter names accept letters, digits and underscores only, which is why the example uses bookshelf_perimeter. The Cloud Storage security options that complement a perimeter (public access prevention, uniform bucket-level access, signed URLs) are in Cloud Storage Security and Static Sites, and the network side in VPC Networking on Google Cloud.

Assured Workloads and data residency

Assured Workloads creates a folder-level workload that applies a compliance regime on top of the resource hierarchy: it sets the allowed locations through org policy, restricts which services may be used, and, for the regimes that require it, limits support access to personnel of a given nationality and location. It exists so a regulated workload (FedRAMP, CJIS, ITAR, an EU data-sovereignty regime) can be created inside a pre-configured folder rather than assembled by hand.

Regimes

A workload picks one compliance regime when it is created. Examples are FEDRAMP_MODERATE, FEDRAMP_HIGH, CJIS, IL4, ITAR, HIPAA, HITRUST and the EU regimes such as EU_REGIONS_AND_SUPPORT. The current list, and which of them are generally available, is in the documentation.

Data residency

Choosing a region for a resource is not by itself a residency guarantee: some services are global or replicate metadata elsewhere. The gcp.resourceLocations org policy confines where new resources can be created, Assured Workloads sets it for you, and the documented service-by-service data-residency lists tell you what remains outside.

Related controls

Access Transparency writes a log entry whenever Google personnel access your content, and Access Approval goes further by requiring your explicit approval before they do. Both are meaningful mostly for regulated workloads and require a support package.

In the Google Cloud console

  1. Open Security → Assured Workloads with the organization selected.

  2. Click Create new workload, enter a name, choose the compliance regime and the region.

  3. Link the billing account and, where offered, choose the KMS key rotation defaults and the support-access settings; accept the terms for the regime.

  4. Click Create; the resulting folder appears in the hierarchy and its org policies are managed by Assured Workloads.

  5. Create projects inside that folder for the regulated resources.

With the gcloud CLI

gcloud services enable assuredworkloads.googleapis.com accessapproval.googleapis.com

ORG_ID=$(gcloud organizations list --format='value(ID)' --limit=1)

# A workload for an EU data-residency regime
gcloud assured workloads create \
  --organization="$ORG_ID" \
  --location=europe-west1 \
  --display-name="bookshelf-eu" \
  --compliance-regime=EU_REGIONS_AND_SUPPORT \
  --billing-account=billingAccounts/000000-000000-000000

gcloud assured workloads list --organization="$ORG_ID" --location=europe-west1

# Access Approval for Cloud Storage and Cloud SQL (project scope)
PROJECT_ID=$(gcloud config get-value project)
gcloud access-approval settings update --project="$PROJECT_ID" \
  --enrolled-services=storage.googleapis.com,sqladmin.googleapis.com \
  --notification-emails=security@example.com
gcloud access-approval requests list --project="$PROJECT_ID"

Treat the placeholder billing account 000000-000000-000000 and the e-mail address as values to replace. The accepted --location values and the regime list differ between regimes; run gcloud assured workloads create --help and read the regime’s page before creating one, because a workload’s regime cannot be changed afterwards.

Sensitive Data Protection and other data controls

Sensitive Data Protection (formerly Cloud Data Loss Prevention, DLP) inspects, classifies and de-identifies sensitive data in Cloud Storage, BigQuery, Datastore and arbitrary text. It finds credit-card numbers, national identifiers and custom patterns, can redact or tokenise them, and can feed data profiles into SCC. For Bookshelf, an inspection job on the bookshelf-uploads-$PROJECT_ID bucket would catch a customer uploading a scan of a passport into a place meant for book covers. It is priced per byte inspected or profiled; the free tier is limited, so scope the jobs.

Complementary controls that belong to other pages:

Compliance resources

Google Cloud publishes evidence of its own compliance, which you then combine with what you build on top of it.

Compliance resource center

The catalogue of certifications and attestations (ISO 27001, SOC 1/2/3, PCI DSS, FedRAMP, HIPAA support and so on) with regional and industry guides.

Compliance Reports Manager

A console and API service for downloading Google’s audit reports and certificates (SOC reports, ISO certificates, penetration-test summaries) under a click-through agreement, instead of requesting them from the sales team.

Customer responsibility

Google’s certifications cover the infrastructure; the configuration of your projects is yours. The shared-responsibility model, and how the same idea looks on the other clouds, is in Cloud Concepts, Governance, Security and Compliance and Governance and Compliance.

Posture and audit tooling

SCC compliance reports map findings to CIS, PCI DSS, NIST and ISO controls; Assured Workloads reports violations of the regime’s org policies; Policy Analyzer and Asset Inventory exports supply the evidence of who could access what.

In the Google Cloud console

  1. Open Security → Compliance Reports Manager (or the Compliance page of the console).

  2. Choose a report family (for example ISO/IEC 27001) and click Download, accepting the terms.

  3. For your own posture, open Security Command Center → Compliance to see the percentage of controls passing per standard and the failing findings behind it.

With the gcloud CLI

Compliance Reports Manager has no dedicated gcloud group; use the console or the REST API. The posture side has commands:

ORG_ID=$(gcloud organizations list --format='value(ID)' --limit=1)

# Findings that map to a compliance standard (requires SCC Premium or Enterprise)
gcloud scc findings list "$ORG_ID" --location=global \
  --filter='state="ACTIVE" AND compliances.standard="cis"' \
  --format="table(finding.category,finding.resourceName)"

A governance baseline for a new organization

A minimal, ordered sequence for the platform team. Each step uses a control from this page and a page elsewhere in the section.

  1. Create the organization, folders and projects (Resource Hierarchy and Projects).

  2. Keep the secure-by-default org policies in force and add gcp.resourceLocations, compute.requireOsLogin and iam.allowedPolicyMemberDomains in dry-run mode first.

  3. Create an aggregated sink that sends the organization’s audit logs to a locked Cloud Storage bucket and a BigQuery dataset.

  4. Enable Data Access audit logs for Secret Manager, Cloud KMS and the buckets with sensitive data.

  5. Activate Security Command Center and route high-severity findings to the on-call channel through Pub/Sub.

  6. Schedule a Cloud Asset Inventory export to BigQuery and a daily query for public bindings and keys.

  7. Put production data services inside a VPC Service Controls perimeter, in dry-run mode first.

  8. Use Assured Workloads only for the regulated folders that need it.

  9. Review the cost of the above, mainly log ingestion and SCC (see Cost Management and Billing).

Pricing, limits and recent changes

Cost drivers

Organization Policy, Cloud Asset Inventory search and VPC Service Controls have no charge of their own at the time of writing. Admin Activity and System Event audit logs are free. Data Access audit logs are billed as log ingestion and storage beyond the free allocation. SCC Standard is free; Premium and Enterprise are billed against the usage of the protected environment (compute, storage and database consumption, not a flat price per seat). Sensitive Data Protection is priced per byte inspected or profiled. Assured Workloads has a subscription fee for the regimes that require it. Check the dated pricing pages in the references before enabling any of them organization-wide.

Quotas and limits

There are limits on the number of org-policy custom constraints per organization, on the number and size of VPC SC perimeters per access policy, on Cloud Asset Inventory export frequency and on audit-log entry size. They are listed on each product’s quotas page; none blocks a small project.

Launch stages and recent changes
  • Organizations created on or after 2024-05-03 have secure-by-default org policies (see Resource Hierarchy and Projects).

  • Cloud Run Threat Detection became generally available on 2025-09-10.

  • The Security Command Center Enterprise tier is shown as sunsetting on 2027-05-21; confirm before planning around it.

  • The Logging UI for SQL-based log analysis has been renamed more than once (Log Analytics, now often labelled Observability Analytics); the capability is the same.

  • Older guides still show gcloud beta commands and the cloud.google.com documentation host. The commands above are the current GA ones and the documentation moved to docs.cloud.google.com.

Clean up

Remove in reverse dependency order; most of the controls above are free to keep but log buckets, BigQuery datasets and SCC are not.

PROJECT_ID=$(gcloud config get-value project)
ORG_ID=$(gcloud organizations list --format='value(ID)' --limit=1)
POLICY=$(gcloud access-context-manager policies list \
  --organization="$ORG_ID" --format='value(name)' --limit=1)
AUDIT_BUCKET=bookshelf-audit-$PROJECT_ID

# VPC Service Controls
gcloud access-context-manager perimeters dry-run delete bookshelf_perimeter --policy="$POLICY"
gcloud access-context-manager perimeters delete bookshelf_perimeter --policy="$POLICY"
gcloud access-context-manager levels delete office --policy="$POLICY"

# Assured Workloads: list, then delete the workload by its resource name
gcloud assured workloads list --organization="$ORG_ID" --location=europe-west1
# gcloud assured workloads delete --workload=WORKLOAD_RESOURCE_NAME

# SCC mute config
gcloud scc muteconfigs delete accept-public-web-bucket \
  --organization="$ORG_ID" --location=global

# Asset Inventory feed, export dataset and topic
gcloud asset feeds delete bookshelf-feed --project="$PROJECT_ID"
bq rm -r -f -d "$PROJECT_ID:asset_export"
gcloud pubsub topics delete asset-changes

# Audit log sink and its bucket
gcloud logging sinks delete audit-archive
gcloud storage rm -r "gs://$AUDIT_BUCKET"

# Organization policies and the custom constraint
gcloud org-policies delete gcp.resourceLocations --project="$PROJECT_ID"
gcloud org-policies delete custom.vmNamePrefix --project="$PROJECT_ID"
gcloud org-policies delete-custom-constraint custom.vmNamePrefix --organization="$ORG_ID"

The Data Access auditConfigs block stays in the project IAM policy until you remove it: read the policy with gcloud projects get-iam-policy, delete the auditConfigs entries you added, and write it back with set-iam-policy. Assured Workloads folders can only be deleted once the projects inside have been deleted. A Cloud Storage bucket removed with rm -r leaves no soft-deleted copy of the bucket itself, but its objects follow the soft-delete retention of the bucket; see Cloud Storage. For a throwaway project, deleting the project removes the project-scoped resources at once (see Resource Hierarchy and Projects).