Kubernetes Secret or ConfigMap Access via Azure Arc Proxy

Detects when secrets or configmaps are accessed, created, modified, or deleted in a Kubernetes cluster by the Azure Arc AAD proxy service account. When operations are routed through the Azure Arc Cluster Connect proxy, the Kubernetes audit log records the acting user as system:serviceaccount:azure-arc:azure-arc-kube-aad-proxy-sa with the actual caller identity in the impersonatedUser field. This pattern indicates that someone is accessing the cluster through the Azure ARM API rather than directly via kubectl against the API server. While legitimate for Arc-managed workflows, adversaries with stolen service principal credentials can abuse Arc Cluster Connect to read, exfiltrate, or modify secrets and configmaps while appearing as the Arc proxy service account in K8s audit logs. This rule uses a 5-day new-terms history window keyed on the impersonated identity and alerts the first time that Azure AD principal performs this activity.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/03/10"
  3integration = ["kubernetes"]
  4maturity = "production"
  5updated_date = "2026/09/18"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Detects when secrets or configmaps are accessed, created, modified, or deleted in a Kubernetes cluster by the Azure Arc
 11AAD proxy service account. When operations are routed through the Azure Arc Cluster Connect proxy, the Kubernetes audit
 12log records the acting user as system:serviceaccount:azure-arc:azure-arc-kube-aad-proxy-sa with the actual caller
 13identity in the impersonatedUser field. This pattern indicates that someone is accessing the cluster through the Azure
 14ARM API rather than directly via kubectl against the API server. While legitimate for Arc-managed workflows, adversaries
 15with stolen service principal credentials can abuse Arc Cluster Connect to read, exfiltrate, or modify secrets and
 16configmaps while appearing as the Arc proxy service account in K8s audit logs. This rule uses a 5-day new-terms history
 17window keyed on the impersonated identity and alerts the first time that Azure AD principal performs this activity.
 18"""
 19false_positives = [
 20    """
 21    Azure Arc system components may create or update secrets and configmaps in the azure-arc and azure-arc-release
 22    namespaces during normal cluster management. Filter by namespace to exclude these.
 23    """,
 24    """
 25    Helm operations managed through Arc may create release secrets (prefixed with sh.helm.release.v1). These are normal
 26    Arc lifecycle operations.
 27    """,
 28]
 29from = "now-5d"
 30interval = "9m"
 31language = "esql"
 32license = "Elastic License v2"
 33name = "Kubernetes Secret or ConfigMap Access via Azure Arc Proxy"
 34note = """## Triage and analysis
 35
 36### Investigating Kubernetes Secret or ConfigMap Access via Azure Arc Proxy
 37
 38When Kubernetes operations are performed through Azure Arc Cluster Connect, the K8s audit log shows the Arc AAD proxy
 39service account as the authenticated user, with the actual Azure AD identity in the `impersonatedUser` field. This
 40rule detects non-system secret and configmap access — including reads, writes, and deletions — routed through this
 41proxy path. Read operations (`get`, `list`) are particularly important to detect as they represent the most common
 42adversary action: exfiltrating secrets without leaving obvious modification traces.
 43
 44This rule uses a new terms approach keyed on `kubernetes.audit.impersonatedUser.username`, so it fires the first time a
 45given impersonated identity performs this activity within the 5-day history window.
 46
 47### Possible investigation steps
 48
 49- Check the `kubernetes.audit.impersonatedUser.username` field — this contains the Azure AD object ID of the actual
 50  caller. Cross-reference with Azure AD to identify the service principal or user.
 51- Review the `kubernetes.audit.impersonatedUser.extra.oid` field for the Azure AD object ID.
 52- Examine the namespace — operations in `default` or application namespaces are more suspicious than `azure-arc` or
 53  `kube-system`.
 54- Check the `kubernetes.audit.objectRef.name` — look for suspicious secret/configmap names that don't match known
 55  application resources.
 56- Correlate with Azure Activity Logs for the same time window to find the `LISTCLUSTERUSERCREDENTIAL` operation that
 57  initiated the Arc proxy session.
 58- Review Azure Sign-In Logs for the impersonated identity's authentication source IP and geolocation.
 59
 60### Response and remediation
 61
 62- If the impersonated identity is not recognized, revoke its Azure AD credentials immediately.
 63- Remove the ClusterRoleBinding or RoleBinding that grants the identity access to secrets/configmaps.
 64- Rotate any Kubernetes secrets that may have been read or exfiltrated.
 65- Review the Arc connection and consider disconnecting it if compromised.
 66"""
 67references = [
 68    "https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/cluster-connect",
 69    "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
 70    "https://www.ibm.com/think/x-force/identifying-abusing-azure-arc-for-hybrid-escalation-persistence",
 71    "https://cloud.google.com/blog/topics/threat-intelligence/escalating-privileges-azure-kubernetes-services",
 72    "https://www.wiz.io/blog/lateral-movement-risks-in-the-cloud-and-how-to-prevent-them-part-3-from-compromis",
 73]
 74risk_score = 47
 75rule_id = "220d92c6-479d-4a49-9cc0-3a29756dad0c"
 76severity = "medium"
 77tags = [
 78    "Data Source: Kubernetes",
 79    "Data Source: Kubernetes API Server Audit Logs",
 80    "Domain: Kubernetes",
 81    "Platform: Kubernetes",
 82    "Domain: Cloud",
 83    "Use Case: Threat Detection",
 84    "Tactic: Credential Access",
 85    "Tactic: Collection",
 86    "Resources: Investigation Guide",
 87    "Noise: Low",
 88    "Performance: Fast",
 89    "Rule Type: ES|QL",
 90    "Domain: Containers",
 91]
 92timestamp_override = "event.ingested"
 93type = "esql"
 94
 95query = '''
 96FROM logs-kubernetes.audit_logs-* metadata _id, _version, _index
 97| WHERE STARTS_WITH(kubernetes.audit.user.username, "system:serviceaccount:azure-arc:")
 98    AND kubernetes.audit.objectRef.resource IN ("secrets", "configmaps")
 99    AND kubernetes.audit.verb IN ("get", "list", "create", "update", "patch", "delete")
100    AND kubernetes.audit.objectRef.namespace NOT IN ("azure-arc", "azure-arc-release", "kube-system")
101    AND NOT STARTS_WITH(kubernetes.audit.objectRef.name, "sh.helm.release.v1")
102
103| STATS
104    Esql.verb_values = VALUES(kubernetes.audit.verb),
105    Esql.resource_type_values = VALUES(kubernetes.audit.objectRef.resource),
106    Esql.resource_name_values = VALUES(kubernetes.audit.objectRef.name),
107    Esql.namespace_values = VALUES(kubernetes.audit.objectRef.namespace),
108    Esql.data_stream_namespace_values = VALUES(data_stream.namespace),
109    Esql.acting_user_values = VALUES(kubernetes.audit.user.username),
110    Esql.user_agent_values = VALUES(kubernetes.audit.userAgent),
111    Esql.source_ips_values = VALUES(kubernetes.audit.sourceIPs),
112    Esql.response_code_values = VALUES(kubernetes.audit.responseStatus.code),
113    Esql.timestamp_first_seen = MIN(@timestamp),
114    Esql.timestamp_last_seen = MAX(@timestamp),
115    Esql.event_count = COUNT(*)
116    BY kubernetes.audit.impersonatedUser.username
117
118| WHERE Esql.timestamp_first_seen >= NOW() - 9 minutes
119| KEEP kubernetes.audit.impersonatedUser.username, Esql.*
120'''
121
122
123[[rule.threat]]
124framework = "MITRE ATT&CK"
125
126[[rule.threat.technique]]
127id = "T1552"
128name = "Unsecured Credentials"
129reference = "https://attack.mitre.org/techniques/T1552/"
130
131[[rule.threat.technique.subtechnique]]
132id = "T1552.007"
133name = "Container API"
134reference = "https://attack.mitre.org/techniques/T1552/007/"
135
136[rule.threat.tactic]
137id = "TA0006"
138name = "Credential Access"
139reference = "https://attack.mitre.org/tactics/TA0006/"
140
141[[rule.threat]]
142framework = "MITRE ATT&CK"
143
144[[rule.threat.technique]]
145id = "T1213"
146name = "Data from Information Repositories"
147reference = "https://attack.mitre.org/techniques/T1213/"
148
149[[rule.threat.technique]]
150id = "T1530"
151name = "Data from Cloud Storage"
152reference = "https://attack.mitre.org/techniques/T1530/"
153
154[rule.threat.tactic]
155id = "TA0009"
156name = "Collection"
157reference = "https://attack.mitre.org/tactics/TA0009/"
158
159[[rule.threat]]
160framework = "MITRE ATT&CK"
161
162[[rule.threat.technique]]
163id = "T1565"
164name = "Data Manipulation"
165reference = "https://attack.mitre.org/techniques/T1565/"
166
167[[rule.threat.technique.subtechnique]]
168id = "T1565.001"
169name = "Stored Data Manipulation"
170reference = "https://attack.mitre.org/techniques/T1565/001/"
171
172[rule.threat.tactic]
173id = "TA0040"
174name = "Impact"
175reference = "https://attack.mitre.org/tactics/TA0040/"

Triage and analysis

Investigating Kubernetes Secret or ConfigMap Access via Azure Arc Proxy

When Kubernetes operations are performed through Azure Arc Cluster Connect, the K8s audit log shows the Arc AAD proxy service account as the authenticated user, with the actual Azure AD identity in the impersonatedUser field. This rule detects non-system secret and configmap access — including reads, writes, and deletions — routed through this proxy path. Read operations (get, list) are particularly important to detect as they represent the most common adversary action: exfiltrating secrets without leaving obvious modification traces.

This rule uses a new terms approach keyed on kubernetes.audit.impersonatedUser.username, so it fires the first time a given impersonated identity performs this activity within the 5-day history window.

Possible investigation steps

  • Check the kubernetes.audit.impersonatedUser.username field — this contains the Azure AD object ID of the actual caller. Cross-reference with Azure AD to identify the service principal or user.
  • Review the kubernetes.audit.impersonatedUser.extra.oid field for the Azure AD object ID.
  • Examine the namespace — operations in default or application namespaces are more suspicious than azure-arc or kube-system.
  • Check the kubernetes.audit.objectRef.name — look for suspicious secret/configmap names that don't match known application resources.
  • Correlate with Azure Activity Logs for the same time window to find the LISTCLUSTERUSERCREDENTIAL operation that initiated the Arc proxy session.
  • Review Azure Sign-In Logs for the impersonated identity's authentication source IP and geolocation.

Response and remediation

  • If the impersonated identity is not recognized, revoke its Azure AD credentials immediately.
  • Remove the ClusterRoleBinding or RoleBinding that grants the identity access to secrets/configmaps.
  • Rotate any Kubernetes secrets that may have been read or exfiltrated.
  • Review the Arc connection and consider disconnecting it if compromised.

References

Related rules

to-top