GKE API Request Failure Burst by User
editGKE API Request Failure Burst by User
editDetects bursts of failed GKE API requests from a single user identity within a five-minute window. Repeated authorization failures across multiple actions can indicate credential stuffing, RBAC probing, or reconnaissance with stolen tokens.
Rule type: esql
Rule indices: None
Severity: medium
Risk score: 47
Runs every: 5m
Searches indices from: now-11m (Date Math format, see also Additional look-back time)
Maximum alerts per execution: 100
References:
Tags:
- Domain: Cloud
- Domain: Kubernetes
- Data Source: GCP
- Data Source: Google Cloud Platform
- Use Case: Threat Detection
- Tactic: Discovery
- Resources: Investigation Guide
Version: 1
Rule authors:
- Elastic
Rule license: Elastic License v2
Investigation guide
editTriage and analysis
Investigating GKE API Request Failure Burst by User
The rule aggregates failed Kubernetes API calls per user.email, source IP, and user agent in five-minute buckets and
alerts when failures reach ten or more.
Investigation steps
-
Review
Esql.actionsandEsql.resourcesfor targeted API operations. - Validate whether the identity should exist and whether the source IP is expected.
- Hunt for later successful calls indicating privilege escalation.
False positives
- Misconfigured automation or CI jobs with stale credentials may generate bursts; exclude known service accounts.
Setup
editThe GCP Fleet integration with GKE audit logs enabled is required to be compatible with this rule.
Rule query
editfrom logs-gcp.audit-* metadata _id, _index, _version
| eval Esql.time_interval = date_trunc(5 minutes, @timestamp)
| where data_stream.dataset == "gcp.audit"
and service.name == "k8s.io"
and event.outcome == "failure"
and event.type != "allowed"
and user.email is not null
and not to_string(user.email) rlike "(system:serviceaccount:|system:gke-spiffe-controller|system:kube-scheduler|system:node:).*"
| stats
Esql.unique_actions = count_distinct(event.action),
Esql.failures_count = count(*),
Esql.actions = values(event.action),
Esql.resources = values(orchestrator.resource.name)
by user.email, source.ip, user_agent.original, data_stream.namespace, Esql.time_interval
| where Esql.failures_count >= 10
| keep Esql.*, user.email, source.ip, user_agent.original, data_stream.namespace
Framework: MITRE ATT&CKTM
-
Tactic:
- Name: Discovery
- ID: TA0007
- Reference URL: https://attack.mitre.org/tactics/TA0007/
-
Technique:
- Name: Container and Resource Discovery
- ID: T1613
- Reference URL: https://attack.mitre.org/techniques/T1613/