From dbb8eb1f80068c9286c58cbbf81bd85f5910e43a Mon Sep 17 00:00:00 2001 From: om986 Date: Wed, 30 Sep 2026 19:02:22 -0400 Subject: [PATCH] Document GCP Admin Activity events on attack paths. Co-authored-by: Cursor --- src/pages/docs/api.astro | 2 +- src/pages/docs/architecture.astro | 4 +-- src/pages/docs/attack-paths.astro | 14 ++++---- src/pages/docs/cli.astro | 4 +-- src/pages/docs/collectors/aws.astro | 5 +-- src/pages/docs/collectors/azure.astro | 4 +-- src/pages/docs/collectors/gcp.astro | 52 +++++++++++++++++++++++++-- src/pages/docs/collectors/index.astro | 4 +-- src/pages/docs/open-source.astro | 9 ++--- src/pages/docs/schema.astro | 2 +- 10 files changed, 76 insertions(+), 24 deletions(-) diff --git a/src/pages/docs/api.astro b/src/pages/docs/api.astro index e88cf94..aa437cf 100644 --- a/src/pages/docs/api.astro +++ b/src/pages/docs/api.astro @@ -128,7 +128,7 @@ curl -s -H "Authorization: Bearer $OM_API_SECRET" \\

GET /v1/graph/query?name=internet-to-datastore returns query, summary, and paths. Each path is an array of nodes. When a - CloudTrail or Activity Log event’s resource node is on a path, audits lists that + CloudTrail, Activity Log, or Admin Activity event’s resource node is on a path, audits lists that event with index set to the path’s position. Unknown names are 400. The six names are listed by GET /v1/graph/queries as {`{"queries":[{"name":"...","description":"..."}]}`}. See diff --git a/src/pages/docs/architecture.astro b/src/pages/docs/architecture.astro index e503b33..083184f 100644 --- a/src/pages/docs/architecture.astro +++ b/src/pages/docs/architecture.astro @@ -34,8 +34,8 @@ import DocsLayout from '@/layouts/DocsLayout.astro';

Core is one Go module. The CLI and the API share internal/graph, internal/rules, and the collectors. PostgreSQL is the graph store. Phase 3 adds - the plugin SDK, the embedded rule pack, a Helm chart, CloudTrail management events on - the AWS collector, and Activity Log events on the Azure collector, on top of the Phase 2 feature set. + the plugin SDK, the embedded rule pack, a Helm chart, and cloud audit context from + CloudTrail, Activity Log, and Admin Activity logs, on top of the Phase 2 feature set.

{`Cloud / Kubernetes APIs
         │
diff --git a/src/pages/docs/attack-paths.astro b/src/pages/docs/attack-paths.astro
index 45d06c8..ad52761 100644
--- a/src/pages/docs/attack-paths.astro
+++ b/src/pages/docs/attack-paths.astro
@@ -26,7 +26,7 @@ import DocsLayout from '@/layouts/DocsLayout.astro';
     {
       question: 'Where do cloud audit events show up on a path?',
       answer:
-        'om scan aws stores recent CloudTrail management events, and om scan azure stores recent Activity Log events, on the identity and resource they name. GET /v1/graph/query returns those events in audits when the resource node is on a path. om paths run prints the same lines under the path.',
+        'om scan aws stores recent CloudTrail management events, om scan azure stores recent Activity Log events, and om scan gcp stores recent Admin Activity audit logs, on the identity and resource they name. GET /v1/graph/query returns those events in audits when the resource node is on a path. om paths run prints the same lines under the path.',
     },
   ]}
   related={[
@@ -180,8 +180,9 @@ import DocsLayout from '@/layouts/DocsLayout.astro';
 
   

Audit events on a path

- om scan aws reads CloudTrail management events, and om scan azure - reads administrative Activity Log events, from the last 24 hours. A match is stored as + om scan aws reads CloudTrail management events, om scan azure + reads administrative Activity Log events, and om scan gcp reads Admin Activity + audit logs, from the last 24 hours. A match is stored as audit_events on the identity and the resource the event names. A match requires both nodes to already be in the scan, and the resource has to sit on an exposed path: an internet-reachable workload, something that workload assumes or can access, a public @@ -194,9 +195,10 @@ import DocsLayout from '@/layouts/DocsLayout.astro'; paths. The same event stored on two nodes of one path is listed once. om paths run prints the time, event name, principal, and resource under that path. The console does the same. GetObject is an S3 data event and is not in - this slice. Entra ID sign-in logs and GCP Cloud Audit Logs are not collected. See the - AWS collector and the - Azure collector. + this slice. Entra ID sign-in logs and GCP Data Access logs are not collected. See the + AWS collector, the + Azure collector, and the + GCP collector.

Reading an empty result

diff --git a/src/pages/docs/cli.astro b/src/pages/docs/cli.astro index 6b2b85a..5f913f9 100644 --- a/src/pages/docs/cli.astro +++ b/src/pages/docs/cli.astro @@ -53,7 +53,7 @@ import DocsLayout from '@/layouts/DocsLayout.astro'; om scan gcp - GCE, GCS, and service accounts in GCP_PROJECT_ID. + GCE, GCS, service accounts, and Admin Activity audit logs from the last 24 hours in GCP_PROJECT_ID. om scan k8s @@ -77,7 +77,7 @@ import DocsLayout from '@/layouts/DocsLayout.astro'; om paths run <name> - Run one named query and print paths. A CloudTrail or Activity Log event whose resource is on a path is printed under that path. + Run one named query and print paths. A CloudTrail, Activity Log, or Admin Activity event whose resource is on a path is printed under that path. om graph stats diff --git a/src/pages/docs/collectors/aws.astro b/src/pages/docs/collectors/aws.astro index af1cd85..bf25f3d 100644 --- a/src/pages/docs/collectors/aws.astro +++ b/src/pages/docs/collectors/aws.astro @@ -122,8 +122,9 @@ import DocsLayout from '@/layouts/DocsLayout.astro';

GET /v1/graph/query and om paths run list those events in audits when the resource node is on the returned path. The console prints the - same lines under the path. GCP Cloud Audit Logs are not collected. Azure Activity Log events - are collected by om scan azure. + same lines under the path. Azure Activity Log events are collected by + om scan azure. GCP Admin Activity logs are collected by + om scan gcp.

Read-only actions

diff --git a/src/pages/docs/collectors/azure.astro b/src/pages/docs/collectors/azure.astro index ce63ca0..3ef1811 100644 --- a/src/pages/docs/collectors/azure.astro +++ b/src/pages/docs/collectors/azure.astro @@ -132,8 +132,8 @@ az login GET /v1/graph/query and om paths run list those events in audits when the resource node is on the returned path. The console prints the same lines under the path. Entra ID sign-in logs and storage data-plane reads are not in - the Activity Log, so this slice does not collect them. GCP Cloud Audit Logs are not - collected. + the Activity Log, so this slice does not collect them. GCP Admin Activity logs are collected + by om scan gcp.

Read access

diff --git a/src/pages/docs/collectors/gcp.astro b/src/pages/docs/collectors/gcp.astro index c6705c9..bf5ae4e 100644 --- a/src/pages/docs/collectors/gcp.astro +++ b/src/pages/docs/collectors/gcp.astro @@ -6,7 +6,7 @@ import DocsLayout from '@/layouts/DocsLayout.astro';

GCP security collector

@@ -38,7 +38,7 @@ gcloud auth application-default login Compute instances.aggregatedList - Workload. Properties: resource_id (self link), public_ip (NAT IP, or empty), status. A NAT IP adds REACHABLE from internet:global. Firewall rules are not consulted. Each attached service account gets an ASSUMES edge from the instance. + Workload. Properties: resource_id (self link), public_ip (NAT IP, or empty), status. A NAT IP or a public load balancer adds REACHABLE from internet:global when a firewall allow is not covered by a higher-priority deny. The firewall is a Network node. Each attached service account gets an ASSUMES edge from the instance. Storage bucket list, then each bucket’s IAM policy @@ -48,6 +48,14 @@ gcloud auth application-default login IAM service accounts, then the project IAM policy Identity named by email, with email and admin_access. Project bindings that grant object access add CAN_ACCESS to every bucket in the project. + + Cloud SQL instances + Datastore with resource_id (connection name), service: cloudsql, public_access, and sensitivity when a user label names it. A workload gets CAN_ACCESS when it shares the instance’s private-IP network, or its public IP is in an authorized network. + + + Logging entries.list for the Admin Activity log, last 24 hours + Up to five audit_events on the identity and the resource the event names. See below. + @@ -106,4 +114,44 @@ gcloud auth application-default login included. A bucket policy that cannot be read is stored as not public and adds no CAN_ACCESS edges. The scan continues.

+ +

Cloud Audit Logs

+

+ After inventory is built, the scan lists Admin Activity log entries for the project from the + last 24 hours. The call is Logging entries.list on + projects/GCP_PROJECT_ID, filtered to + cloudaudit.googleapis.com/activity, newest first, and it stops after four pages. + A failed lookup omits audit_events and does not fail the scan. +

+

+ An event is kept when its method is on a fixed admin list (for example + v1.compute.instances.insert, storage.buckets.update, + v1.compute.firewalls.patch, SetIamPolicy, + cloudsql.instances.update) and its principal email matches an identity already + in the batch. The resource has to sit on an exposed path: an internet-reachable workload, a + node that workload assumes or can access, a network that workload affects, a public + datastore, or an identity that can access a public datastore. Instance and firewall names + match the self link stored on the node. A bucket event uses + projects/_/buckets/NAME. A service-account key walks up to that identity. A + project SetIamPolicy event is stored on the identity, because the project is + not a node. The same event is stored on the identity and the resource, newest first, at + most five per node. +

+

+ GET /v1/graph/query and om paths run list those events in + audits when the resource node is on the returned path. The console prints the + same lines under the path. Data Access logs, including object reads, are a different log, so + this slice does not collect them. CloudTrail events are collected by + om scan aws. Activity Log events are collected by + om scan azure. +

+ +

Read access

+

+ The scan lists instances, firewalls, load-balancer pieces, buckets, bucket IAM, service + accounts, the project IAM policy, Cloud SQL instances, and Admin Activity log entries. + Listing those entries needs logging.logEntries.list. Logs Viewer + (roles/logging.viewer) includes it. The collector does not call mutating APIs + and does not request Data Access logs. +

diff --git a/src/pages/docs/collectors/index.astro b/src/pages/docs/collectors/index.astro index 8eefb88..52fd109 100644 --- a/src/pages/docs/collectors/index.astro +++ b/src/pages/docs/collectors/index.astro @@ -65,7 +65,7 @@ import DocsLayout from '@/layouts/DocsLayout.astro'; om scan gcp - Compute instances, GCS buckets, service accounts + Compute instances, GCS buckets, service accounts, recent Admin Activity audit logs Application Default Credentials and GCP_PROJECT_ID @@ -107,7 +107,7 @@ import DocsLayout from '@/layouts/DocsLayout.astro'; GCP - The instance has a NAT IP. Firewall rules are not read. + The instance has a NAT IP or sits behind a public load balancer, and a firewall allow is not covered by a higher-priority deny. Kubernetes diff --git a/src/pages/docs/open-source.astro b/src/pages/docs/open-source.astro index 91e7f79..d11775b 100644 --- a/src/pages/docs/open-source.astro +++ b/src/pages/docs/open-source.astro @@ -85,10 +85,11 @@ import DocsLayout from '@/layouts/DocsLayout.astro';

- om scan aws stores CloudTrail management events, and om scan azure - stores Activity Log events, from the last 24 hours on the identity and resource they name, - when that resource is on an exposed path. Path queries return those events with the path. - GCP Cloud Audit Logs are not collected yet. Platform audit logs — operator actions in the + om scan aws stores CloudTrail management events, om scan azure + stores Activity Log events, and om scan gcp stores Admin Activity audit logs, + from the last 24 hours on the identity and resource they name, when that resource is on an + exposed path. Path queries return those events with the path. Data Access logs are not + collected. Platform audit logs — operator actions in the console/API, SSO identity, retention, and auditor export — belong in the commercial offering.

diff --git a/src/pages/docs/schema.astro b/src/pages/docs/schema.astro index 686f9ed..191ef8c 100644 --- a/src/pages/docs/schema.astro +++ b/src/pages/docs/schema.astro @@ -160,7 +160,7 @@ import DocsLayout from '@/layouts/DocsLayout.astro';
  • mfa, unused_access_keys — IAM user pack rules
  • public_ip, imdsv2 — workload exposure and metadata rules
  • packages, image, images — workload inventory that om enrich cve matches. Rules do not read these keys. See CVE enrichment.
  • -
  • audit_events — recent CloudTrail or Activity Log events on an identity or resource. Each item has id, name, time, principal, resource, principal_node_id, resource_node_id, and optional source_ip and read_only. om scan aws and om scan azure write at most five, newest first, and only when the resource is on an exposed path. A plugin may set the same list. Named path queries copy an event into audits when its resource node is on the path. Rules do not match this key.
  • +
  • audit_events — recent CloudTrail, Activity Log, or Admin Activity events on an identity or resource. Each item has id, name, time, principal, resource, principal_node_id, resource_node_id, and optional source_ip and read_only. om scan aws, om scan azure, and om scan gcp write at most five, newest first, and only when the resource is on an exposed path. A plugin may set the same list. Named path queries copy an event into audits when its resource node is on the path. Rules do not match this key.
  • internet_reachable, path_to_datastore, admin_can_access — graph match keys on YAML rules, computed at run time, not stored by collectors