# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # E2E Test: Managed Identity/FIC_LimitToAzureKubernetesIssuer # Real Azure Policy: "Managed Identity Federated Credentials from Azure # Kubernetes should be from trusted sources" # Source: regolator/policyDefinitions/Managed Identity/FIC_LimitToAzureKubernetesIssuer.json # # Features exercised: # - Value count (count over parameter arrays) # - Complex nested if/split/length value expressions to parse issuer URL # - Double negation: not { anyOf [...] } # - Child resource type (sub-resource) # - `like` operator with wildcard pattern aliases: test_aliases.json policy_definition: | { "properties": { "displayName": "[Preview]: Managed Identity Federated Credentials from Azure Kubernetes should be from trusted sources", "policyType": "BuiltIn", "mode": "All", "parameters": { "allowedTenants": { "type": "Array", "metadata": { "displayName": "Allowed tenants", "description": "The list of allowed Azure AD tenant ID's of AKS OIDC issuers. Empty to allow all tenants." } }, "allowedLocations": { "type": "Array", "defaultValue": [], "metadata": { "displayName": "Allowed locations", "description": "The list of allowed locations for AKS OIDC issuers. Empty to allow any location." } }, "allowedClusterExceptions": { "type": "Array", "defaultValue": [], "metadata": { "displayName": "Allowed Exception Clusters", "description": "The list of specific cluster ids that will be exceptions to the location and tenant rules." } }, "effect": { "type": "String", "defaultValue": "Audit", "allowedValues": ["Audit", "Disabled", "Deny"] } }, "policyRule": { "if": { "allOf": [ { "field": "type", "equals": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" }, { "allOf": [ { "value": "[if(greaterOrEquals(length(split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')),3),split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')[2],'')]", "like": "*.oic.prod-aks.azure.com" }, { "not": { "anyOf": [ { "allOf": [ { "anyOf": [ { "count": { "value": "[parameters('allowedLocations')]" }, "equals": 0 }, { "value": "[if(greaterOrEquals(length(split(if(greaterOrEquals(length(split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')),3),split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')[2],''), '.')),1),split(if(greaterOrEquals(length(split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')),3),split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')[2],''), '.')[0],'')]", "in": "[parameters('allowedLocations')]" } ] }, { "anyOf": [ { "count": { "value": "[parameters('allowedTenants')]" }, "equals": 0 }, { "value": "[if(greaterOrEquals(length(split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')),4),split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')[3],'')]", "in": "[parameters('allowedTenants')]" } ] } ] }, { "value": "[if(greaterOrEquals(length(split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')),5),split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer'),'/')[4],'')]", "in": "[parameters('allowedClusterExceptions')]" } ] } } ] } ] }, "then": { "effect": "[parameters('effect')]" } } } } cases: # ========================================================================= # Audit — untrusted AKS issuer (wrong tenant AND wrong location) # ========================================================================= - note: audit_untrusted_tenant_and_location resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "aks-fic" properties: issuer: "https://eastus.oic.prod-aks.azure.com/bad-tenant-id/some-cluster-id" subject: "system:serviceaccount:default:workload-identity-sa" parameters: allowedTenants: ["good-tenant-id"] allowedLocations: ["westus"] allowedClusterExceptions: [] want_effect: "Audit" # ========================================================================= # Audit — correct location but wrong tenant # ========================================================================= - note: audit_wrong_tenant_correct_location resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "aks-fic" properties: issuer: "https://eastus.oic.prod-aks.azure.com/bad-tenant-id/some-cluster-id" subject: "system:serviceaccount:default:workload-identity-sa" parameters: allowedTenants: ["good-tenant-id"] allowedLocations: ["eastus"] allowedClusterExceptions: [] want_effect: "Audit" # ========================================================================= # Pass — allowed tenant and allowed location # ========================================================================= - note: pass_allowed_tenant_and_location resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "aks-fic" properties: issuer: "https://eastus.oic.prod-aks.azure.com/good-tenant-id/some-cluster-id" subject: "system:serviceaccount:default:workload-identity-sa" parameters: allowedTenants: ["good-tenant-id", "other-tenant-id"] allowedLocations: ["eastus", "westus"] allowedClusterExceptions: [] want_undefined: true # ========================================================================= # Pass — allowed tenant, empty allowedLocations (any location allowed) # ========================================================================= - note: pass_allowed_tenant_any_location resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "aks-fic" properties: issuer: "https://westeurope.oic.prod-aks.azure.com/good-tenant-id/some-cluster-id" subject: "system:serviceaccount:default:workload-identity-sa" parameters: allowedTenants: ["good-tenant-id"] allowedLocations: [] allowedClusterExceptions: [] want_undefined: true # ========================================================================= # Pass — empty allowedTenants and empty allowedLocations (allow all) # ========================================================================= - note: pass_empty_tenants_and_locations_allows_all resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "aks-fic" properties: issuer: "https://australiaeast.oic.prod-aks.azure.com/any-tenant/any-cluster" subject: "system:serviceaccount:kube-system:my-sa" parameters: allowedTenants: [] allowedLocations: [] allowedClusterExceptions: [] want_undefined: true # ========================================================================= # Pass — cluster ID is in the exceptions list (bypasses tenant/location) # ========================================================================= - note: pass_cluster_in_exceptions resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "aks-fic" properties: issuer: "https://eastus.oic.prod-aks.azure.com/untrusted-tenant/special-cluster-id" subject: "system:serviceaccount:default:workload-identity-sa" parameters: allowedTenants: ["other-tenant"] allowedLocations: ["westus"] allowedClusterExceptions: ["special-cluster-id"] want_undefined: true # ========================================================================= # Pass — non-AKS issuer (GitHub Actions OIDC) # ========================================================================= - note: pass_non_aks_issuer resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "github-fic" properties: issuer: "https://token.actions.githubusercontent.com" subject: "repo:myorg/myrepo:ref:refs/heads/main" parameters: allowedTenants: ["some-tenant"] want_undefined: true # ========================================================================= # Skip — wrong resource type entirely # ========================================================================= - note: skip_wrong_resource_type resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities" name: "my-identity" properties: {} want_undefined: true