60 WORM off-tenant log archive
draft
Audit logs that live where the tenant's own admins can reach them — the Admin console, the BigQuery export (33 Audit-log export to SIEM/BigQuery) — are still deletable by whoever administers that surface, and that is often the same super admin the logs are evidence against. This control lands a second copy in a Cloud Storage bucket with a LOCKED Bucket Lock retention policy, in a project whose IAM is separate from the Workspace super admins being audited. Locked means write-once: the retention period cannot be shortened and objects cannot be deleted before it expires. The lock only places a lien against deleting the project, though — anyone who can remove liens (included in roles/owner) can delete the whole project, bucket and all, which is why the IAM split below is load-bearing. The source is Workspace data sharing with Google Cloud, which places the audit logs in Cloud Logging at the organization level; the BigQuery export is a separate pipe that never passes through Cloud Logging.
Documentation: Audit logs for Google Workspace
Caveats
- The control fails if the same super admin can delete both the tenant logs and the sink — the split of custody, not the bucket, is what makes it WORM.
- Expanded and late log events (Ent Std+) arrive with a delay — the archive is only ever as complete as the export that feeds it.
Setup steps
-
Account › Account settings › Legal and complianceSharing options = Enabled (share Google Workspace data with Google Cloud services; super admin only)
-
gcloud logging sinks create ws-audit-archive storage.googleapis.com/<archive-bucket> --organization=<ORG_ID> --log-filter='protoPayload.serviceName=("admin.googleapis.com" OR "login.googleapis.com" OR "cloudidentity.googleapis.com" OR "oauth2.googleapis.com")' -
gcloud storage buckets update gs://… --retention-period=94608000s (3 years) gcloud storage buckets update gs://… --lock-retention-period -
Separate GCP org/project IAM; no shared identity
Ongoing maintenance
- automatable: script Weekly: alert on sink export errors and on the bucket receiving no new objects.
How to verify
-
Confirm the retention policy is LOCKED (not merely set) and that objects are still arriving.
gcloud storage buckets describe gs://<archive-bucket> --format='default(retention_policy)' gcloud storage ls -l --recursive gs://<archive-bucket> | tail -3 -
Attempt to delete a recent object with project-owner credentials — the locked policy must refuse it. The refusal is the control.
draft v0.1.3 Assure edition All (expanded events: Ent Std+) policy #18 · #11 ↗