AnalysisType: rule
Filename: gcp_iam_corp_email.py
RuleID: "GCP.IAM.CorporateEmail"
DisplayName: "GCP Corporate Email Not Used"
Enabled: true
DedupPeriodMinutes: 720 # 12 hours
LogTypes:
- GCP.AuditLog
Tags:
- GCP
- Identity & Access Management
- Persistence:Create Account
Reports:
MITRE ATT&CK:
- TA0003:T1136
CIS:
- 1.1
Severity: Low
Description: Unexpected domain is being used instead of a corporate email
Runbook: Remove the user
Reference: https://cloud.google.com/iam/docs/service-account-overview
SummaryAttributes:
- severity
- p_any_ip_addresses
- p_any_domain_names
Tests:
- Name: Gmail account added
ExpectedResult: true
Log:
{
"protoPayload":
{
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"status": {},
"authenticationInfo": { "principalEmail": "test@runpanther.com" },
"requestMetadata":
{
"callerIp": "136.24.229.58",
"callerSuppliedUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36,gzip(gfe)",
"requestAttributes": {},
"destinationAttributes": {},
},
"serviceName": "cloudresourcemanager.googleapis.com",
"methodName": "SetIamPolicy",
"authorizationInfo":
[
{
"resource": "projects/western-verve-123456",
"permission": "resourcemanager.projects.setIamPolicy",
"granted": true,
"resourceAttributes": {},
},
{
"resource": "projects/western-verve-123456",
"permission": "resourcemanager.projects.setIamPolicy",
"granted": true,
"resourceAttributes": {},
},
],
"resourceName": "projects/western-verve-123456",
"serviceData":
{
"@type": "type.googleapis.com/google.iam.v1.logging.AuditData",
"policyDelta":
{
"bindingDeltas":
[
{
"action": "ADD",
"role": "roles/viewer",
"member": "user:username@gmail.com",
},
],
},
},
"request":
{
"resource": "western-verve-123456",
"@type": "type.googleapis.com/google.iam.v1.SetIamPolicyRequest",
"policy":
{
"bindings":
[
{
"members": ["user:user-two@gmail.com"],
"role": "roles/appengine.serviceAdmin",
},
{
"members":
[
"serviceAccount:service-951849100836@compute-system.iam.gserviceaccount.com",
],
"role": "roles/compute.serviceAgent",
},
{
"role": "roles/editor",
"members":
[
"serviceAccount:951849100836-compute@developer.gserviceaccount.com",
"serviceAccount:951849100836@cloudservices.gserviceaccount.com",
],
},
{
"members": ["user:test@runpanther.com"],
"role": "roles/owner",
},
{
"members": ["user:user-two@gmail.com"],
"role": "roles/pubsub.admin",
},
{
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
"role": "roles/pubsub.subscriber",
},
{
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
"role": "roles/pubsub.viewer",
},
{
"role": "roles/resourcemanager.organizationAdmin",
"members": ["user:test@runpanther.com"],
},
{
"members": ["user:username@gmail.com"],
"role": "roles/viewer",
},
],
"etag": "BwWk8zJlg2o=",
},
},
"response":
{
"etag": "BwWlp7rH6tY=",
"bindings":
[
{
"members": ["user:user-two@gmail.com"],
"role": "roles/appengine.serviceAdmin",
},
{
"members":
[
"serviceAccount:service-951849100836@compute-system.iam.gserviceaccount.com",
],
"role": "roles/compute.serviceAgent",
},
{
"members":
[
"serviceAccount:951849100836-compute@developer.gserviceaccount.com",
"serviceAccount:951849100836@cloudservices.gserviceaccount.com",
],
"role": "roles/editor",
},
{
"members": ["user:test@runpanther.com"],
"role": "roles/owner",
},
{
"role": "roles/pubsub.admin",
"members": ["user:user-two@gmail.com"],
},
{
"role": "roles/pubsub.subscriber",
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
},
{
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
"role": "roles/pubsub.viewer",
},
{
"members": ["user:test@runpanther.com"],
"role": "roles/resourcemanager.organizationAdmin",
},
{
"members": ["user:username@gmail.com"],
"role": "roles/viewer",
},
],
"@type": "type.googleapis.com/google.iam.v1.Policy",
},
},
"insertId": "mrbji0dal80",
"resource":
{
"type": "project",
"labels": { "project_id": "western-verve-123456" },
},
"timestamp": "2020-05-15T03:51:35.019Z",
"severity": "NOTICE",
"logName": "projects/western-verve-123456/logs/cloudaudit.googleapis.com%2Factivity",
"receiveTimestamp": "2020-05-15T03:51:35.977314225Z",
}
- Name: Expected account added
ExpectedResult: false
Log:
{
"protoPayload":
{
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"status": {},
"authenticationInfo": { "principalEmail": "test@runpanther.com" },
"requestMetadata":
{
"callerIp": "136.24.229.58",
"callerSuppliedUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36,gzip(gfe)",
"requestAttributes": {},
"destinationAttributes": {},
},
"serviceName": "cloudresourcemanager.googleapis.com",
"methodName": "SetIamPolicy",
"authorizationInfo":
[
{
"resource": "projects/western-verve-123456",
"permission": "resourcemanager.projects.setIamPolicy",
"granted": true,
"resourceAttributes": {},
},
{
"resource": "projects/western-verve-123456",
"permission": "resourcemanager.projects.setIamPolicy",
"granted": true,
"resourceAttributes": {},
},
],
"resourceName": "projects/western-verve-123456",
"serviceData":
{
"@type": "type.googleapis.com/google.iam.v1.logging.AuditData",
"policyDelta":
{
"bindingDeltas":
[
{
"action": "ADD",
"role": "roles/viewer",
"member": "user:username@runpanther.com",
},
],
},
},
"request":
{
"resource": "western-verve-123456",
"@type": "type.googleapis.com/google.iam.v1.SetIamPolicyRequest",
"policy":
{
"bindings":
[
{
"members": ["user:user-two@gmail.com"],
"role": "roles/appengine.serviceAdmin",
},
{
"members":
[
"serviceAccount:service-951849100836@compute-system.iam.gserviceaccount.com",
],
"role": "roles/compute.serviceAgent",
},
{
"role": "roles/editor",
"members":
[
"serviceAccount:951849100836-compute@developer.gserviceaccount.com",
"serviceAccount:951849100836@cloudservices.gserviceaccount.com",
],
},
{
"members": ["user:test@runpanther.com"],
"role": "roles/owner",
},
{
"members": ["user:user-two@gmail.com"],
"role": "roles/pubsub.admin",
},
{
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
"role": "roles/pubsub.subscriber",
},
{
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
"role": "roles/pubsub.viewer",
},
{
"role": "roles/resourcemanager.organizationAdmin",
"members": ["user:test@runpanther.com"],
},
{
"members": ["user:username@gmail.com"],
"role": "roles/viewer",
},
],
"etag": "BwWk8zJlg2o=",
},
},
"response":
{
"etag": "BwWlp7rH6tY=",
"bindings":
[
{
"members": ["user:user-two@gmail.com"],
"role": "roles/appengine.serviceAdmin",
},
{
"members":
[
"serviceAccount:service-951849100836@compute-system.iam.gserviceaccount.com",
],
"role": "roles/compute.serviceAgent",
},
{
"members":
[
"serviceAccount:951849100836-compute@developer.gserviceaccount.com",
"serviceAccount:951849100836@cloudservices.gserviceaccount.com",
],
"role": "roles/editor",
},
{
"members": ["user:test@runpanther.com"],
"role": "roles/owner",
},
{
"role": "roles/pubsub.admin",
"members": ["user:user-two@gmail.com"],
},
{
"role": "roles/pubsub.subscriber",
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
},
{
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
"role": "roles/pubsub.viewer",
},
{
"members": ["user:test@runpanther.com"],
"role": "roles/resourcemanager.organizationAdmin",
},
{
"members": ["user:username@gmail.com"],
"role": "roles/viewer",
},
],
"@type": "type.googleapis.com/google.iam.v1.Policy",
},
},
"insertId": "mrbji0dal80",
"resource":
{
"type": "project",
"labels": { "project_id": "western-verve-123456" },
},
"timestamp": "2020-05-15T03:51:35.019Z",
"severity": "NOTICE",
"logName": "projects/western-verve-123456/logs/cloudaudit.googleapis.com%2Factivity",
"receiveTimestamp": "2020-05-15T03:51:35.977314225Z",
}
- Name: Expected GCP service account added by Service Agent Manager
ExpectedResult: false
Log:
{
"protoPayload":
{
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"status": {},
"authenticationInfo":
{
"principalEmail": "service-agent-manager@system.gserviceaccount.com",
},
"requestMetadata":
{
"callerIp": "136.24.229.58",
"callerSuppliedUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36,gzip(gfe)",
"requestAttributes": {},
"destinationAttributes": {},
},
"serviceName": "cloudresourcemanager.googleapis.com",
"methodName": "SetIamPolicy",
"authorizationInfo":
[
{
"resource": "projects/western-verve-123456",
"permission": "resourcemanager.projects.setIamPolicy",
"granted": true,
"resourceAttributes": {},
},
{
"resource": "projects/western-verve-123456",
"permission": "resourcemanager.projects.setIamPolicy",
"granted": true,
"resourceAttributes": {},
},
],
"resourceName": "projects/western-verve-123456",
"serviceData":
{
"@type": "type.googleapis.com/google.iam.v1.logging.AuditData",
"policyDelta":
{
"bindingDeltas":
[
{
"action": "ADD",
"role": "roles/logging.serviceAgent",
"member": "serviceAccount:service-951849100836@gcp-sa-logging.iam.gserviceaccount.com",
},
],
},
},
"request":
{
"resource": "western-verve-123456",
"@type": "type.googleapis.com/google.iam.v1.SetIamPolicyRequest",
"policy":
{
"bindings":
[
{
"members": ["user:user-two@gmail.com"],
"role": "roles/appengine.serviceAdmin",
},
{
"members":
[
"serviceAccount:service-951849100836@compute-system.iam.gserviceaccount.com",
],
"role": "roles/compute.serviceAgent",
},
{
"role": "roles/editor",
"members":
[
"serviceAccount:951849100836-compute@developer.gserviceaccount.com",
"serviceAccount:951849100836@cloudservices.gserviceaccount.com",
],
},
{
"members": ["user:test@runpanther.com"],
"role": "roles/owner",
},
{
"members": ["user:user-two@gmail.com"],
"role": "roles/pubsub.admin",
},
{
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
"role": "roles/pubsub.subscriber",
},
{
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
"role": "roles/pubsub.viewer",
},
{
"role": "roles/resourcemanager.organizationAdmin",
"members": ["user:test@runpanther.com"],
},
{
"members":
[
"serviceAccount:service-951849100836@gcp-sa-logging.iam.gserviceaccount.com",
],
"role": "roles/logging.ServiceAgent",
},
],
"etag": "BwWk8zJlg2o=",
},
},
"response":
{
"etag": "BwWlp7rH6tY=",
"bindings":
[
{
"members": ["user:user-two@gmail.com"],
"role": "roles/appengine.serviceAdmin",
},
{
"members":
[
"serviceAccount:service-951849100836@compute-system.iam.gserviceaccount.com",
],
"role": "roles/compute.serviceAgent",
},
{
"members":
[
"serviceAccount:951849100836-compute@developer.gserviceaccount.com",
"serviceAccount:951849100836@cloudservices.gserviceaccount.com",
],
"role": "roles/editor",
},
{
"members": ["user:test@runpanther.com"],
"role": "roles/owner",
},
{
"role": "roles/pubsub.admin",
"members": ["user:user-two@gmail.com"],
},
{
"role": "roles/pubsub.subscriber",
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
},
{
"members":
[
"serviceAccount:pubsub-reader@western-verve-123456.iam.gserviceaccount.com",
],
"role": "roles/pubsub.viewer",
},
{
"members": ["user:test@runpanther.com"],
"role": "roles/resourcemanager.organizationAdmin",
},
{
"members":
[
"serviceAccount:service-951849100836@gcp-sa-logging.iam.gserviceaccount.com",
],
"role": "roles/logging.ServiceAgent",
},
],
"@type": "type.googleapis.com/google.iam.v1.Policy",
},
},
"insertId": "mrbji0dal80",
"resource":
{
"type": "project",
"labels": { "project_id": "western-verve-123456" },
},
"timestamp": "2020-05-15T03:51:35.019Z",
"severity": "NOTICE",
"logName": "projects/western-verve-123456/logs/cloudaudit.googleapis.com%2Factivity",
"receiveTimestamp": "2020-05-15T03:51:35.977314225Z",
}
# ------ paired body: gcp_iam_corp_email.py ------
from fnmatch import fnmatch
from panther_base_helpers import deep_get
# These patterns indicate members which might be added by default by some GCP services
ACCEPTED_MEMBER_PATTERNS = [
"serviceAccount:*@*.gserviceaccount.com",
"serviceAccount:*.svc.id.goog[*",
"principalSet://iam.googleapis.com/projects/*/workloadIdentityPools/*",
]
def rule(event):
if event.deep_get("protoPayload", "methodName") != "SetIamPolicy":
return False
service_data = event.deep_get("protoPayload", "serviceData")
if not service_data:
return False
authenticated = event.deep_get(
"protoPayload", "authenticationInfo", "principalEmail", default=""
)
expected_domain = authenticated.split("@")[-1]
binding_deltas = deep_get(service_data, "policyDelta", "bindingDeltas")
if not binding_deltas:
return False
for delta in binding_deltas:
if delta.get("action") != "ADD":
continue
member = delta.get("member", "")
if any(fnmatch(member, pattern) for pattern in ACCEPTED_MEMBER_PATTERNS):
continue # Skip this member, check others
if member.endswith(f"@{expected_domain}"):
continue # Skip this member, check others
return True # Found a suspicious member - alert
return False # No suspicious members found
def title(event):
return (
f"A GCP IAM account has been created with an unexpected email domain in "
f"{event.deep_get('resource', 'labels', 'project_id', default='<UNKNOWN_PROJECT>')}"
)