Cloud Security
Google Cloud Security
GCP Security
Cloud Security
VPC Service Controls
+4 more

Google Cloud Security: Complete GCP Hardening Guide for 2026

SCR Team
April 13, 2026
24 min read
Share

Why GCP Security Requires a Different Approach

Google Cloud Platform has a fundamentally different security model than AWS. GCP uses resource hierarchy (Organization → Folders → Projects) with inherited IAM policies and default encryption on everything.

Google Cloud Security — Threat Landscape and Controls
Google Cloud Security — Threat Landscape and Controls

Despite strong defaults, GCP breaches are rising. The 2025 Mandiant M-Trends Report found that 37% of cloud breaches started with misconfigurations, and GCP-specific incidents increased 45% year-over-year.


1. GCP IAM: Resource Hierarchy and Bindings

Unlike AWS (user-centric IAM), GCP IAM is resource-centric — permissions are granted on resources via role bindings.

Principle of Least Privilege with Custom Roles

# Create a custom role with minimal permissions
gcloud iam roles create appReadOnly \
  --project=my-project \
  --title="App Read Only" \
  --description="Read-only access to app resources" \
  --permissions=storage.objects.get,storage.objects.list,logging.logEntries.list \
  --stage=GA

# Bind to a service account (not a user)
gcloud projects add-iam-policy-binding my-project \
  --member="serviceAccount:app-sa@my-project.iam.gserviceaccount.com" \
  --role="projects/my-project/roles/appReadOnly" \
  --condition='expression=request.time < timestamp("2026-12-31T00:00:00Z"),title=temp-access'

Service Account Security

Service account key leaks are the #1 GCP attack vector:

# List all SA keys (look for user-managed keys)
gcloud iam service-accounts keys list \
  --iam-account=my-sa@my-project.iam.gserviceaccount.com \
  --managed-by=user

# BEST: Use Workload Identity Federation instead of keys
gcloud iam workload-identity-pools create github-pool \
  --project=my-project \
  --location=global \
  --display-name="GitHub Actions Pool"

gcloud iam workload-identity-pools providers create-oidc github-provider \
  --project=my-project \
  --location=global \
  --workload-identity-pool=github-pool \
  --display-name="GitHub Provider" \
  --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \
  --issuer-uri="https://token.actions.githubusercontent.com"

Organization Policy Constraints

# Disable SA key creation org-wide
gcloud org-policies set-policy \
  --organization=123456789 \
  policy.yaml

# policy.yaml
# constraint: constraints/iam.disableServiceAccountKeyCreation
# booleanPolicy:
#   enforced: true

# Restrict which external IP ranges can access resources
gcloud org-policies set-policy \
  --organization=123456789 \
  ip-policy.yaml

# Require OS Login for all VMs
gcloud compute project-info add-metadata \
  --metadata enable-oslogin=TRUE

2. VPC Service Controls: The GCP Secret Weapon

VPC Service Controls create a security perimeter around GCP resources that prevents data exfiltration — even with valid IAM credentials.

# Create an access policy
gcloud access-context-manager policies create \
  --organization=123456789 \
  --title="Production Security Policy"

# Create an access level (IP + device requirements)
gcloud access-context-manager levels create corp-network \
  --title="Corporate Network" \
  --basic-level-spec=level-spec.yaml \
  --policy=POLICY_ID

# Create a service perimeter
gcloud access-context-manager perimeters create production \
  --title="Production Perimeter" \
  --resources="projects/12345,projects/67890" \
  --restricted-services="storage.googleapis.com,bigquery.googleapis.com" \
  --access-levels="accessPolicies/POLICY_ID/accessLevels/corp-network" \
  --policy=POLICY_ID

What VPC SC prevents:

  • Service account key stolen → can't exfil data outside perimeter
  • Insider threat → BigQuery exports blocked outside perimeter
  • Compromised CI/CD → GCS access blocked from non-approved networks

3. Security Command Center (SCC)

SCC is GCP's CSPM — think of it as AWS Security Hub + GuardDuty combined.

Enable SCC Premium Tier

# Enable SCC Premium (org-level)
gcloud scc manage services update security-health-analytics \
  --organization=123456789 \
  --enablement-state=ENABLED

# Enable all detectors
gcloud scc manage services update web-security-scanner \
  --organization=123456789 \
  --enablement-state=ENABLED

gcloud scc manage services update event-threat-detection \
  --organization=123456789 \
  --enablement-state=ENABLED

gcloud scc manage services update container-threat-detection \
  --organization=123456789 \
  --enablement-state=ENABLED

Query SCC Findings

# List all HIGH/CRITICAL findings
gcloud scc findings list 123456789 \
  --source="-" \
  --filter='severity="HIGH" OR severity="CRITICAL"' \
  --format="table(finding.category, finding.severity, resource.name)"

# Find all public GCS buckets
gcloud scc findings list 123456789 \
  --source="-" \
  --filter='category="PUBLIC_BUCKET"'

4. Binary Authorization

Enforce that only signed, trusted container images run in GKE:

# Create an attestor
gcloud container binauthz attestors create prod-attestor \
  --attestation-authority-note=prod-note \
  --attestation-authority-note-project=my-project

# Create the Binary Authorization policy
gcloud container binauthz policy import policy.yaml

# policy.yaml:
# defaultAdmissionRule:
#   evaluationMode: REQUIRE_ATTESTATION
#   enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
#   requireAttestationsBy:
#     - projects/my-project/attestors/prod-attestor
# clusterAdmissionRules:
#   us-central1-a.prod-cluster:
#     evaluationMode: REQUIRE_ATTESTATION
#     enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
#     requireAttestationsBy:
#       - projects/my-project/attestors/prod-attestor

5. Cloud Armor: DDoS and WAF

# Create a security policy
gcloud compute security-policies create web-policy \
  --description="Production WAF policy"

# Block SQL injection
gcloud compute security-policies rules create 1000 \
  --security-policy=web-policy \
  --expression="evaluatePreconfiguredExpr('sqli-v33-stable')" \
  --action=deny-403 \
  --description="Block SQLi"

# Block XSS
gcloud compute security-policies rules create 1001 \
  --security-policy=web-policy \
  --expression="evaluatePreconfiguredExpr('xss-v33-stable')" \
  --action=deny-403 \
  --description="Block XSS"

# Rate limiting
gcloud compute security-policies rules create 2000 \
  --security-policy=web-policy \
  --src-ip-ranges="*" \
  --action=rate-based-ban \
  --rate-limit-threshold-count=100 \
  --rate-limit-threshold-interval-sec=60 \
  --ban-duration-sec=300 \
  --description="Rate limit: 100 req/min"

# Geo-blocking
gcloud compute security-policies rules create 3000 \
  --security-policy=web-policy \
  --expression="origin.region_code == 'CN' || origin.region_code == 'RU'" \
  --action=deny-403 \
  --description="Block traffic from CN/RU"

6. GCP Security Audit Script

import subprocess
import json

def gcp_security_audit(project_id):
    """Comprehensive GCP security audit"""
    findings = []
    
    # Check 1: Public GCS buckets
    result = subprocess.run(
        ['gsutil', 'ls', '-p', project_id],
        capture_output=True, text=True
    )
    buckets = result.stdout.strip().split('\n')
    
    for bucket in buckets:
        if bucket:
            iam = subprocess.run(
                ['gsutil', 'iam', 'get', bucket],
                capture_output=True, text=True
            )
            if 'allUsers' in iam.stdout or 'allAuthenticatedUsers' in iam.stdout:
                findings.append({
                    'severity': 'CRITICAL',
                    'resource': bucket,
                    'issue': 'Publicly accessible GCS bucket'
                })
    
    # Check 2: SA keys older than 90 days
    result = subprocess.run(
        ['gcloud', 'iam', 'service-accounts', 'list',
         '--project', project_id, '--format', 'json'],
        capture_output=True, text=True
    )
    service_accounts = json.loads(result.stdout)
    
    for sa in service_accounts:
        keys_result = subprocess.run(
            ['gcloud', 'iam', 'service-accounts', 'keys', 'list',
             '--iam-account', sa['email'],
             '--managed-by', 'user', '--format', 'json'],
            capture_output=True, text=True
        )
        keys = json.loads(keys_result.stdout)
        if keys:
            findings.append({
                'severity': 'HIGH',
                'resource': sa['email'],
                'issue': f'{len(keys)} user-managed SA keys found'
            })
    
    # Check 3: Default network exists
    result = subprocess.run(
        ['gcloud', 'compute', 'networks', 'list',
         '--project', project_id, '--format', 'json'],
        capture_output=True, text=True
    )
    networks = json.loads(result.stdout)
    for network in networks:
        if network['name'] == 'default':
            findings.append({
                'severity': 'MEDIUM',
                'resource': 'default-network',
                'issue': 'Default VPC network still exists'
            })
    
    return findings

GCP vs AWS Security: Key Differences

FeatureGCPAWS
IAM modelResource-centricUser-centric
Default encryptionAlways on (Google-managed)Opt-in per service
Network isolationVPC Service ControlsVPC + security groups
Container securityBinary AuthorizationECR image scanning
Threat detectionSCC + ChronicleGuardDuty + Detective
Audit loggingCloud Audit Logs (always on)CloudTrail (must enable)
DDoS protectionCloud Armor (included)Shield (Standard free / Advanced paid)

Key Takeaways

  1. VPC Service Controls are non-negotiable — they stop data exfiltration even with valid credentials
  2. Eliminate SA keys — use Workload Identity Federation for all CI/CD and cross-cloud access
  3. Organization Policies > individual project settings — enforce security at the org level
  4. Binary Authorization for GKE — prevent unauthorized container images from running
  5. SCC Premium is worth it — real-time threat detection, vulnerability scanning, and compliance monitoring in one dashboard

Scan your GCP infrastructure code with ShieldX — detect misconfigurations in Terraform, Deployment Manager, and Kubernetes manifests before deployment.

Advertisement