11.9 Security Best Practices

Note

Security is a shared responsibility between Google Cloud and you. Google secures the underlying infrastructure, while you’re responsible for securing your applications, data, and access controls. This chapter covers GCP security best practices, tools, and services to help you build and maintain secure cloud environments.

Security Shared Responsibility Model

Google’s Responsibilities:

  • Physical security of data centers

  • Hardware and network infrastructure

  • Hypervisor and host OS security

  • Service availability and reliability

  • Data encryption at rest by default

Your Responsibilities:

  • Identity and Access Management (IAM)

  • Data classification and encryption keys

  • Network configuration

  • Application security

  • Access controls and monitoring

  • Compliance requirements

Identity and Access Management (IAM)

Principle of Least Privilege:

# BAD: Granting owner role to everyone
gcloud projects add-iam-policy-binding my-project \
    --member="user:alice@example.com" \
    --role="roles/owner"

# GOOD: Grant specific roles needed
gcloud projects add-iam-policy-binding my-project \
    --member="user:alice@example.com" \
    --role="roles/compute.instanceAdmin.v1"

Service Account Best Practices:

# Create service account with descriptive name
gcloud iam service-accounts create app-backend-sa \
    --display-name="Backend Application Service Account" \
    --description="SA for backend application with minimal permissions"

# Grant only necessary permissions
gcloud projects add-iam-policy-binding my-project \
    --member="serviceAccount:app-backend-sa@my-project.iam.gserviceaccount.com" \
    --role="roles/storage.objectViewer"

# Disable default service account
gcloud iam service-accounts disable \
    PROJECT_NUMBER-compute@developer.gserviceaccount.com

Use Workload Identity (GKE):

# Enable Workload Identity on cluster
gcloud container clusters update my-cluster \
    --zone=us-central1-a \
    --workload-pool=PROJECT_ID.svc.id.goog

# Create Kubernetes service account
kubectl create serviceaccount app-ksa

# Bind Kubernetes SA to Google SA
gcloud iam service-accounts add-iam-policy-binding \
    app-backend-sa@PROJECT_ID.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:PROJECT_ID.svc.id.goog[default/app-ksa]"

# Annotate Kubernetes service account
kubectl annotate serviceaccount app-ksa \
    iam.gke.io/gcp-service-account=app-backend-sa@PROJECT_ID.iam.gserviceaccount.com

Regular Access Reviews:

# List all IAM policies
gcloud projects get-iam-policy my-project \
    --format=json > iam-policy.json

# Audit service accounts
gcloud iam service-accounts list \
    --format="table(email,displayName,disabled)"

# Find unused service accounts
gcloud recommender recommendations list \
    --project=PROJECT_ID \
    --location=global \
    --recommender=google.iam.policy.Recommender

Network Security

VPC Security:

# Create custom VPC
gcloud compute networks create secure-vpc \
    --subnet-mode=custom \
    --bgp-routing-mode=regional

# Create subnet with Private Google Access
gcloud compute networks subnets create private-subnet \
    --network=secure-vpc \
    --region=us-central1 \
    --range=10.0.1.0/24 \
    --enable-private-ip-google-access

Firewall Rules Best Practices:

# Default deny all ingress (implicit in GCP)
# Only allow necessary traffic

# Allow SSH only from specific IP (bastion)
gcloud compute firewall-rules create allow-ssh-bastion \
    --network=secure-vpc \
    --allow=tcp:22 \
    --source-ranges=10.0.0.10/32 \
    --target-tags=ssh-access

# Allow HTTPS from internet
gcloud compute firewall-rules create allow-https \
    --network=secure-vpc \
    --allow=tcp:443 \
    --source-ranges=0.0.0.0/0 \
    --target-tags=web-server

# Allow internal communication between VMs
gcloud compute firewall-rules create allow-internal \
    --network=secure-vpc \
    --allow=tcp:0-65535,udp:0-65535,icmp \
    --source-ranges=10.0.0.0/16

# Log firewall rules for monitoring
gcloud compute firewall-rules update allow-https \
    --enable-logging

Cloud NAT for Egress:

# Create Cloud Router
gcloud compute routers create nat-router \
    --network=secure-vpc \
    --region=us-central1

# Configure Cloud NAT (VMs don't need public IPs)
gcloud compute routers nats create nat-config \
    --router=nat-router \
    --region=us-central1 \
    --nat-all-subnet-ip-ranges \
    --auto-allocate-nat-external-ips

Private GKE Cluster:

# Create private GKE cluster
gcloud container clusters create private-cluster \
    --zone=us-central1-a \
    --enable-private-nodes \
    --enable-private-endpoint \
    --enable-ip-alias \
    --master-ipv4-cidr=172.16.0.0/28 \
    --no-enable-basic-auth \
    --no-issue-client-certificate

VPC Service Controls:

# Create access policy
gcloud access-context-manager policies create \
    --organization=ORGANIZATION_ID \
    --title="Production Access Policy"

# Create service perimeter
gcloud access-context-manager perimeters create prod_perimeter \
    --title="Production Perimeter" \
    --resources=projects/PROJECT_NUMBER \
    --restricted-services=storage.googleapis.com,bigquery.googleapis.com \
    --policy=POLICY_ID

Data Security

Encryption at Rest:

# Create encryption key
gcloud kms keyrings create my-keyring \
    --location=us-central1

gcloud kms keys create my-key \
    --location=us-central1 \
    --keyring=my-keyring \
    --purpose=encryption

# Create disk with customer-managed encryption
gcloud compute disks create encrypted-disk \
    --size=100GB \
    --zone=us-central1-a \
    --kms-key=projects/PROJECT_ID/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key

# Create VM with encrypted disk
gcloud compute instances create secure-vm \
    --zone=us-central1-a \
    --disk=name=encrypted-disk,boot=yes

Encryption in Transit:

# All GCP services use TLS by default
# For custom apps, ensure TLS is enabled

# Create SSL certificate for Load Balancer
gcloud compute ssl-certificates create my-cert \
    --certificate=cert.pem \
    --private-key=key.pem \
    --global

Secret Management:

# Enable Secret Manager API
gcloud services enable secretmanager.googleapis.com

# Create secret
echo -n "my-db-password" | gcloud secrets create db-password \
    --data-file=-

# Grant access to service account
gcloud secrets add-iam-policy-binding db-password \
    --member="serviceAccount:app-sa@PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"

# Access secret in application
gcloud secrets versions access latest --secret="db-password"

Use Secret Manager with GKE:

# deployment.yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  serviceAccountName: app-ksa
  containers:
  - name: app
    image: myapp:1.0
    env:
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-password
          key: password
# Install External Secrets Operator
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets

# Create SecretStore
cat <<EOF | kubectl apply -f -
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: gcpsm-secret-store
spec:
  provider:
    gcpsm:
      projectID: "PROJECT_ID"
      auth:
        workloadIdentity:
          clusterLocation: us-central1
          clusterName: my-cluster
          serviceAccountRef:
            name: app-ksa
EOF

Data Loss Prevention (DLP):

# dlp-scan.py
from google.cloud import dlp_v2

def inspect_content(project_id, content):
    """Scan content for sensitive data."""
    dlp = dlp_v2.DlpServiceClient()

    parent = f"projects/{project_id}"

    # Configure what to scan for
    info_types = [
        {"name": "EMAIL_ADDRESS"},
        {"name": "PHONE_NUMBER"},
        {"name": "CREDIT_CARD_NUMBER"},
        {"name": "US_SOCIAL_SECURITY_NUMBER"}
    ]

    inspect_config = {
        "info_types": info_types,
        "min_likelihood": dlp_v2.Likelihood.POSSIBLE
    }

    item = {"value": content}

    response = dlp.inspect_content(
        request={
            "parent": parent,
            "inspect_config": inspect_config,
            "item": item
        }
    )

    if response.result.findings:
        print("Sensitive data found:")
        for finding in response.result.findings:
            print(f"  - {finding.info_type.name}: {finding.quote}")
    else:
        print("No sensitive data found.")

Compute Security

VM Security Best Practices:

# Use Shielded VMs (secure boot, vTPM, integrity monitoring)
gcloud compute instances create secure-vm \
    --zone=us-central1-a \
    --machine-type=n1-standard-2 \
    --shielded-secure-boot \
    --shielded-vtpm \
    --shielded-integrity-monitoring

# Disable external IP (use Cloud NAT)
gcloud compute instances create private-vm \
    --zone=us-central1-a \
    --machine-type=n1-standard-2 \
    --no-address \
    --subnet=private-subnet

# Use custom service account
gcloud compute instances create vm-with-sa \
    --zone=us-central1-a \
    --service-account=app-sa@PROJECT_ID.iam.gserviceaccount.com \
    --scopes=cloud-platform

# Enable OS Login (instead of SSH keys)
gcloud compute instances add-metadata vm-with-oslogin \
    --zone=us-central1-a \
    --metadata=enable-oslogin=TRUE

OS Patch Management:

# Enable OS Config API
gcloud services enable osconfig.googleapis.com

# Create patch deployment
gcloud compute os-config patch-deployments create monthly-patches \
    --file=patch-deployment.yaml
# patch-deployment.yaml
patchConfig:
  rebootConfig: DEFAULT
  apt:
    type: DIST
oneTimeSchedule:
  executeTime: '2024-02-01T02:00:00Z'
instanceFilter:
  all: true

Container Security:

# Scan container images for vulnerabilities
gcloud artifacts docker images scan \
    us-central1-docker.pkg.dev/PROJECT_ID/my-repo/myapp:latest

# View scan results
gcloud artifacts docker images list-vulnerabilities \
    us-central1-docker.pkg.dev/PROJECT_ID/my-repo/myapp:latest

Binary Authorization:

# Enable Binary Authorization
gcloud services enable binaryauthorization.googleapis.com

# Create policy requiring attestations
cat > policy.yaml << EOF
admissionWhitelistPatterns:
- namePattern: gcr.io/google-containers/*
- namePattern: k8s.gcr.io/*
defaultAdmissionRule:
  requireAttestationsBy:
  - projects/PROJECT_ID/attestors/my-attestor
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
globalPolicyEvaluationMode: ENABLE
EOF

gcloud container binauthz policy import policy.yaml

Monitoring and Logging

Cloud Logging:

# View logs
gcloud logging read "resource.type=gce_instance" \
    --limit 50 \
    --format json

# Create log sink to export logs
gcloud logging sinks create security-logs-sink \
    storage.googleapis.com/security-logs-bucket \
    --log-filter='severity >= ERROR'

# Create metric from logs
gcloud logging metrics create failed-login-attempts \
    --description="Count of failed login attempts" \
    --log-filter='resource.type="gce_instance" AND
                 textPayload=~"Failed password"'

Cloud Monitoring Alerts:

# Create alert policy
cat > alert-policy.yaml << EOF
displayName: "High Failed Login Attempts"
conditions:
- displayName: "Failed logins > 10"
  conditionThreshold:
    filter: 'metric.type="logging.googleapis.com/user/failed-login-attempts"'
    comparison: COMPARISON_GT
    thresholdValue: 10
    duration: 300s
notificationChannels:
- projects/PROJECT_ID/notificationChannels/CHANNEL_ID
EOF

gcloud alpha monitoring policies create --policy-from-file=alert-policy.yaml

Audit Logging:

# Admin Activity logs (always on, free)
gcloud logging read "logName:activity" --limit 10

# Data Access logs (must be enabled)
gcloud logging read "logName:data_access" --limit 10

# Query specific events
gcloud logging read \
    'protoPayload.methodName="v1.compute.instances.delete"' \
    --limit 10 \
    --format json

Security Command Center:

# Enable Security Command Center
gcloud services enable securitycenter.googleapis.com

# List findings
gcloud scc findings list ORGANIZATION_ID \
    --filter="state=\"ACTIVE\""

# Get specific finding
gcloud scc findings describe FINDING_NAME

Security Scanning

Web Security Scanner:

# Enable Web Security Scanner API
gcloud services enable websecurityscanner.googleapis.com

# Create scan configuration
gcloud alpha web-security-scanner scan-configs create \
    --display-name="My App Scan" \
    --starting-urls="https://myapp.example.com"

# Start scan
gcloud alpha web-security-scanner scan-runs start \
    SCAN_CONFIG_NAME

Container Analysis:

# Automatically scans images pushed to Container Registry/Artifact Registry
# View vulnerabilities
gcloud container images describe \
    gcr.io/PROJECT_ID/myapp:latest \
    --show-package-vulnerability

Event Threat Detection:

  • Automatically enabled in Security Command Center

  • Detects: - Malware - Cryptomining - Brute force SSH - IAM anomalies - Data exfiltration

Compliance and Governance

Organization Policies:

# Require OS Login on all VMs
gcloud resource-manager org-policies enable-enforce \
    compute.requireOsLogin \
    --organization=ORGANIZATION_ID

# Restrict VM external IPs
gcloud resource-manager org-policies set-policy \
    restrict-vm-external-ips.yaml \
    --organization=ORGANIZATION_ID
# restrict-vm-external-ips.yaml
constraint: compute.vmExternalIpAccess
listPolicy:
  deniedValues:
  - "*"

Resource Hierarchy:

# Best practice: Use folders for organization
# Organization
#   └── Folder: Production
#       ├── Project: prod-web
#       └── Project: prod-api
#   └── Folder: Development
#       ├── Project: dev-web
#       └── Project: dev-api

# Create folder
gcloud resource-manager folders create \
    --display-name="Production" \
    --organization=ORGANIZATION_ID

Access Transparency:

# View Access Transparency logs (Enterprise only)
gcloud logging read \
    'logName:"cloudaudit.googleapis.com%2Faccess_transparency"' \
    --limit 10

Incident Response

Incident Response Plan:

  1. Detection

    • Monitor Security Command Center

    • Set up alerts for anomalies

    • Regular log reviews

  2. Analysis

    • Review audit logs

    • Check Cloud Monitoring

    • Investigate affected resources

  3. Containment

    • Isolate affected resources

    • Revoke compromised credentials

    • Apply firewall rules

  4. Eradication

    • Remove malicious resources

    • Patch vulnerabilities

    • Update access controls

  5. Recovery

    • Restore from backups

    • Verify system integrity

    • Resume normal operations

  6. Post-Incident

    • Document incident

    • Update procedures

    • Implement preventive measures

Quick Response Commands:

# Disable compromised service account
gcloud iam service-accounts disable \
    compromised-sa@PROJECT_ID.iam.gserviceaccount.com

# Remove IAM binding immediately
gcloud projects remove-iam-policy-binding my-project \
    --member="user:compromised@example.com" \
    --role="roles/owner"

# Block VM from internet
gcloud compute firewall-rules create block-compromised-vm \
    --action=DENY \
    --rules=all \
    --source-ranges=0.0.0.0/0 \
    --target-tags=compromised-vm \
    --priority=100

# Stop VM immediately
gcloud compute instances stop compromised-vm \
    --zone=us-central1-a

# Take snapshot for forensics
gcloud compute disks snapshot compromised-disk \
    --snapshot-names=forensic-snapshot-$(date +%s) \
    --zone=us-central1-a

Security Automation

Automated Security Checks:

# security-checks.py
from google.cloud import compute_v1
from google.cloud import logging

def check_vm_security(project_id, zone):
    """Check VMs for security best practices."""
    compute = compute_v1.InstancesClient()
    instances = compute.list(project=project_id, zone=zone)

    issues = []

    for instance in instances:
        # Check for external IP
        for interface in instance.network_interfaces:
            if interface.access_configs:
                issues.append(f"{instance.name}: Has external IP")

        # Check for default service account
        for sa in instance.service_accounts:
            if 'compute@developer' in sa.email:
                issues.append(f"{instance.name}: Uses default SA")

        # Check for Shielded VM
        if not instance.shielded_instance_config:
            issues.append(f"{instance.name}: Not a Shielded VM")

    return issues

# Run checks
issues = check_vm_security('my-project', 'us-central1-a')
for issue in issues:
    print(f"{issue}")

Security Response Automation:

# auto-response.py
from google.cloud import pubsub_v1
from google.cloud import compute_v1
import json

def handle_security_finding(event, context):
    """Respond to Security Command Center finding."""
    pubsub_message = base64.b64decode(event['data']).decode('utf-8')
    finding = json.loads(pubsub_message)

    # Check finding type
    if finding['category'] == 'MALWARE':
        # Isolate affected VM
        instance_name = extract_instance_name(finding)
        isolate_vm(instance_name)
        send_alert(f"VM {instance_name} isolated due to malware")

def isolate_vm(instance_name):
    """Apply deny-all firewall rule to VM."""
    compute = compute_v1.FirewallsClient()
    # Create isolation rule
    # Implementation details...

Security Checklist

IAM and Authentication:

Use principle of least privilege Enable MFA for all users Regular access reviews Use service accounts instead of user accounts Enable Workload Identity for GKE Disable default service accounts Set up Cloud Identity for user management

Network Security:

Use private IPs where possible Implement firewall rules with logging Enable VPC Flow Logs Use Cloud NAT for egress Implement VPC Service Controls Use Private Google Access Enable DDoS protection

Data Security:

Enable encryption at rest (CMEK where needed) Ensure encryption in transit (TLS) Use Secret Manager for secrets Implement data classification Enable DLP scanning Regular backups with testing Implement retention policies

Compute Security:

Use Shielded VMs Enable OS Login Disable external IPs Regular patching Container vulnerability scanning Enable Binary Authorization Use minimal base images

Monitoring and Logging:

Enable audit logging Set up Cloud Monitoring alerts Export logs to Cloud Storage Enable Security Command Center Configure log retention Regular log analysis Incident response plan

Compliance:

Implement organization policies Use resource hierarchy Enable Access Transparency (if needed) Regular compliance audits Document security controls Security training for team

Security Tools Summary

Tool

Purpose

Cloud IAM

Identity and access management

VPC Service Controls

Create security perimeters

Secret Manager

Manage secrets securely

Cloud KMS

Encryption key management

Security Command Center

Centralized security dashboard

Web Security Scanner

Scan web apps for vulnerabilities

Container Analysis

Scan container images

Binary Authorization

Deploy only verified containers

Cloud Armor

DDoS protection and WAF

Cloud DLP

Discover and protect sensitive data

Cloud Logging

Centralized logging

Cloud Monitoring

Alerting and monitoring

Organization Policy

Enforce compliance

Access Transparency

Log Google access to your data

Best Practices Summary

1. Defense in Depth:

  • Multiple layers of security

  • Assume breach mentality

  • Zero trust architecture

2. Automation:

  • Automate security checks

  • Automated incident response

  • Infrastructure as Code with security

3. Monitoring:

  • Continuous monitoring

  • Real-time alerts

  • Regular audits

4. Training:

  • Regular security training

  • Security awareness program

  • Incident response drills

5. Documentation:

  • Security policies

  • Incident response procedures

  • Architecture documentation

Additional Resources