agentsclimarketplace

Configuring azure oidc for github actions

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

Azure apps that cost nothing when nobody's using them. A Claude Code skill pack — 14 composable skills, 37+ documented gotchas, branch-per-env CI/CD.

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.

One thing to look at

  • 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.

What its author says it does

Copied from the file, not written here

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.

SKILL.md

5.2 KB, 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.

Keep looking

Skills are one crate of 328,083. 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.