GCP Security for SOC 2: IAM, Cloud Storage, and Audit Logging
How to secure Google Cloud Platform for SOC 2 compliance — IAM least privilege, Cloud Storage public access, audit log configuration, and the checks that matter for auditors.
GCP in Your SOC 2 Scope
Google Cloud Platform (GCP) brings its own set of security controls and configuration patterns to SOC 2 compliance. Whether GCP is your primary cloud or a secondary environment alongside AWS or Azure, the same SOC 2 Trust Service Criteria apply — and your auditor will check GCP controls the same way they check AWS.
1. IAM — Least Privilege on GCP
GCP's IAM system uses roles (predefined and custom) rather than AWS-style inline policies. For SOC 2:
Avoid primitive roles (Owner, Editor, Viewer) on production projects. These broad roles violate least privilege. Use predefined service-specific roles instead:
# Instead of giving Editor role:
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="user:dev@company.com" \
--role="roles/compute.instanceAdmin.v1"
# Audit primitive role bindings
gcloud projects get-iam-policy PROJECT_ID \
--format="json" | python3 -c "
import json,sys
p=json.load(sys.stdin)
for b in p['bindings']:
if b['role'] in ['roles/owner','roles/editor','roles/viewer']:
print(b['role'], b.get('members',[]))
"
Disable service account key creation at the organization level where possible — use Workload Identity Federation instead. Long-lived service account keys are a credential leakage risk.
# Audit service account keys
gcloud iam service-accounts list --format="value(email)" | while read SA; do
gcloud iam service-accounts keys list --iam-account="$SA" \
--managed-by=user --format="table(keyAlgorithm,validAfterTime,validBeforeTime)"
done
SecureSpect check: gcp.iam.primitive_roles and gcp.iam.service_account_keys_age.
2. Cloud Storage — Block Public Access
GCP Cloud Storage buckets can be made publicly accessible via IAM bindings or ACLs. For SOC 2, no bucket storing customer data should be publicly accessible.
Enforce uniform bucket-level access (disables per-object ACLs, simplifies policy management):
gcloud storage buckets update gs://YOUR-BUCKET \
--uniform-bucket-level-access
Remove allUsers and allAuthenticatedUsers IAM bindings:
# Check for public bindings
gsutil iam get gs://YOUR-BUCKET | grep -E "allUsers|allAuthenticatedUsers"
# Remove public binding
gcloud storage buckets remove-iam-policy-binding gs://YOUR-BUCKET \
--member="allUsers" \
--role="roles/storage.objectViewer"
Enable public access prevention at the organization level — prevents any bucket from becoming public regardless of individual bucket settings:
gcloud resource-manager org-policies set-policy \
--organization=ORG_ID \
constraints/storage.publicAccessPrevention.yaml
3. Cloud Audit Logs — GCP's CloudTrail Equivalent
Cloud Audit Logs capture Admin Activity, Data Access, and System Events. For SOC 2 logging controls (CC7.2):
Ensure Admin Activity logs are enabled — they're on by default and can't be disabled. But verify Data Access logs are enabled for your most sensitive services:
GCP Console → IAM & Admin → Audit Logs → [Service] → Data Read / Data Write
Enable Data Access logs for at minimum:
- BigQuery (customer data processing)
- Cloud Storage (production data buckets)
- Cloud SQL / Spanner / Firestore
- Secrets Manager (Key Management Service)
gcloud logging sinks create soc2-audit-sink storage.googleapis.com/YOUR-LOG-ARCHIVE-BUCKET --log-filter='logName:"cloudaudit.googleapis.com"' --include-children
Set retention on the log bucket to 365 days minimum.
4. VPC and Firewall Rules
GCP firewall rules control traffic to VM instances. For SOC 2:
- No firewall rule should allow ingress from
0.0.0.0/0to SSH (22), RDP (3389), or database ports - Use Identity-Aware Proxy (IAP) for SSH/RDP access instead of open firewall rules
- Tag-based rules are preferred over IP-range rules for maintainability
# Audit overly permissive firewall rules
gcloud compute firewall-rules list \
--format="table(name,direction,sourceRanges,allowed)" \
--filter="direction=INGRESS AND sourceRanges=0.0.0.0/0"
5. Secrets Manager — No Hardcoded Credentials
GCP Secret Manager stores application secrets with versioning, audit logging, and IAM-controlled access:
# Create a secret
gcloud secrets create db-password \
--replication-policy=automatic
echo -n "YOUR_PASSWORD" | gcloud secrets versions add db-password --data-file=-
# Access in application code
from google.cloud import secretmanager
client = secretmanager.SecretManagerServiceClient()
response = client.access_secret_version(
name="projects/PROJECT_ID/secrets/db-password/versions/latest"
)
password = response.payload.data.decode("UTF-8")
Every access to a secret is logged to Cloud Audit Logs — automatic evidence for CC6.7.
SecureSpect + GCP
SecureSpect connects to GCP via a service account JSON key with read-only IAM roles (roles/iam.securityReviewer, roles/viewer). Checks cover IAM policy analysis, public bucket detection, service account key age, and audit log configuration — all mapped to SOC 2 Trust Service Criteria.