Cloud Audit Logs answer “who did what, where and when” for Google Cloud APIs. They are written per project, folder and organization.
flowchart LR CALL["API call: delete VM web-1<br/>by alice@example.com"] --> AA["Admin Activity log<br/>always on, free"] READ["API call: read object in bucket"] --> DA["Data Access log<br/>off by default"] SYS["Google maintenance: live migration"] --> SE["System Event log"] DENY["Request blocked by org policy or VPC-SC"] --> PD["Policy Denied log"] AA --> Q["Logs Explorer / sink to BigQuery"] DA --> Q %% step CALL: Any call that changes configuration or metadata, such as deleting a VM, is recorded. %% step AA: Admin Activity logs are always written, cannot be turned off and are kept 400 days for free. %% step READ: Reading data or metadata, such as downloading an object, is a data access. %% step DA: Data Access logs must be enabled per service (BigQuery is the exception, on by default) and can be very large. %% step SYS: Actions Google performs on your resources appear as System Event logs. %% step DENY: Requests denied by security policies appear in Policy Denied logs. %% step Q: Query them in Logs Explorer or route them with a sink for long-term analysis.
The four types
| Type | Contains | Default | Cost |
|---|---|---|---|
| Admin Activity | Changes to configuration and metadata (create, delete, setIamPolicy) | Always on | Free |
| Data Access | Reads of config/metadata (ADMIN_READ) and user data (DATA_READ, DATA_WRITE) |
Off (except BigQuery) | Billed by volume |
| System Event | Google-initiated changes (live migration, autoscaling events) | Always on | Free |
| Policy Denied | Requests denied by VPC Service Controls or other policies | On (can be excluded) | Billed |
Access Transparency logs (with supported support plans) record actions Google staff take on your content.
Enabling Data Access logs
In IAM → Audit Logs, or in the auditConfigs section of the project’s IAM policy:
auditConfigs:
- service: storage.googleapis.com
auditLogConfigs:
- logType: DATA_READ
- logType: DATA_WRITE
Enable them for sensitive services (Cloud Storage buckets with customer data, Secret Manager), not for everything, because volume and cost can explode.
Reading an entry
Key fields: protoPayload.authenticationInfo.principalEmail (who), protoPayload.methodName (what, e.g. v1.compute.instances.delete), resource (where), timestamp (when), protoPayload.requestMetadata.callerIp.
gcloud logging read 'logName:"cloudaudit.googleapis.com%2Factivity" AND protoPayload.methodName:"instances.delete"' --project=dl-lab-prod --freshness=7d --limit=10
Who can see them
| Role | Can read |
|---|---|
roles/logging.viewer |
Admin Activity, System Event, Policy Denied |
roles/logging.privateLogViewer |
Also Data Access logs |
Route audit logs from the whole organization to a locked security project with an aggregated sink, so a compromised project admin cannot delete the evidence.
| Command | Meaning |
|---|---|
gcloud projects get-iam-policy dl-lab-prod --format="yaml(auditConfigs)" |
Which Data Access logs are on |
gcloud logging read 'protoPayload.authenticationInfo.principalEmail="alice@example.com"' --freshness=1d |
Everything Alice did today |
Traps: Data Access logs are off by default, so “who read this bucket?” cannot be answered retroactively; Logging Viewer cannot see Data Access logs; audit logs record API calls, not what happens inside a VM over SSH.