Lesson 4 of 5 · 20 min read

GCP Detection — Cloud Audit Logs, IAM Anomalies, and Workspace

GCP is less common than AWS in enterprise environments but dominant in ML/data workloads. Its detection model is nearly identical to AWS — control plane API logs, IAM analysis, and data plane visibility gaps.


GCP Cloud Audit Log Format

{
  "insertId": "1abcdef2ghijk",
  "logName": "projects/my-project/logs/cloudaudit.googleapis.com%2Factivity",
  "protoPayload": {
    "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
    "authenticationInfo": {
      "principalEmail": "attacker@gmail.com"
    },
    "methodName": "google.iam.admin.v1.CreateServiceAccountKey",
    "resourceName": "projects/my-project/serviceAccounts/webapp@my-project.iam.gserviceaccount.com",
    "requestMetadata": {
      "callerIp": "203.0.113.42",
      "callerSuppliedUserAgent": "curl/7.68.0"
    },
    "status": {}
  },
  "resource": {
    "type": "service_account",
    "labels": {
      "email_id": "webapp@my-project.iam.gserviceaccount.com",
      "project_id": "my-project",
      "unique_id": "123456789012345678901"
    }
  },
  "severity": "NOTICE",
  "timestamp": "2026-05-18T02:14:23Z"
}

Key detection fields: protoPayload.authenticationInfo.principalEmail, protoPayload.methodName, requestMetadata.callerIp.


Detection Pattern 1: Service Account Key Creation (Persistence)

title: GCP Service Account Key Created
logsource:
  product: gcp
  service: cloudaudit
detection:
  selection:
    protoPayload.methodName: "google.iam.admin.v1.CreateServiceAccountKey"
  filter_known_automation:
    protoPayload.authenticationInfo.principalEmail|contains:
      - "terraform-sa@"
      - "ci-pipeline@"
  condition: selection and not filter_known_automation
falsepositives:
  - Legitimate service account key rotation by infrastructure automation
level: high

Why this matters: Long-lived service account keys (JSON key files) are the GCP equivalent of AWS long-lived access keys. Any key creation outside known automation is a persistence attempt — attackers use these to maintain access after the initial vector is closed.


Detection Pattern 2: IAM Policy Modification

title: GCP IAM Policy Binding Modified — High Privilege Role
logsource:
  product: gcp
  service: cloudaudit
detection:
  selection:
    protoPayload.methodName|contains:
      - "SetIamPolicy"
      - "projects.setIamPolicy"
      - "organizations.setIamPolicy"
  selection_high_priv:
    protoPayload.request.policy.bindings.role:
      - "roles/owner"
      - "roles/editor"
      - "roles/iam.securityAdmin"
      - "roles/iam.roleAdmin"
  condition: selection and selection_high_priv
level: critical

Detection Pattern 3: Cloud Storage Exfiltration (Data Access Logging)

When Data Access audit logs are enabled for Cloud Storage:

title: GCP Cloud Storage Bucket — Unusual Bulk Access
logsource:
  product: gcp
  service: cloudaudit
detection:
  selection:
    protoPayload.methodName: "storage.objects.get"
    protoPayload.resourceName|contains: "sensitive-bucket"
  filter_known_service:
    protoPayload.authenticationInfo.principalEmail|contains:
      - "backup-sa@"
      - "analytics-sa@"
  condition: selection and not filter_known_service | count() > 50
level: high

GCP-Specific Attack Scenarios

AttackLog eventDetection
Service account key theftCreateServiceAccountKeyKey created outside automation by unknown principal
Owner role escalationSetIamPolicy with roles/ownerAny owner role grant outside known admin pipeline
Cloud Function backdoorcloudfunctions.functions.createNew function created outside CI/CD service account
Project-level IAM grantresourcemanager.projects.setIamPolicyUnexpected principal added to project IAM
GCS object public accessstorage.buckets.setIamPolicy with allUsersBucket made public
Secret Manager accesssecretmanager.versions.accessSecret accessed by non-application principal

Google Workspace Detection

Workspace audit logs via Admin SDK Reports API cover the SaaS layer:

# Detection: Google Drive file shared externally to 'anyone with link'
# Admin SDK event: drive_sharing_change with visibility = 'people_with_link'
# or 'public_on_the_web'

# Sigma representation (vendor-specific, adapt to SIEM connector format):
# logsource product: google_workspace service: drive
# detection:
#   selection:
#     eventName: change_document_access_scope
#     visibility: ['people_with_link', 'public_on_the_web']
#   condition: selection
# level: medium

High-priority Workspace events:

EventWhy it matters
drive: change_document_access_scope with public_on_the_webDrive file made public
admin: add_privilege for new admin roleAdmin role granted to user
token: authorize for new OAuth appOAuth app granted scopes to access Workspace data
gmail: create_filter with forward_toEmail forwarding rule created (exfil path)
login: login_failureFailed logins (spray/brute force detection)
GCP Cloud Audit Logs— Google Google Workspace Audit Reports— Google