agentsclimarketplace

Configuring azure oidc for github actions

Skill alexpizarro/azure-lean-stack-skills/skills/configuring-azure-oidc-for-github-actions

Sets up branch-scoped Azure OIDC for GitHub Actions — creates service principals, federated credentials bound to each branch's refs/heads/{branch}, generates SQL passwords, and sets GitHub secrets. Use when bootstrapping CI/CD, onboarding a new environment branch, or fixing AADSTS70021 subject mismatches.From its SKILL.md

Install
npx -y skills add alexpizarro/azure-lean-stack-skills --skill configuring-azure-oidc-for-github-actions

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

3 things to look at

  • reads credentialsReads from 1 credential source: `AZURE_CONFIG_DIR`.
  • 1 stars1 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.
  • runs commandsInstructs the agent to run 6 commands, including `bash scripts/create-sp-with-oidc.sh` and 5 more.

SKILL.md

5.2 KB, ~1.2k tokens by cl100k_base, as published. Nobody here has run it

Configuring Azure OIDC for GitHub Actions

Sets up secret-less Azure authentication for GitHub Actions. After running these scripts, deploys work via git push with no client secrets to rotate.

Why OIDC

  • No client secrets stored in GitHub or in code
  • Branch-scoped: the test SP can't deploy to production and vice versa
  • Federated credential subject is bound to refs/heads/{branch} exactly — drift causes AADSTS70021

Workflow checklist

Copy this checklist into your response and check items off as you complete them:

OIDC + GitHub Actions setup:
- [ ] Step 1: Verify az login + gh auth login (and AZURE_CONFIG_DIR if shared machine)
- [ ] Step 2: Confirm GitHub repo exists, branches (test, production) created
- [ ] Step 3: Run scripts/create-sp-with-oidc.sh → creates test + prod SPs + federated creds
- [ ] Step 4: Run scripts/generate-sql-password.sh → SQL admin passwords
- [ ] Step 5: Run scripts/add-github-secrets.sh → 6 secrets set
- [ ] Step 6: For each additional environment branch (acme-demo, customer-uat, etc.), re-run with that branch name
- [ ] Step 7: First push to test → verify the workflow authenticates (no AADSTS70021)

Setup sequence

Run these scripts in order. Each is idempotent (safe to re-run).

# Prerequisites: az login and gh auth login already done.
# Use AZURE_CONFIG_DIR if this project shares a machine with others.

export ORG="acme"             # short org prefix
export PROJECT="taskapp"      # short project name
export GITHUB_ORG="myorg"
export REPO="taskapp"

# 1. Create both service principals + federated credentials
bash scripts/create-sp-with-oidc.sh

# 2. Generate SQL admin passwords (test + prod)
bash scripts/generate-sql-password.sh

# 3. Set the 6 GitHub secrets
bash scripts/add-github-secrets.sh

Each script prints what it will do, what already exists, and what was created.

The 6 GitHub secrets

SecretScopeSource
AZURE_TENANT_IDBoth envsaz account show --query tenantId
AZURE_SUBSCRIPTION_IDBoth envsaz account show --query id
AZURE_CLIENT_ID_TESTTest SP appIdcreate-sp-with-oidc.sh output
AZURE_CLIENT_ID_PRODProd SP appIdcreate-sp-with-oidc.sh output
SQL_ADMIN_PASSWORD_TESTTest SQL admingenerate-sql-password.sh output
SQL_ADMIN_PASSWORD_PRODProd SQL admingenerate-sql-password.sh output

Critical: federated credential subject format

Azure rejects the OIDC token if the subject doesn't match exactly:

repo:{GitHubOrg}/{Repo}:ref:refs/heads/{branch}
Common mistakeError
ref:refs/heads/main when workflow pushes from testAADSTS70021: No matching federated identity record found
pull_request subject for branch pushsame
Extra trailing slashsame
Repo case mismatch (MyOrg vs myorg)same

If you see AADSTS70021, dump the actual issuer + subject from the failed run, then compare against the federated credential:

az ad app federated-credential list --id "$CLIENT_ID" -o table

When to use User Access Administrator

The default Contributor role is sufficient for SWA + SQL deploys. You need User Access Administrator when Bicep contains Microsoft.Authorization/roleAssignments resources — typically:

  • FC1 Flex Consumption (Function App MI → Storage Blob Data Owner)
  • Container Apps Jobs that need AcrPull or similar
  • Any module that does roleAssignments on a child resource

Grant at the smallest scope that works (RG > subscription):

az role assignment create \
  --assignee "$SP_OID" \
  --role "User Access Administrator" \
  --scope "/subscriptions/$SUB_ID/resourceGroups/$ORG-$PROJECT-rg-test"

If the RG doesn't exist yet, scope to subscription temporarily.

SP creation gotcha — WARNING in stdout

az ad sp create-for-rbac --sdk-auth prepends a WARNING: line to stdout. If that ends up in AZURE_CREDENTIALS (the legacy format), authentication silently fails. OIDC sidesteps this — we only store the appId, never the SP JSON. But if you ever need AZURE_CREDENTIALS, strip the warning:

az ad sp create-for-rbac ... --sdk-auth 2>/dev/null \
  | python3 -c "import sys,json; d=sys.stdin.read(); print(json.dumps(json.loads(d[d.find('{'):]),indent=2))"

Composes with

Reference

See references/federated-credentials.md for the full breakdown of subject formats, audiences, and verification commands.

What ships with it: 4 files

10.1 KB alongside SKILL.md, 3 of them executable

references/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.