Skip to content

Cloud Audit Logs trong IAM — Admin Activity, Data Access và Policy Denied

Tại sao Audit Logging là backbone của IAM security

IAM grant và revoke access, nhưng bản thân IAM không biết khi nào access đó được dùng. Cloud Audit Logs là cơ chế ghi lại "ai đã làm gì, trên resource nào, khi nào" — thông tin không thể thiếu cho:

  • Forensic investigation: Khi có incident, trace backward để biết attacker đã làm gì
  • Compliance: PCI-DSS, HIPAA, SOC 2 đều yêu cầu audit trail đầy đủ
  • Anomaly detection: Phát hiện access patterns bất thường
  • IAM policy validation: Verify rằng actual access patterns khớp với intended IAM design

GCP tích hợp audit logging vào platform từ đầu (không phải afterthought), nhưng model của nó có một số subtleties quan trọng — đặc biệt về chi phí của Data Access logsenablement defaults khác nhau cho từng log type.


Bốn loại Cloud Audit Logs

1. Admin Activity Audit Logs

Ghi lại gì: Các operations thay đổi configuration hoặc metadata của GCP resources.

Ví dụ events:

  • SetIamPolicy — thay đổi IAM policy của resource
  • CreateBucket, DeleteBucket — tạo/xóa GCS bucket
  • CreateInstance, StopInstance — tạo/dừng VM
  • CreateServiceAccount, DeleteServiceAccount
  • CreateCustomRole, UpdateCustomRole

Enabled theo mặc định: Luôn bật, không thể disable.

Chi phí: Miễn phí — không tính vào log ingestion cost.

Retention: 400 ngày (trong Log Bucket _Required, không thể delete hay modify).

Tại sao Admin Activity logs không thể disable: Google thiết kế như vậy để đảm bảo mọi changes đến configuration có thể được audit. Nếu có thể disable, attacker sau khi compromise một account có thể disable logging trước khi thực hiện actions.

2. Data Access Audit Logs

Ghi lại gì: Các API calls đọc metadata hoặc user data, và các API calls tạo/modify user data.

Ví dụ events:

  • storage.objects.get — đọc một GCS object
  • bigquery.jobs.query — query BigQuery
  • bigquery.tables.getData — đọc BigQuery table data
  • GetIamPolicy — xem IAM policy (đây cũng là Data Access log, vì đọc metadata)

Enabled theo mặc định: KHÔNG. Mặc định, Data Access logs bị tắt cho hầu hết services.

Ngoại lệ: BigQuery Data Access logs được bật mặc định.

Chi phí: Có phí — tính vào Cloud Logging ingestion cost (hiện tại ~$0.01/GB đến ~$0.50/GB tùy volume). Đây là nguồn chi phí logging lớn nhất nếu bật toàn bộ Data Access logs.

Retention: 30 ngày mặc định trong _Default Log Bucket (có thể extend bằng custom retention).

3. System Event Audit Logs

Ghi lại gì: GCP system actions không được trigger bởi user — các automated operations nội bộ của GCP.

Ví dụ events:

  • Live migration của VM
  • Auto-scale operations của managed instance groups
  • Automated node upgrades trong GKE

Enabled theo mặc định: Luôn bật.

Chi phí: Miễn phí.

Khi nào hữu ích: Debug incidents do GCP infrastructure actions (ví dụ: "VM khởi động lại lúc 3 giờ sáng" — kiểm tra System Events để xem có live migration hay node upgrade không).

4. Policy Denied Audit Logs

Ghi lại gì: Khi GCP từ chối một request vì vi phạm Organization Policy.

Ví dụ:

  • User cố tạo VM với external IP nhưng Org Policy deny external IPs
  • User cố tạo resource trong region bị restrict

Enabled theo mặc định: Luôn bật.

Chi phí: Được log miễn phí.

Lưu ý: Policy Denied logs là cho Organization Policy violations, không phải IAM permission denials. IAM 403 PERMISSION_DENIED errors không tự động tạo audit log entry. Để track IAM denials, cần export access denied responses từ application hoặc dùng custom logic.


Cấu trúc của một Audit Log Entry

Mỗi log entry trong Cloud Audit Logs là một LogEntry proto với các fields:

json
{
  "logName": "projects/my-project/logs/cloudaudit.googleapis.com%2Factivity",
  "resource": {
    "type": "gcs_bucket",
    "labels": {
      "bucket_name": "my-sensitive-bucket",
      "project_id": "my-project",
      "location": "us-central1"
    }
  },
  "timestamp": "2026-06-23T10:30:00Z",
  "severity": "NOTICE",
  "protoPayload": {
    "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
    "serviceName": "storage.googleapis.com",
    "methodName": "storage.buckets.delete",
    "authenticationInfo": {
      "principalEmail": "alice@example.com",
      "serviceAccountKeyName": "//iam.googleapis.com/projects/.../keys/abc123",
      "principalSubject": "user:alice@example.com"
    },
    "authorizationInfo": [
      {
        "resource": "projects/_/buckets/my-sensitive-bucket",
        "permission": "storage.buckets.delete",
        "granted": true,
        "resourceAttributes": {}
      }
    ],
    "requestMetadata": {
      "callerIp": "203.0.113.10",
      "callerSuppliedUserAgent": "google-cloud-sdk gcloud/400.0.0",
      "requestAttributes": {}
    },
    "status": {}
  }
}

Các fields quan trọng nhất

authenticationInfo.principalEmail: Email của principal thực hiện action. Đây là field đầu tiên cần xem khi investigate.

authenticationInfo.serviceAccountDelegationInfo: Nếu có SA impersonation chain, field này trace toàn bộ chain từ real caller đến impersonated SA.

json
"serviceAccountDelegationInfo": [
  {
    "firstPartyPrincipal": {
      "principalEmail": "alice@example.com"
    }
  }
]

Điều này cực kỳ valuable khi investigate: nếu thấy một SA gọi API, delegationInfo cho biết human nào đứng sau.

authorizationInfo: Danh sách các IAM permission checks được thực hiện, và kết quả (granted/denied). Một API call có thể trigger nhiều permission checks.

requestMetadata.callerIp: IP của caller. Cẩn thận: nếu gọi qua Workload Identity, IP có thể là internal IP của GKE node.

protoPayload.methodName: Tên method được gọi, theo format service.resource.action.


Enable Data Access Logs: Chiến Lược và Chi Phí

Enable Data Access logs

Data Access logs có thể enable per-service và per-project/folder/organization:

bash
# Lấy current audit config của project
gcloud projects get-iam-policy PROJECT_ID \
  --format=json | jq '.auditConfigs'

# Enable Data Access logs cho Cloud Storage (DATA_READ và DATA_WRITE)
gcloud projects set-iam-policy PROJECT_ID policy.json
json
// policy.json với auditConfigs
{
  "version": 3,
  "auditConfigs": [
    {
      "service": "storage.googleapis.com",
      "auditLogConfigs": [
        {"logType": "DATA_READ"},
        {"logType": "DATA_WRITE"}
      ]
    },
    {
      "service": "bigquery.googleapis.com",
      "auditLogConfigs": [
        {"logType": "DATA_READ"},
        {"logType": "DATA_WRITE"},
        {"logType": "ADMIN_READ"}
      ]
    }
  ]
}

Ba loại Data Access log type

Trong Data Access logging configuration, có ba sub-types:

  • DATA_READ: API calls đọc user-created data (GET, LIST)
  • DATA_WRITE: API calls tạo/modify/delete user-created data
  • ADMIN_READ: API calls đọc metadata configuration (GetIamPolicy, DescribeInstance...)

Chi phí: Tính toán trước khi bật

Bật Data Access logs cho một large project với nhiều traffic có thể tạo ra hàng TB logs mỗi tháng, với chi phí đáng kể.

Ví dụ: Một bucket GCS với 1 triệu object reads/ngày, mỗi log entry ~500 bytes:

  • 1,000,000 × 500 bytes = 500 MB logs/ngày
  • 500 MB × 30 ngày = 15 GB/tháng
  • 15 GB × $0.01/GB = $0.15/tháng (có thể cao hơn ở các log buckets khác)

Với production systems có nhiều services và high traffic, chi phí có thể lên đến hàng nghìn USD/tháng.

Chiến lược bật Data Access logs có kiểm soát

Approach 1: Selective enablement theo data sensitivity

  • Bật Data Access (DATA_READ + DATA_WRITE) cho services chứa sensitive data: Cloud Storage buckets có PII, BigQuery datasets production, Secret Manager
  • Không bật cho services low-sensitivity: Cloud Monitoring metrics reads, Cloud Logging reads

Approach 2: Exclusion filters Bật Data Access rộng hơn nhưng exclude traffic không cần thiết:

bash
# Tạo exclusion trong Log Sink để filter out healthcheck reads
gcloud logging sinks create bigquery-audit-sink \
  bigquery.googleapis.com/projects/ANALYTICS_PROJECT/datasets/audit_logs \
  --log-filter='logName:"cloudaudit.googleapis.com%2Fdata_access"
    AND -protoPayload.methodName="google.monitoring.v3.MetricService.ListTimeSeries"'

Approach 3: Organization-level policy với fine-grained exceptions

Enable Data Access ở organization level, exempt specific services:

json
{
  "auditConfigs": [
    {
      "service": "allServices",
      "auditLogConfigs": [
        {"logType": "DATA_WRITE"}
      ]
    },
    {
      "service": "monitoring.googleapis.com",
      "auditLogConfigs": [
        {
          "logType": "DATA_READ",
          "exemptedMembers": [
            "serviceAccount:monitoring-reader@project.iam.gserviceaccount.com"
          ]
        }
      ]
    }
  ]
}

Querying Audit Logs cho Security Use Cases

Tìm tất cả IAM policy changes trong khoảng thời gian

logName="projects/PROJECT/logs/cloudaudit.googleapis.com%2Factivity"
AND protoPayload.methodName=("SetIamPolicy" OR "UpdateRole" OR "CreateRole")
AND timestamp>="2026-06-01T00:00:00Z"
AND timestamp<"2026-06-24T00:00:00Z"

Tìm access từ IP bất thường

logName:"cloudaudit.googleapis.com%2Factivity"
AND protoPayload.requestMetadata.callerIp!~"10\\..*|172\\.16\\..*|192\\.168\\..*"
AND protoPayload.methodName="storage.objects.get"

Tìm SA key creation events (cần kiểm soát chặt)

logName:"cloudaudit.googleapis.com%2Factivity"
AND protoPayload.methodName="google.iam.admin.v1.CreateServiceAccountKey"

Phát hiện privilege escalation attempts

logName:"cloudaudit.googleapis.com%2Factivity"
AND (
  protoPayload.methodName="SetIamPolicy"
  OR protoPayload.methodName="google.iam.admin.v1.CreateRole"
  OR protoPayload.methodName="google.iam.admin.v1.UpdateRole"
)
AND protoPayload.authenticationInfo.principalEmail!~".*@developer.gserviceaccount.com"

Export audit logs sang BigQuery để phân tích dài hạn

bash
# Tạo log sink export sang BigQuery
gcloud logging sinks create iam-audit-sink \
  bigquery.googleapis.com/projects/SECURITY_PROJECT/datasets/audit_logs \
  --log-filter='logName:("cloudaudit.googleapis.com%2Factivity" OR "cloudaudit.googleapis.com%2Fdata_access")' \
  --use-partitioned-tables

# Grant BigQuery writer permission cho Logging service account
gcloud projects add-iam-policy-binding SECURITY_PROJECT \
  --member="serviceAccount:$(gcloud logging sinks describe iam-audit-sink --format='value(writerIdentity)')" \
  --role="roles/bigquery.dataEditor"

BigQuery giữ audit logs lâu hơn và cho phép query SQL phức tạp, bao gồm joins với IAM policy snapshots để correlation analysis.


Audit Logging trong IAM-specific actions

GetIamPolicySetIamPolicy

Hai operations này là quan trọng nhất cần monitor:

  • GetIamPolicy: Được log là ADMIN_READ event (Data Access log, cần enable)
  • SetIamPolicy: Được log là Admin Activity event (luôn on, miễn phí)

Ai có thể gọi GetIamPolicy? Bất kỳ principal có resourcemanager.projects.getIamPolicy permission. Nếu không bật ADMIN_READ Data Access logs, không có record ai đã xem IAM policy — quan trọng trong insider threat scenarios.

Service Account operations

Mọi operations trên service accounts (create, delete, disable, create keys) được log dưới Admin Activity:

methodName: "google.iam.admin.v1.CreateServiceAccount"
methodName: "google.iam.admin.v1.DeleteServiceAccount"
methodName: "google.iam.admin.v1.EnableServiceAccount"
methodName: "google.iam.admin.v1.DisableServiceAccount"
methodName: "google.iam.admin.v1.CreateServiceAccountKey"
methodName: "google.iam.admin.v1.DeleteServiceAccountKey"

Impersonation audit trail

Khi SA impersonation xảy ra, audit log của action được thực hiện (không phải log của generateAccessToken call) sẽ có serviceAccountDelegationInfo:

json
"authenticationInfo": {
  "principalEmail": "target-sa@project.iam.gserviceaccount.com",
  "serviceAccountDelegationInfo": [
    {
      "firstPartyPrincipal": {
        "principalEmail": "alice@example.com"
      }
    }
  ]
}

Field này cho thấy action được thực hiện bởi target-sa nhưng được initiated bởi alice@example.com. Điều này làm audit trail của impersonation rất clean và traceable.


References