# CI/CD with GitHub Actions and OIDC — Azure

Source: https://www.skillbyai.com/en/azure/o-cicd

> Deploy to Azure from a pipeline without storing long-lived secrets.

## Federated credentials instead of client secrets

A pipeline needs an Azure identity to deploy. The old approach stored a service principal's client secret in the CI system, which expires, leaks and is hard to rotate. The recommended approach is **workload identity federation** with **OpenID Connect (OIDC)**: you create an Entra app registration (or a user-assigned managed identity), add a **federated credential** that trusts tokens from GitHub for a specific repository and branch or environment, and grant it a narrowly scoped role. At run time GitHub issues a short-lived token, Entra exchanges it for an Azure token, and no secret is stored anywhere. The same pattern works for Azure DevOps, GitLab and Kubernetes workloads.

## A GitHub Actions job using OIDC

Only IDs are stored as repository variables; none of them is a secret.

```yaml
name: deploy-infra
on:
  push:
    branches: [main]

permissions:
  id-token: write   # allow the job to request an OIDC token
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: azure/login@v2
        with:
          client-id: ${{ vars.AZURE_CLIENT_ID }}
          tenant-id: ${{ vars.AZURE_TENANT_ID }}
          subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
      - run: az deployment group what-if -g rg-shop-prod-cin -f infra/main.bicep
      - run: az deployment group create  -g rg-shop-prod-cin -f infra/main.bicep
```

## A visitor badge instead of a house key

A stored client secret is a copied house key that works until someone changes the locks. OIDC is a visitor badge printed at reception for one visit, checked against the guest list, and useless the next day.

**Quiz:** Why is OIDC federation preferred over storing a client secret in GitHub?

- [ ] It makes deployments run faster
- [ ] It removes the need for RBAC roles
- [ ] It only works with Bicep
- [x] No long-lived secret is stored; each run gets a short-lived token scoped by a trust rule

*Answer:* No long-lived secret is stored; each run gets a short-lived token scoped by a trust rule. Federation exchanges a short-lived GitHub token for an Azure token, so there is nothing to leak or rotate.
