Detection rules › Panther
GCP Service Account Access Denied
This rule detects deletions of GCP Log Buckets or Sinks.
Rule body yaml
---
AnalysisType: rule
DedupPeriodMinutes: 5
Threshold: 30
DisplayName: GCP Service Account Access Denied
Enabled: true
Filename: gcp_service_account_access_denied.py
RuleID: "GCP.Service.Account.Access.Denied"
Severity: Low
LogTypes:
- GCP.AuditLog
Tags:
- GCP
- Service Account
- Access
Description: >
This rule detects deletions of GCP Log Buckets or Sinks.
Runbook: >
Ensure that the bucket or sink deletion was expected. Adversaries may do this to cover their tracks.
Reference: https://cloud.google.com/iam/docs/service-account-overview
Tests:
- Name: service-account.access-denied-should-alert
LogType: GCP.AuditLog
ExpectedResult: true
Log:
{
"insertid": "xxxxxxxxxxxx",
"logname": "projects/test-project-123456/logs/cloudaudit.googleapis.com%2Factivity",
"protoPayload":
{
"at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo":
{
"principalEmail": "test-no-perms@test-project-123456.iam.gserviceaccount.com",
"principalSubject": "serviceAccount:test-no-perms@test-project-123456.iam.gserviceaccount.com",
"serviceAccountKeyName": "//iam.googleapis.com/projects/test-project-123456/serviceAccounts/test-no-perms@test-project-123456.iam.gserviceaccount.com/keys/a0064fe0ef82b9e256b8b093d927ee842a19da34",
},
"authorizationInfo":
[
{
"permission": "iam.serviceAccounts.create",
"resource": "projects/test-project-123456",
"resourceAttributes": {},
},
],
"methodName": "google.iam.admin.v1.CreateServiceAccount",
"request":
{
"@type": "type.googleapis.com/google.iam.admin.v1.CreateServiceAccountRequest",
"account_id": "test123",
"name": "projects/test-project-123456",
"service_account": {},
},
"requestMetadata":
{
"callerIP": "12.12.12.12",
"callerSuppliedUserAgent": "google-cloud-sdk gcloud/431.0.0 command/gcloud.iam.service-accounts.create invocation-id/b2ea5dab8c9b4bff8bc15ab299dff79e environment/devshell environment-version/None client-os/LINUX client-os-ver/5.15.107 client-pltf-arch/x86_64 interactive/True from-script/False python/3.9.2 term/screen (Linux 5.15.107+),gzip(gfe)",
"destinationAttributes": {},
"requestAttributes":
{ "auth": {}, "time": "2023-05-24T21:12:55.211301546Z" },
},
"resourceName": "projects/test-project-123456",
"response":
{
"@type": "type.googleapis.com/google.iam.admin.v1.ServiceAccount",
},
"serviceName": "iam.googleapis.com",
"status":
{
"code": 7,
"details":
[
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"domain": "iam.googleapis.com",
"metadata":
{ "permission": "iam.serviceAccounts.create" },
"reason": "IAM_PERMISSION_DENIED",
},
],
"message": "Permission 'iam.serviceAccounts.create' denied on resource (or it may not exist).",
},
},
"receivetimestamp": "2023-05-24 21:12:55.964",
"resource":
{
"labels":
{
"email_id": "",
"project_id": "test-project-123456",
"unique_id": "",
},
"type": "service_account",
},
"severity": "ERROR",
"timestamp": "2023-05-24 21:12:55.145",
}
- Name: service-account.access-grated-should-not-alert
LogType: GCP.AuditLog
ExpectedResult: false
Log:
{
"insertId": "xxxxxxxxxxxx",
"logName": "projects/test-project-123456/logs/cloudaudit.googleapis.com%2Factivity",
"protoPayload":
{
"at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": {},
"authorizationInfo":
[
{
"granted": true,
"permission": "iam.serviceAccounts.create",
"resource": "projects/test-project-123456",
"resourceAttributes": {},
},
],
"methodName": "google.iam.admin.v1.CreateServiceAccount",
"request":
{
"@type": "type.googleapis.com/google.iam.admin.v1.CreateServiceAccountRequest",
"account_id": "appengine-default",
"name": "projects/test-project-123456",
"service_account":
{
"display_name": "App Engine default service account",
"email": "test-project-123456@appspot.gserviceaccount.com",
},
},
"requestMetadata":
{
"callerIP": "private",
"destinationAttributes": {},
"requestAttributes":
{ "auth": {}, "time": "2023-05-23T19:27:42.510877536Z" },
},
"resourceName": "projects/test-project-123456",
"response":
{
"@type": "type.googleapis.com/google.iam.admin.v1.ServiceAccount",
"display_name": "App Engine default service account",
"email": "test-project-123456@appspot.gserviceaccount.com",
"etag": "MDEwMjE5MjA=",
"name": "projects/test-project-123456/serviceAccounts/test-project-123456@appspot.gserviceaccount.com",
"oauth2_client_id": "114240096070638624820",
"project_id": "test-project-123456",
"unique_id": "114240096070638624820",
},
"serviceName": "iam.googleapis.com",
"status": { "message": "OK" },
},
"receiveTimestamp": "2023-05-23 19:27:44.037",
"resource":
{
"labels":
{
"email_id": "test-project-123456@appspot.gserviceaccount.com",
"project_id": "test-project-123456",
"unique_id": "114240096070638624820",
},
"type": "service_account",
},
"severity": "NOTICE",
"timestamp": "2023-05-23 19:27:42.492",
}
Detection logic
Condition
protoPayload.status.details.reason eq "IAM_PERMISSION_DENIED"
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
protoPayload.status.details.reason | eq |
|
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
project | resource.labels.project_id |
principal | protoPayload.authenticationInfo.principalEmail |
caller_ip | protoPayload.requestMetadata.callerIP |
methodName | protoPayload.methodName |
resourceName | protoPayload.resourceName |
serviceName | protoPayload.serviceName |