Provision github azure federated identity
Skill PlagueHO/plagueho.copilot/skills/provision-github-azure-federated-identity
**WORKFLOW SKILL** — Provision Azure User Assigned Managed Identity with OIDC federation and RBAC for passwordless GitHub authentication. WHEN: "set up Azure access for GitHub Actions", "configure managed identity for GitHub", "enable passwordless Azure authentication in CI/CD", "configure OIDC federation GitHub Azure", "Copilot coding agent Azure identity". INVOKES: run_in_terminal for PowerShell. FOR SINGLE OPERATIONS: Use az CLI for simple role assignments.From its SKILL.md
npx -y skills add PlagueHO/plagueho.copilot --skill provision-github-azure-federated-identityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
11.9 KB, as published. Nobody here has run it
Overview
This skill provisions one Azure User Assigned Managed Identity (UAMI) per invocation for GitHub OIDC authentication — no long-lived credentials required. To cover multiple environments or both GitHub Actions and Copilot coding agent, run the script once per identity needed.
Each invocation creates or verifies (idempotent):
- A shared resource group (
rg-github-<RepositoryName>-mi) for GitHub integration resources - One User Assigned Managed Identity for either a GitHub Actions deployment environment or the GitHub Copilot coding agent
- A Federated Identity Credential on the identity, binding it to the specified GitHub context via OIDC
- RBAC role assignments at subscription scope:
Contributor— allows creating and managing Azure resourcesUser Access Administrator(with conditions) — allows role assignment but prevents grantingOwner,User Access Administrator, orRole Based Access Control Administratorto any principal
If a resource already exists, the script skips creation and outputs the existing details.
Prerequisites
-
Azure PowerShell modules installed (the script validates this):
Az.Accounts≥ 5.3.2Az.Resources≥ 9.0.0Az.ManagedServiceIdentity≥ 2.0.0
Install missing modules with:
Install-Module -Name Az.Accounts, Az.Resources, Az.ManagedServiceIdentity -Scope CurrentUser -Force -
Authenticated Azure session — run
Connect-AzAccountif not already authenticated. -
The authenticated identity must have subscription-level permissions to:
- Create resource groups
- Create managed identities (
Microsoft.ManagedIdentity/userAssignedIdentities/write) - Assign RBAC roles (
Microsoft.Authorization/roleAssignments/write)
Script
The PowerShell script is bundled inside this skill's scripts/ subdirectory — it is not in
the active workspace. Before running, resolve the absolute path as follows:
- Note the absolute path of this SKILL.md file (available from the
filePathattribute of the skill attachment in context) - Replace
SKILL.mdwithscripts/Update-AzureUserAssignedManagedIdentityForGitHub.ps1to get the full script path - Confirm the file exists by calling
list_diron the skill'sscripts/subfolder
Always use the full absolute path when invoking the script via #runInTerminal.
[!IMPORTANT] Don't search for the script in any other location. Do not create the script if you can't find it — 🛑 and report the issue instead.
Script parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
RepositoryName | Yes | — | GitHub repository name (not the full org/repo path) |
Type | No | actions | Identity purpose: actions (GitHub Actions environment) or codingAgent (Copilot coding agent) |
Environment | No | test | GitHub environment name — only used when Type is actions |
GitHubOrganization | No | PlagueHO | GitHub organization or user account owning the repository |
SubscriptionId | No | Current context | Azure subscription ID to deploy resources into |
Location | No | New Zealand North | Azure region for the resource group and identity |
ResourceGroupName | No | rg-github-<RepositoryName>-mi | Override the resource group name |
IdentityName | No | Computed (see naming) | Override the UAMI name |
RbacRoles | No | @('Contributor','User Access Administrator') | RBAC role names to assign at subscription scope — overrides the default set |
RemoveUnlistedRoles | No | $false | Remove any subscription-scope role assignments for this identity that are absent from -RbacRoles |
Force | No | $false | Skip interactive confirmation prompts |
Resource naming
| Resource | Default name |
|---|---|
| Resource group | rg-github-<RepositoryName>-mi |
UAMI — actions type | mi-actions-<RepositoryName>-<Environment>-env |
UAMI — codingAgent type | mi-coding-agent-<RepositoryName> |
Federated credential — actions | <GitHubOrganization>-<RepositoryName>-<Environment> |
Federated credential — codingAgent | <GitHubOrganization>-<RepositoryName>-copilot |
Use -ResourceGroupName or -IdentityName to override the computed defaults when needed.
How to use this skill
Step 1 — Gather required information
Ask the user for (or infer from context):
RepositoryName(required) — GitHub repo nameType—actionsfor a deployment environment,codingAgentfor Copilot coding agentEnvironment— GitHub environment name (required whenTypeisactions; e.g.test,staging,prod)GitHubOrganization— if not the defaultPlagueHOSubscriptionId— if targeting a specific Azure subscription
For multiple environments or both GitHub Actions and Copilot agent access, plan to run the script once per identity required.
Step 2 — Run the script
Use #runInTerminal to execute from a PowerShell session already authenticated to Azure.
GitHub Actions identity for a single environment:
.\scripts\Update-AzureUserAssignedManagedIdentityForGitHub.ps1 `
-RepositoryName 'my-repo' `
-Type 'actions' `
-Environment 'test'
GitHub Actions identities for multiple environments (run once per environment):
foreach ($env in @('test', 'staging', 'prod')) {
.\scripts\Update-AzureUserAssignedManagedIdentityForGitHub.ps1 `
-RepositoryName 'my-repo' `
-Type 'actions' `
-Environment $env `
-Force
}
Copilot coding agent identity:
.\scripts\Update-AzureUserAssignedManagedIdentityForGitHub.ps1 `
-RepositoryName 'my-repo' `
-Type 'codingAgent'
Full invocation with all common parameters:
.\scripts\Update-AzureUserAssignedManagedIdentityForGitHub.ps1 `
-RepositoryName 'my-repo' `
-Type 'actions' `
-Environment 'prod' `
-GitHubOrganization 'MyOrg' `
-SubscriptionId '12345678-1234-1234-1234-123456789012' `
-Location 'East US' `
-Force
Custom RBAC roles (overrides defaults):
.\scripts\Update-AzureUserAssignedManagedIdentityForGitHub.ps1 `
-RepositoryName 'my-repo' `
-Type 'actions' `
-Environment 'prod' `
-RbacRoles @('Contributor')
Remove roles no longer required:
.\scripts\Update-AzureUserAssignedManagedIdentityForGitHub.ps1 `
-RepositoryName 'my-repo' `
-Type 'actions' `
-Environment 'prod' `
-RbacRoles @('Contributor') `
-RemoveUnlistedRoles
Preview changes without applying (-WhatIf):
.\scripts\Update-AzureUserAssignedManagedIdentityForGitHub.ps1 `
-RepositoryName 'my-repo' `
-Type 'actions' `
-Environment 'test' `
-WhatIf
Step 3 — Configure GitHub repository secrets and environments
After each script run, it outputs the values needed for GitHub.
Repository-level secrets (Settings → Secrets and variables → Actions):
| Secret | Value |
|---|---|
AZURE_TENANT_ID | Azure AD tenant ID (printed by script) |
AZURE_SUBSCRIPTION_ID | Azure subscription ID (printed by script) |
Per-environment secret (Settings → Environments → <env name> → Secrets):
| Secret | Value |
|---|---|
AZURE_CLIENT_ID | clientId of the managed identity for that environment (printed by script) |
For the Copilot coding agent, create a GitHub environment named copilot and set
AZURE_CLIENT_ID under it.
Step 4 — Use the managed identity in GitHub Actions
permissions:
id-token: write # Required for OIDC token request
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
environment: test # Must match the environment name used when creating the identity
steps:
- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
For Copilot coding agent workflows, use environment: copilot.
Idempotency
Running the script multiple times against the same repository is safe. Each resource (resource group, UAMI, federated credential, role assignment) is checked before creation. If it already exists, it is skipped and its current details are included in the output. Re-running is the standard approach to update a subset of environments or verify state.
RBAC role management
- Default roles:
ContributorandUser Access Administrator. - Pass
-RbacRolesto specify a different set of roles — this replaces the defaults entirely for that invocation. - By default, roles already assigned to the identity but absent from
-RbacRolesare left intact. - Pass
-RemoveUnlistedRolesto also remove any subscription-scope role assignments for the identity that are not listed in-RbacRoles. User Access Administratoris always assigned with a condition preventing the identity from grantingOwner,User Access Administrator, orRole Based Access Control Administratorto any principal, regardless of whether the role list was customised.
Edge cases and when to pause
RepositoryNamenot provided — only mandatory parameter; ask before running.Typenot specified — ask whether the identity is for GitHub Actions (actions) or Copilot coding agent (codingAgent).Environmentnot specified foractionstype — ask for the environment name; each environment requires a separate script execution.- Multiple environments — confirm the list before running; one execution is needed per environment.
- Non-default
SubscriptionId— confirm which subscription to use if it differs from the current Azure context. -Forceflag — do not pass unless the user explicitly requests skipping prompts; without it the script confirms each resource creation interactively.-RemoveUnlistedRoles— confirm with the user before using; roles assigned outside this script could be intentional.- Role assignment failures — the script retries up to 3 times. If all retries fail, surface the error and ask the user to verify Azure permissions before retrying.
Security notes
- No static credentials are created. All authentication uses short-lived OIDC tokens issued by GitHub at runtime.
User Access Administratoris granted with a condition expression that prevents assignment ofOwner,User Access Administrator, orRole Based Access Control Administrator, following the principle of least privilege.- Script output includes tenant and subscription IDs. These are non-secret identifiers but should not be committed to public repositories — store them as GitHub secrets.