# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # E2E Test: Managed Identity/FIC_LimitToGitHubIssuer # Real Azure Policy: "Managed Identity Federated Credentials from GitHub # should be from trusted repository owners" # Source: regolator/policyDefinitions/Managed Identity/FIC_LimitToGitHubIssuer.json # # Features exercised: # - Value count (count over parameter array) # - Complex nested if/split/length value expressions to parse subject field # - Double negation: not { anyOf [...] } # - Child resource type (sub-resource) aliases: test_aliases.json policy_definition: | { "properties": { "displayName": "[Preview]: Managed Identity Federated Credentials from GitHub should be from trusted repository owners", "policyType": "BuiltIn", "mode": "All", "parameters": { "allowedRepoOwners": { "type": "Array", "metadata": { "displayName": "Allowed Repo Owners" } }, "allowedRepoExceptions": { "type": "Array", "defaultValue": [], "metadata": { "displayName": "Allowed Repo Exceptions" } }, "effect": { "type": "String", "defaultValue": "Audit", "allowedValues": ["Audit", "Disabled", "Deny"] } }, "policyRule": { "if": { "allOf": [ { "field": "type", "equals": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" }, { "allOf": [ { "field": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/issuer", "equals": "https://token.actions.githubusercontent.com" }, { "not": { "anyOf": [ { "allOf": [ { "anyOf": [ { "count": { "value": "[parameters('allowedRepoOwners')]" }, "equals": 0 }, { "value": "[if(greaterOrEquals(length(split(if(greaterOrEquals(length(split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/subject'),':')),2),split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/subject'),':')[1],''), '/')),2),split(if(greaterOrEquals(length(split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/subject'),':')),2),split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/subject'),':')[1],''), '/')[0],'')]", "in": "[parameters('allowedRepoOwners')]" } ] } ] }, { "value": "[if(greaterOrEquals(length(split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/subject'),':')),2),split(field('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/subject'),':')[1],'')]", "in": "[parameters('allowedRepoExceptions')]" } ] } } ] } ] }, "then": { "effect": "[parameters('effect')]" } } } } cases: # ========================================================================= # Audit — untrusted repo owner (not in allowedRepoOwners) # ========================================================================= - note: audit_untrusted_repo_owner resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "github-fic" properties: issuer: "https://token.actions.githubusercontent.com" subject: "repo:evil-org/malicious-repo:ref:refs/heads/main" parameters: allowedRepoOwners: ["trusted-org", "another-org"] allowedRepoExceptions: [] want_effect: "Audit" # ========================================================================= # Pass — repo owner is in the allowed list # ========================================================================= - note: pass_allowed_repo_owner resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "github-fic" properties: issuer: "https://token.actions.githubusercontent.com" subject: "repo:trusted-org/my-repo:ref:refs/heads/main" parameters: allowedRepoOwners: ["trusted-org", "another-org"] allowedRepoExceptions: [] want_undefined: true # ========================================================================= # Pass — repo is in exceptions list (even if owner not allowed) # ========================================================================= - note: pass_repo_in_exceptions resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "github-fic" properties: issuer: "https://token.actions.githubusercontent.com" subject: "repo:random-org/special-repo:ref:refs/heads/main" parameters: allowedRepoOwners: ["trusted-org"] allowedRepoExceptions: ["random-org/special-repo"] want_undefined: true # ========================================================================= # Pass — empty allowedRepoOwners means allow all # ========================================================================= - note: pass_empty_owners_allows_all resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "github-fic" properties: issuer: "https://token.actions.githubusercontent.com" subject: "repo:any-org/any-repo:ref:refs/heads/main" parameters: allowedRepoOwners: [] allowedRepoExceptions: [] want_undefined: true # ========================================================================= # Pass — not a GitHub issuer (different OIDC provider) # ========================================================================= - note: pass_non_github_issuer resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials" name: "aks-fic" properties: issuer: "https://oidc.prod-aks.azure.com/00000000-0000-0000-0000-000000000000" subject: "system:serviceaccount:default:workload-identity-sa" parameters: allowedRepoOwners: ["trusted-org"] want_undefined: true # ========================================================================= # Skip — wrong resource type # ========================================================================= - note: skip_wrong_type resource: type: "Microsoft.ManagedIdentity/userAssignedIdentities" name: "my-identity" properties: {} want_undefined: true