Problem
The CI/CD pipeline currently authenticates to Azure using a AZURE_CREDENTIALS GitHub secret containing a long-lived service principal JSON (client ID + secret). This is the highest-risk secret in the repo: it grants broad Azure access and never expires automatically.
Solution
Switch to Workload Identity Federation (OIDC). GitHub Actions obtains a short-lived token from the Azure identity provider at job start — no stored credentials at all.
Steps
- Create a user-assigned managed identity (or use a service principal) and configure a federated credential for:
repo:techhubms/techhub:environment:staging
repo:techhubms/techhub:environment:production
repo:techhubms/techhub:ref:refs/heads/main (for shared infra deploys)
- Grant the identity the required roles (Contributor on sub, Key Vault Secrets Officer, etc.)
- Replace
azure/login with the OIDC variant:
- uses: azure/login@v2
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
- Delete the
AZURE_CREDENTIALS GitHub secret
- Store
AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID as repository variables (not secrets — they are not sensitive)
Outcome
- Zero long-lived credentials in GitHub
- Tokens are scoped per-job and expire after the job
- Audit trail in Azure AD shows exactly which workflow run authenticated
Problem
The CI/CD pipeline currently authenticates to Azure using a
AZURE_CREDENTIALSGitHub secret containing a long-lived service principal JSON (client ID + secret). This is the highest-risk secret in the repo: it grants broad Azure access and never expires automatically.Solution
Switch to Workload Identity Federation (OIDC). GitHub Actions obtains a short-lived token from the Azure identity provider at job start — no stored credentials at all.
Steps
repo:techhubms/techhub:environment:stagingrepo:techhubms/techhub:environment:productionrepo:techhubms/techhub:ref:refs/heads/main(for shared infra deploys)azure/loginwith the OIDC variant:AZURE_CREDENTIALSGitHub secretAZURE_CLIENT_ID,AZURE_TENANT_ID,AZURE_SUBSCRIPTION_IDas repository variables (not secrets — they are not sensitive)Outcome