GKE Multi-Resource Discovery

Last updated 2 days ago on 2026-07-31
Created 12 days ago on 2026-07-21

About

Adversaries who land credentials in a GKE cluster—or abuse an over-privileged token, often map the environment before exfiltration or privilege escalation. A practical first pass is to learn where workloads run, how the cluster is partitioned, and what RBAC exists at namespace vs cluster scope. Rapid get/list traffic across many distinct API resource kinds that answer those questions (namespaces, workloads, roles, cluster-wide roles) is a common setup and orientation pattern for both interactive attackers and automated recon scripts. This rule highlights that cross-resource burst from a single client fingerprint within a one-minute bucket when both cluster-layout and RBAC resource kinds are touched, so analysts can separate routine automation from potential discovery ahead of follow-on actions.
Tags
Domain: CloudDomain: KubernetesData Source: GCPData Source: Google Cloud PlatformUse Case: Threat DetectionTactic: DiscoveryLanguage: esql
Severity
medium
Risk Score
47
MITRE ATT&CK™

Discovery (TA0007)(external, opens in a new tab or window)

False Positive Examples
Platform operators, installers, or runbooks that reconcile RBAC and workload state may span these resource types in a short window; tune by identity, source IP, or user agent when documented. GitOps controllers and cluster scanners can still match if not covered by built-in exclusions; baseline approved service accounts after review.
License
Elastic License v2(external, opens in a new tab or window)

Definition

Integration Pack
Prebuilt Security Detection Rules
Related Integrations

gcp(external, opens in a new tab or window)

Query
text code block:
from logs-gcp.audit-* metadata _id, _index, _version | where data_stream.dataset == "gcp.audit" and service.name == "k8s.io" and event.action in ( "io.k8s.core.v1.namespaces.get", "io.k8s.core.v1.namespaces.list", "io.k8s.core.v1.nodes.get", "io.k8s.core.v1.nodes.list", "io.k8s.core.v1.pods.get", "io.k8s.core.v1.pods.list", "io.k8s.core.v1.configmaps.get", "io.k8s.core.v1.configmaps.list", "io.k8s.core.v1.serviceaccounts.get", "io.k8s.core.v1.serviceaccounts.list", "io.k8s.authorization.rbac.v1.roles.get", "io.k8s.authorization.rbac.v1.roles.list", "io.k8s.authorization.rbac.v1.rolebindings.get", "io.k8s.authorization.rbac.v1.rolebindings.list", "io.k8s.authorization.rbac.v1.clusterroles.get", "io.k8s.authorization.rbac.v1.clusterroles.list", "io.k8s.authorization.rbac.v1.clusterrolebindings.get", "io.k8s.authorization.rbac.v1.clusterrolebindings.list" ) and source.ip is not null and client.user.email is not null and not to_string(source.ip) in ("127.0.0.1", "::1") and not client.user.email like "system:kube-*" and not client.user.email like "system:gke-*" and not client.user.email like "system:node:*" and not client.user.email like "system:serviceaccount:kube-system:*" and not client.user.email like "system:serviceaccount:gke-managed*" and not client.user.email in ( "system:apiserver", "system:addon-manager", "system:kubestore-collector", "gcp:kube-bootstrap", "system:serviceaccount:security:trivy-operator" ) and not client.user.email like "system:serviceaccount:flux-system:*" and not client.user.email like "system:serviceaccount:argocd:*" and not client.user.email like "system:serviceaccount:argocd-system:*" and not client.user.email like "system:serviceaccount:cattle-turtles-system:*" and not client.user.email like "system:serviceaccount:*:palette-manager" | eval Esql.time_interval = date_trunc(1 minute, @timestamp), Esql.resource_kind = case( event.action in ("io.k8s.core.v1.namespaces.get", "io.k8s.core.v1.namespaces.list"), "namespaces", event.action in ("io.k8s.core.v1.nodes.get", "io.k8s.core.v1.nodes.list"), "nodes", event.action in ("io.k8s.core.v1.pods.get", "io.k8s.core.v1.pods.list"), "pods", event.action in ("io.k8s.core.v1.configmaps.get", "io.k8s.core.v1.configmaps.list"), "configmaps", event.action in ("io.k8s.core.v1.serviceaccounts.get", "io.k8s.core.v1.serviceaccounts.list"), "serviceaccounts", event.action in ("io.k8s.authorization.rbac.v1.roles.get", "io.k8s.authorization.rbac.v1.roles.list"), "roles", event.action in ("io.k8s.authorization.rbac.v1.rolebindings.get", "io.k8s.authorization.rbac.v1.rolebindings.list"), "rolebindings", event.action in ("io.k8s.authorization.rbac.v1.clusterroles.get", "io.k8s.authorization.rbac.v1.clusterroles.list"), "clusterroles", event.action in ("io.k8s.authorization.rbac.v1.clusterrolebindings.get", "io.k8s.authorization.rbac.v1.clusterrolebindings.list"), "clusterrolebindings", null ), Esql.is_rbac = case( event.action in ( "io.k8s.authorization.rbac.v1.roles.get", "io.k8s.authorization.rbac.v1.roles.list", "io.k8s.authorization.rbac.v1.rolebindings.get", "io.k8s.authorization.rbac.v1.rolebindings.list", "io.k8s.authorization.rbac.v1.clusterroles.get", "io.k8s.authorization.rbac.v1.clusterroles.list", "io.k8s.authorization.rbac.v1.clusterrolebindings.get", "io.k8s.authorization.rbac.v1.clusterrolebindings.list" ), 1, 0 ), Esql.is_layout = case( event.action in ( "io.k8s.core.v1.namespaces.get", "io.k8s.core.v1.namespaces.list", "io.k8s.core.v1.pods.get", "io.k8s.core.v1.pods.list", "io.k8s.core.v1.nodes.get", "io.k8s.core.v1.nodes.list" ), 1, 0 ) | stats Esql.unique_resources = count_distinct(Esql.resource_kind), Esql.rbac_event_count = sum(Esql.is_rbac), Esql.layout_event_count = sum(Esql.is_layout), Esql.enumerated_resources = values(Esql.resource_kind), Esql.enumerated_namespaces = values(orchestrator.namespace), Esql.enumerated_resource_names = values(gcp.audit.resource_name), Esql.event_outcome_values = values(event.outcome) by client.user.email, source.ip, user_agent.original, Esql.time_interval | where Esql.unique_resources >= 5 and Esql.rbac_event_count > 0 and Esql.layout_event_count > 0 | keep Esql.*, client.user.email, source.ip, user_agent.original

Install detection rules in Elastic Security

Detect GKE Multi-Resource Discovery in the Elastic Security detection engine by installing this rule into your Elastic Stack.

To setup this rule, check out the installation guide for Prebuilt Security Detection Rules(external, opens in a new tab or window).