azure-aks-mi-trusts-ksa
match (record)
{
"field": "federatedIdentityCredentials",
"resource_type": "Microsoft.ManagedIdentity/userAssignedIdentities"
}
where
federatedIdentityCredential.issuer matches an AKS cluster oidcIssuerProfile.issuerURL
federatedIdentityCredential.subject starts with system:serviceaccount:
emit
| source type | ManagedIdentity |
|---|---|
| target type | WorkloadIdentity |
| source | <managed identity (user-assigned MI holding the federated credential)> |
| target | <Kubernetes ServiceAccount (WorkloadIdentity) matching the subject> |
Narrative
MI {mi.name} has a federated credential trusting KSA {ksa.name} (issuer: {issuerURL}, subject: {subject}); pods running as {ksa.name} can exchange their projected SA token for an MI access token.
Raw rule rules/explicit/azure-aks.yaml
id: azure-aks-mi-trusts-ksa
emits: TrustsExternalIdentity
applies_to:
- azure
match_record:
resource_type: Microsoft.ManagedIdentity/userAssignedIdentities
field: federatedIdentityCredentials
where:
- federatedIdentityCredential.issuer matches an AKS cluster oidcIssuerProfile.issuerURL
- 'federatedIdentityCredential.subject starts with system:serviceaccount:'
emit:
source_type: ManagedIdentity
target_type: WorkloadIdentity
source: <managed identity (user-assigned MI holding the federated credential)>
target: <Kubernetes ServiceAccount (WorkloadIdentity) matching the subject>
api_source: az identity federated-credential list --identity-name <name> --resource-group <rg>
evidence_field: federatedIdentityCredentials[].issuer + subject
note: "The trust condition (subject pin) is:\n BROAD/UNPINNED if subject is a wildcard or if the attacker\
\ can schedule a pod\n as the matching KSA (they control the namespace / hold pods/create RBAC there).\n\
\ PINNED if subject is a specific system:serviceaccount:<ns>:<sa> the attacker\n cannot run a pod\
\ as \u2014 federation-maps-to-identity stays CONDITIONAL(trust_condition)."
narrative: 'MI {mi.name} has a federated credential trusting KSA {ksa.name} (issuer: {issuerURL}, subject:
{subject}); pods running as {ksa.name} can exchange their projected SA token for an MI access token.'