# 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
