Configuring GitHub Actions to Azure authentication with OIDC

Security is one of the top priorities for any company working with cloud. Any intrusion can cost thousands of dollars due to the easiness of compute spin-ups to happen. Which is why we should limit the use of credentials anywhere in our code!
One such risk factor is running your CI/CD pipelines with Azure credentials hardcoded as a GitHub secret. Luckily for us, GitHub added Azure OIDC (OpenID Connect) that allows us to connect GitHub to Azure as a managed identity.
But how do we configure this? Well, that's what I will explain in this article!
Prerequisites
- Azure CLI Installed
- Logged in on the Azure CLI (
az login
) - Subscription set (
az account set --subscription <YOUR_ID>
)
Create an AD Application
First off, we need to configure our GitHub Actions workspace as an Azure AD application. Once it is created, we fetch the `APP_ID`
az ad app create --display-name "GitHub OIDC"
APP_ID=$(az ad app list --display-name "GitHub OIDC" --query '[].appId' -o tsv)
Create a Service Principal for the Application
Once the app exists we configure a service principal for it. This allows us to assign fine-grained permissions to the application.
az ad sp create --id $APP_ID
SP_ID=$(az ad sp list --display-name "GitHub OIDC" --query '[].id' -o tsv)
Now assign it the proper rights
az role assignment create --assignee-object-id $SP_ID --assignee-principal-type ServicePrincipal --role contributor
Configure access from GitHub to Azure
Finally, we configure the created application to create a federation to GitHub on our specific repository with the below:
GH_USERNAME="YOUR_USER"
GH_REPO="YOUR_REPO"
GH_BRANCH=main
az ad app federated-credential create --id $APP_ID --parameters "{\"name\":\"FederatedCredential\", \"issuer\":\"https://token.actions.githubusercontent.com\", \"subject\":\"repo:${GH_USERNAME}/${GH_REPO}:ref:refs/heads/${GH_BRANCH}\", \"description\":\"Allow GitHub Actions to access Azure Resources\", \"audiences\":[\"api://AzureADTokenExchange\"]}"
Configuring GitHub Actions
To run a workflow, we now configure GitHub Secrets to point to the correct Azure subscription:
echo "AZURE_CLIENT_ID: '$APP_ID'"
echo "AZURE_TENANT_ID: '$(az account show --query tenantId -o tsv)'"
echo "AZURE_SUBSCRIPTION_ID: '$(az account show --query id -o tsv)'"
Now in your GitHub workflow, simply configure the Azure Login action to utilize the secrets configured:
name: Run Azure Login with OIDC
on: [push]
permissions:
id-token: write
contents: read
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: 'Az CLI login'
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: 'Run az commands'
run: |
az account show
az group list
pwd
Script
As a shortcut I included the script below that you can easily run:
GH_USERNAME="YOUR_USER"
GH_REPO="YOUR_REPO"
GH_BRANCH=main
# 1. Create an Azure AD Application:
az ad app create --display-name "GitHub OIDC"
# 2. Get the Azure AD Application ID:
APP_ID=$(az ad app list --display-name "GitHub OIDC" --query '[].appId' -o tsv)
# 3. Create a Service Principal for the Application:
az ad sp create --id $APP_ID
# 4. Get the Service Principal Object ID:
SP_ID=$(az ad sp list --display-name "GitHub OIDC" --query '[].id' -o tsv)
# 5. Assign the Service Principal to the Contributor Role:
az role assignment create --assignee-object-id $SP_ID --assignee-principal-type ServicePrincipal --role contributor
# 6. Add the federated identity credential to GitHub:
# -> findable under https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade/
# under certificates & secrets -> federated credentials
az ad app federated-credential create --id $APP_ID --parameters "{\"name\":\"FederatedCredential\", \"issuer\":\"https://token.actions.githubusercontent.com\", \"subject\":\"repo:${GH_USERNAME}/${GH_REPO}:ref:refs/heads/${GH_BRANCH}\", \"description\":\"Allow GitHub Actions to access Azure Resources\", \"audiences\":[\"api://AzureADTokenExchange\"]}"
# Set the following in GitHub as secrets
echo "Configure the below as GitHub Secrets"
echo "AZURE_CLIENT_ID: '$APP_ID'"
echo "AZURE_TENANT_ID: '$(az account show --query tenantId -o tsv)'"
echo "AZURE_SUBSCRIPTION_ID: '$(az account show --query id -o tsv)'"
Member discussion