AnalysisType: rule
DedupPeriodMinutes: 90
DisplayName: GCP Firewall Rule Created
Enabled: true
Filename: gcp_firewall_rule_created.py
RuleID: "GCP.Firewall.Rule.Created"
Severity: Low
LogTypes:
- GCP.AuditLog
Tags:
- GCP
- Firewall
- Networking
- Infrastructure
Description: >
This rule detects creations of GCP firewall rules.
Runbook: >
Ensure that the rule creation was expected. Firewall rule creations can expose [vulnerable] resoures to the internet.
Reference: https://cloud.google.com/firewall/docs/about-firewalls
Tests:
- Name: compute.firewalls.create-should-alert
LogType: GCP.AuditLog
ExpectedResult: true
Log:
{
"insertid": "-xxxxxxxxxxxx",
"logname": "projects/test-project-123456/logs/cloudaudit.googleapis.com%2Factivity",
"operation":
{
"first": true,
"id": "operation-1684869580331-5fc6144d418a9-e1332ca3-59c615ac",
"producer": "compute.googleapis.com",
},
"protoPayload":
{
"at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": { "principalEmail": "user@domain.com" },
"authorizationInfo":
[
{
"granted": true,
"permission": "compute.firewalls.update",
"resourceAttributes":
{
"name": "projects/test-project-123456/global/firewalls/firewall-create",
"service": "compute",
"type": "compute.firewalls",
},
},
{
"granted": true,
"permission": "compute.networks.updatePolicy",
"resourceAttributes":
{
"name": "projects/test-project-123456/global/networks/default",
"service": "compute",
"type": "compute.networks",
},
},
],
"methodName": "v1.compute.firewalls.insert",
"request":
{
"@type": "type.googleapis.com/compute.firewalls.insert",
"denieds": [{ "IPProtocol": "all" }],
},
"requestMetadata":
{
"callerIP": "12.12.12.12",
"callerSuppliedUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36,gzip(gfe),gzip(gfe)",
"destinationAttributes": {},
"requestAttributes":
{
"auth": {},
"reason": "8uSywAYQGg5Db2xpc2V1bSBGbG93cw",
"time": "2023-05-23T19:19:41.154751Z",
},
},
"resourceName": "projects/test-project-123456/global/firewalls/firewall-create",
"response":
{
"@type": "type.googleapis.com/operation",
"id": "896785227463044899",
"insertTime": "2023-05-23T12:19:40.876-07:00",
"name": "operation-1684869580331-5fc6144d418a9-e1332ca3-59c615ac",
"operationType": "patch",
"progress": "0",
"selfLink": "https://www.googleapis.com/compute/v1/projects/test-project-123456/global/operations/operation-1684869580331-5fc6144d418a9-e1332ca3-59c615ac",
"selfLinkWithId": "https://www.googleapis.com/compute/v1/projects/test-project-123456/global/operations/896785227463044899",
"startTime": "2023-05-23T12:19:40.888-07:00",
"status": "RUNNING",
"targetId": "6563507997690081088",
"targetLink": "https://www.googleapis.com/compute/v1/projects/test-project-123456/global/firewalls/firewall-create",
"user": "user@domain.com",
},
"serviceName": "compute.googleapis.com",
},
"receivetimestamp": "2023-05-23 19:19:41.238",
"resource":
{
"labels":
{
"firewall_rule_id": "6563507997690081088",
"project_id": "test-project-123456",
},
"type": "gce_firewall_rule",
},
"severity": "NOTICE",
"timestamp": "2023-05-23 19:19:40.353",
}
- Name: appengine.firewall.create-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": "user@domain.com" },
"authorizationInfo":
[
{
"granted": true,
"permission": "appengine.applications.update",
"resource": "apps/test-project-123456",
"resourceAttributes": {},
},
],
"methodName": "google.appengine.v1.Firewall.CreateIngressRule",
"requestMetadata":
{
"callerIP": "12.12.12.12",
"destinationAttributes": {},
"requestAttributes":
{ "auth": {}, "time": "2023-05-23T19:28:35.172216Z" },
},
"resourceName": "apps/test-project-123456",
"serviceData":
{
"@type": "type.googleapis.com/google.appengine.v1beta4.AuditData",
},
"serviceName": "appengine.googleapis.com",
"status": {},
},
"receivetimestamp": "2023-05-23 19:28:35.479",
"resource":
{
"labels":
{
"module_id": "",
"project_id": "test-project-123456",
"version_id": "",
"zone": "",
},
"type": "gae_app",
},
"severity": "NOTICE",
"timestamp": "2023-05-23 19:28:35.049",
}
- Name: compute.non-create.firewall.method-should-not-alert
LogType: GCP.AuditLog
ExpectedResult: false
Log: { "methodName": "v1.compute.firewalls.patch" }
- Name: appengine.compute.non-create.firewall.method-should-not-alert
LogType: GCP.AuditLog
ExpectedResult: false
Log: { "methodName": "appengine.compute.v1.Firewall.PatchIngressRule" }
- Name: randomservice.firewall-create.method-should-alert
LogType: GCP.AuditLog
ExpectedResult: true
Log:
{
"protoPayload":
{
"authenticationInfo": { "principalEmail": "user@domain.com" },
"methodName": "randomservice.compute.v1.Firewall.CreateIngressRule",
"resourceName": "randomservice/test-project-123456/firewall/ingressRules/1000",
"requestMetadata":
{
"callerIP": "12.12.12.12",
"destinationAttributes": {},
"requestAttributes":
{ "auth": {}, "time": "2023-05-23T19:28:44.663413Z" },
},
},
"resource":
{
"labels":
{
"firewall_rule_id": "6563507997690081088",
"project_id": "test-project-123456",
},
"type": "gce_firewall_rule",
},
}
# ------ paired body: gcp_firewall_rule_created.py ------
from panther_gcp_helpers import gcp_alert_context
RULE_CREATED_PARTS = [
".Firewall.Create",
".compute.firewalls.insert",
]
def rule(event):
method = event.deep_get("protoPayload", "methodName", default="")
return any(part in method for part in RULE_CREATED_PARTS)
def title(event):
actor = event.deep_get(
"protoPayload", "authenticationInfo", "principalEmail", default="<ACTOR_NOT_FOUND>"
)
resource = event.deep_get(
"protoPayload",
"resourceName",
default="<RESOURCE_NOT_FOUND>",
)
resource_id = event.deep_get(
"resource",
"labels",
"firewall_rule_id",
default="<RESOURCE_ID_NOT_FOUND>",
)
if resource_id != "<RESOURCE_ID_NOT_FOUND>":
return f"[GCP]: [{actor}] created firewall rule with resource ID [{resource_id}]"
return f"[GCP]: [{actor}] created firewall rule for resource [{resource}]"
def dedup(event):
actor = event.deep_get(
"protoPayload", "authenticationInfo", "principalEmail", default="<ACTOR_NOT_FOUND>"
)
return actor
def alert_context(event):
return gcp_alert_context(event)