Azure AKS Certificate Signing Request Created or Approved
Detects an identity creating a client-authentication CertificateSigningRequest (signer kubernetes.io/kube-apiserver-client) or approving a CSR on AKS (Azure Kubernetes Service), excluding node bootstrap and platform controllers. Adversaries submit and self-approve a CSR against the kube-apiserver-client signer to mint a long-lived client certificate for an arbitrary subject (for example a Common Name in system:masters), giving durable authenticated access that survives token revocation. Coverage includes workload service accounts (system:serviceaccount:*), so a compromised in-cluster token forging a certificate is not excluded.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/07/09"
3integration = ["azure"]
4maturity = "production"
5updated_date = "2026/07/09"
6
7[rule]
8author = ["Elastic"]
9description = """
10Detects an identity creating a client-authentication CertificateSigningRequest (signer
11kubernetes.io/kube-apiserver-client) or approving a CSR on AKS (Azure Kubernetes Service), excluding node bootstrap and
12platform controllers. Adversaries submit and self-approve a CSR against the kube-apiserver-client signer to mint a
13long-lived client certificate for an arbitrary subject (for example a Common Name in system:masters), giving durable
14authenticated access that survives token revocation. Coverage includes workload service accounts
15(system:serviceaccount:*), so a compromised in-cluster token forging a certificate is not excluded.
16"""
17false_positives = [
18 """
19 Node bootstrap, cert-manager, and platform controllers legitimately create and approve CSRs. Validate the requesting
20 identity and the certificate subject, and add exclusions for verified automation.
21 """,
22]
23from = "now-9m"
24index = ["logs-azure.platformlogs-*"]
25language = "kuery"
26license = "Elastic License v2"
27name = "Azure AKS Certificate Signing Request Created or Approved"
28note = """## Triage and analysis
29
30### Investigating Azure AKS Certificate Signing Request Created or Approved
31
32AKS kube-audit events are carried under the flattened `azure.platformlogs.properties.log.*` subtree and share the ARM
33operation `event.action: Microsoft.ContainerService/managedClusters/diagnosticLogs/Read`. A CSR created against the
34`kubernetes.io/kube-apiserver-client` signer lets the requester choose the certificate's subject (Common Name and
35organization/groups); once approved it mints a client certificate for an arbitrary identity that yields access not tied
36to a token. The default `CertificateSubjectRestriction` admission controller blocks requests for the `system:masters`
37group, so attackers commonly request a Common Name matching an existing privileged user (or another privileged group)
38instead, making the requested subject the key thing to decode. Node and kubelet certificates use the
39`kube-apiserver-client-kubelet` and `kubelet-serving` signers (whose subject is constrained to the node) and are out of
40scope; cert-manager and application CSRs use their own signers.
41
42### Possible investigation steps
43
44- Identify the requesting identity in `azure.platformlogs.properties.log.user.username` (and its groups in
45 `azure.platformlogs.properties.log.user.groups`) and whether it should submit or approve CSRs. A workload service
46 account (`system:serviceaccount:<ns>:<sa>`) or `masterclient` (the local cluster-admin cert) is the higher-concern
47 case.
48- Confirm the signer in `azure.platformlogs.properties.log.requestObject.spec.signerName` and decode the base64 CSR in
49 `azure.platformlogs.properties.log.requestObject.spec.request` to read the requested Common Name and organization
50 (groups); a subject in `system:masters` or another privileged group is the escalation.
51- Determine whether the same or a related identity approved the CSR (`verb:update`/`patch` on the `approval`
52 subresource), which indicates self-approval, and inspect `azure.platformlogs.properties.log.userAgent`.
53- Evaluate the source in `azure.platformlogs.properties.log.sourceIPs` and pivot on it for follow-on privileged API
54 activity using the newly issued certificate.
55
56### False positive analysis
57
58- Node bootstrap (`kube-apiserver-client-kubelet` signer), kubelet-serving CSRs, and cert-manager/application CSRs
59 (custom signers) are out of scope by design; the kube-controller-manager `certificate-controller` and the AKS
60 `aksService` approver are excluded by identity.
61- Manual CSR approval by an administrator, or an operator that legitimately mints client certificates, may surface;
62 baseline those identities and exclude the specific validated account rather than re-broadening to all `system:*`,
63 which would blind the rule to compromised workload service accounts.
64
65### Response and remediation
66
67- If unauthorized, deny or delete the CSR, revoke the issued certificate, and rotate the cluster CA if a privileged
68 certificate was minted.
69- Review the RBAC that allowed CSR creation and approval, and audit actions taken with the certificate.
70- Collect kube-audit and identity artifacts per incident response procedures.
71"""
72references = [
73 "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
74 "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
75 "https://github.com/inguardians/peirates",
76 "https://raesene.github.io/blog/2022/12/21/Kubernetes-persistence-with-Tocan-and-Teisteanas/",
77 "https://cloud.google.com/blog/topics/threat-intelligence/escalating-privileges-azure-kubernetes-services",
78 "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
79]
80risk_score = 47
81rule_id = "3f6c636a-1ca5-410c-bdad-f8b59a1f2b49"
82setup = """The Azure Fleet integration collecting AKS diagnostic logs forwarded through Event Hub into the `azure.platformlogs`
83data stream is required for this rule. Enable either the `kube-audit` or the `kube-audit-admin` log category (Microsoft
84recommends `kube-audit-admin` alone to reduce volume, as it only drops read-only get/list events). CSR create and
85approval are mutating operations recorded in both categories with the same `auditID`, so clusters that enable both
86categories may generate two alerts per event.
87"""
88severity = "medium"
89tags = [
90 "Domain: Cloud",
91 "Domain: Kubernetes",
92 "Data Source: Azure",
93 "Data Source: Azure Platform Logs",
94 "Data Source: Kubernetes",
95 "Use Case: Threat Detection",
96 "Tactic: Credential Access",
97 "Resources: Investigation Guide",
98]
99timestamp_override = "event.ingested"
100type = "query"
101
102query = '''
103data_stream.dataset:azure.platformlogs and
104 event.action:"Microsoft.ContainerService/managedClusters/diagnosticLogs/Read" and
105 azure.platformlogs.category:("kube-audit" or "kube-audit-admin") and
106 azure.platformlogs.properties.log.stage:"ResponseComplete" and
107 azure.platformlogs.properties.log.objectRef.resource:"certificatesigningrequests" and
108 azure.platformlogs.properties.log.responseStatus.code: "200" and
109 azure.platformlogs.properties.log.requestObject.status.conditions.type: "Approved" and
110 (
111 (
112 azure.platformlogs.properties.log.verb:"create" and
113 azure.platformlogs.properties.log.requestObject.spec.signerName:"kubernetes.io/kube-apiserver-client"
114 ) or (
115 azure.platformlogs.properties.log.verb:("update" or "patch") and
116 azure.platformlogs.properties.log.objectRef.subresource:"approval"
117 )
118 ) and
119 not azure.platformlogs.properties.log.user.username:(
120 system\:node\:* or system\:bootstrap\:* or "aksService" or "hcpService" or
121 "readinessChecker" or system\:serviceaccount\:kube-system\:*
122 )
123'''
124
125
126[[rule.threat]]
127framework = "MITRE ATT&CK"
128[[rule.threat.technique]]
129id = "T1649"
130name = "Steal or Forge Authentication Certificates"
131reference = "https://attack.mitre.org/techniques/T1649/"
132
133
134[rule.threat.tactic]
135id = "TA0006"
136name = "Credential Access"
137reference = "https://attack.mitre.org/tactics/TA0006/"
138
139[rule.investigation_fields]
140field_names = [
141 "@timestamp",
142 "event.action",
143 "azure.platformlogs.category",
144 "azure.platformlogs.properties.log.verb",
145 "azure.platformlogs.properties.log.user.username",
146 "azure.platformlogs.properties.log.user.groups",
147 "azure.platformlogs.properties.log.userAgent",
148 "azure.platformlogs.properties.log.sourceIPs",
149 "azure.platformlogs.properties.log.objectRef.resource",
150 "azure.platformlogs.properties.log.objectRef.name",
151 "azure.platformlogs.properties.log.objectRef.subresource",
152 "azure.platformlogs.properties.log.requestObject.spec.signerName",
153 "azure.platformlogs.properties.log.requestObject.spec.request",
154 "azure.platformlogs.properties.log.responseStatus.code",
155]
Triage and analysis
Investigating Azure AKS Certificate Signing Request Created or Approved
AKS kube-audit events are carried under the flattened azure.platformlogs.properties.log.* subtree and share the ARM
operation event.action: Microsoft.ContainerService/managedClusters/diagnosticLogs/Read. A CSR created against the
kubernetes.io/kube-apiserver-client signer lets the requester choose the certificate's subject (Common Name and
organization/groups); once approved it mints a client certificate for an arbitrary identity that yields access not tied
to a token. The default CertificateSubjectRestriction admission controller blocks requests for the system:masters
group, so attackers commonly request a Common Name matching an existing privileged user (or another privileged group)
instead, making the requested subject the key thing to decode. Node and kubelet certificates use the
kube-apiserver-client-kubelet and kubelet-serving signers (whose subject is constrained to the node) and are out of
scope; cert-manager and application CSRs use their own signers.
Possible investigation steps
- Identify the requesting identity in
azure.platformlogs.properties.log.user.username(and its groups inazure.platformlogs.properties.log.user.groups) and whether it should submit or approve CSRs. A workload service account (system:serviceaccount:<ns>:<sa>) ormasterclient(the local cluster-admin cert) is the higher-concern case. - Confirm the signer in
azure.platformlogs.properties.log.requestObject.spec.signerNameand decode the base64 CSR inazure.platformlogs.properties.log.requestObject.spec.requestto read the requested Common Name and organization (groups); a subject insystem:mastersor another privileged group is the escalation. - Determine whether the same or a related identity approved the CSR (
verb:update/patchon theapprovalsubresource), which indicates self-approval, and inspectazure.platformlogs.properties.log.userAgent. - Evaluate the source in
azure.platformlogs.properties.log.sourceIPsand pivot on it for follow-on privileged API activity using the newly issued certificate.
False positive analysis
- Node bootstrap (
kube-apiserver-client-kubeletsigner), kubelet-serving CSRs, and cert-manager/application CSRs (custom signers) are out of scope by design; the kube-controller-managercertificate-controllerand the AKSaksServiceapprover are excluded by identity. - Manual CSR approval by an administrator, or an operator that legitimately mints client certificates, may surface;
baseline those identities and exclude the specific validated account rather than re-broadening to all
system:*, which would blind the rule to compromised workload service accounts.
Response and remediation
- If unauthorized, deny or delete the CSR, revoke the issued certificate, and rotate the cluster CA if a privileged certificate was minted.
- Review the RBAC that allowed CSR creation and approval, and audit actions taken with the certificate.
- Collect kube-audit and identity artifacts per incident response procedures.
References
Related rules
- Azure AKS CoreDNS or Kube-DNS Configuration Modified
- Azure AKS Secret get or list with Suspicious User Agent
- Azure AKS Kubernetes Events Deleted
- Azure AKS Potential API Enumeration by User
- Azure AKS Suspicious Self-Subject Review by Service Account or Node Identity