Skip to content

Instantly share code, notes, and snippets.

@maskati
Created January 16, 2025 08:50
Show Gist options
  • Select an option

  • Save maskati/96bcb78467a040efc289f546b8f00eb4 to your computer and use it in GitHub Desktop.

Select an option

Save maskati/96bcb78467a040efc289f546b8f00eb4 to your computer and use it in GitHub Desktop.

Revisions

  1. maskati created this gist Jan 16, 2025.
    81 changes: 81 additions & 0 deletions #flexible-federated-identity.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    # Azure flexible federated identity credentials

    Up until now you have been able to define a [federatedIdentityCredential](https://learn.microsoft.com/en-us/azure/templates/microsoft.managedidentity/userassignedidentities/federatedidentitycredentials?pivots=deployment-language-bicep) with the `issuer`, `audiences` and `subject` properties. For example to allow a GitHub Actions workflow running in the context of environment `prod` in the repository `octo-org/octo-repo`:

    ```json
    {
    "issuer": "https://token.actions.githubusercontent.com"
    "audiences": [
    "api://AzureADTokenExchange"
    ]
    "subject": "repo:octo-org/octo-repo:environment:prod"
    }
    ```

    GitHub OIDC [generates a subject](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect#example-subject-claims) (`sub`) claim based on the workflow context:
    - `repo:ORG-NAME/REPO-NAME:environment:ENVIRONMENT-NAME` when the job references an environment
    - `repo:ORG-NAME/REPO-NAME:pull_request` when the workflow is triggered by a pull request event, *but only if the job doesn't reference an environment*
    - `repo:ORG-NAME/REPO-NAME:ref:refs/heads/BRANCH-NAME` or `repo:ORG-NAME/REPO-NAME:ref:refs/tags/TAG-NAME` *only if the job doesn't reference an environment, and if the workflow is not triggered by a pull request event*

    Up until now you have not been able to use any other conditions for GitHub OIDC federation to Azure workload identities. The GitHub [OIDC token](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect#understanding-the-oidc-token) includes many claims that could be useful as conditions for federation:
    ```json
    {
    "jti": "example-id",
    "sub": "repo:octo-org/octo-repo:environment:prod",
    "environment": "prod",
    "aud": "https://github.com/octo-org",
    "ref": "refs/heads/main",
    "sha": "example-sha",
    "repository": "octo-org/octo-repo",
    "repository_owner": "octo-org",
    "actor_id": "12",
    "repository_visibility": "private",
    "repository_id": "74",
    "repository_owner_id": "65",
    "run_id": "example-run-id",
    "run_number": "10",
    "run_attempt": "2",
    "runner_environment": "github-hosted"
    "actor": "octocat",
    "workflow": "example-workflow",
    "head_ref": "",
    "base_ref": "",
    "event_name": "workflow_dispatch",
    "ref_type": "branch",
    "job_workflow_ref": "octo-org/octo-automation/.github/workflows/oidc.yml@refs/heads/main",
    "iss": "https://token.actions.githubusercontent.com",
    "nbf": 1632492967,
    "exp": 1632493867,
    "iat": 1632493567
    }
    ```

    What if you wanted to allow only workflow runs triggered by a specific GitHub user? You can soon configure more flexible rules for Azure workload identity federation using [flexible federated identity credentials](https://learn.microsoft.com/en-us/entra/workload-id/workload-identities-flexible-federated-identity-credentials), which allow using a `claimsMatchingExpression` instead of `subject` specifier. You could for example create the following federated credential to allow a workflow to acquire a token for the associated identity when the workflow is manually triggered by the GitHub user `octocat`:

    ```json
    {
    "issuer": "https://token.actions.githubusercontent.com"
    "audiences": [
    "api://AzureADTokenExchange"
    ]
    "claimsMatchingExpression": {
    "languageVersion": 1
    "value": "claims['event_name'] eq 'workflow_dispatch' and claims['actor'] eq 'octocat'"
    }
    }
    ```

    Or maybe you want to allow the specific workflow in the file `oidc.yml` to acquire a token when running in the context of a release branch by using the `matches` operator and `*` wildcard:

    ```json
    {
    "issuer": "https://token.actions.githubusercontent.com"
    "audiences": [
    "api://AzureADTokenExchange"
    ]
    "claimsMatchingExpression": {
    "languageVersion": 1
    "value": "claims['job_workflow_ref'] matches 'octo-org/octo-automation/.github/workflows/oidc.yml@refs/heads/release/*'"
    }
    }
    ```