Authentication to Azure from GitHub has required that you stored sensitive, time constrained secrets in GitHub. I am of course talking about the ClientSecret you get from creating an Azure AD App Registration.
You can now do authentication with a method called OpenID Connect. This can help authentication in several ways:
When first hearing about OIDC authentication I assumed it would be complex and difficult to set up. Configuring SSO/Federation/authentication has not always been easy.
Imagine my surprise when I managed to configure this within without much hassle at all!
This is the high level task list:
These steps are more or less the same if you are using ARM, Terraform(soon), or Bicep. I will show you a simple deployment to Azure with Bicep in this post.
Run this powershell snippet to create app registration, service principal, and assign contributor role on subscription:
$context = get-azcontext $appName = ‘oidc-demo’ $subscriptionId = $context.subscription.id $appId = (az ad app create –display-name $appName | convertFrom-json).appId $objectId = (az ad sp create –id $appId | convertfrom-json).objectId az role assignment create –role contributor ` –subscription $subscriptionId ` –assignee-object-id $objectId ` –assignee-principal-type ServicePrincipal ` –scope /subscriptions/$subscriptionId Write-Host “These are the “secrets” you need to add to GitHub`n———————————————–`nApplication Id (ClientId/AppId/AAD_APP_ID): $appId`nTenant Id (Directory Id/AAD_TENANT_ID): $($context.tenant.id)`nSubscription Id (AZURE_SUBSCRIPTION_ID): $subscriptionId`n———————————————–”
Please be aware that this service principal will be granted contributor permissions on your entire subscription. If this is not wanted, you can update the role assignment command above before executing.
Also, there is no client secret to note and put into a GitHub secret.
Navigate to your app registration’s Certificates & secrets
Choose _Federated credentials and Add credential
_
Choose GitHub Actions deploying Azure resources
Add credential for your branch in your repository and organisation. This info must be correct, as it is used for token issuing. If you enter the exact information from below image, your authentication will not work.
Authentication from a Pull Request did not work with this federated identity alone, so I needed to add Pull Request entity type also:
You need to create some GitHub secrets for holding App Registration and Azure information. If you change these names, you need to update the deployment workflow accordingly.
Assuming you have performed the steps correctly, you should now be able to run the workflow for deploying a resource group and a storage account with Bicep, authenticated without client secret stored in GitHub! 🥳
There are a few changes from how you would do it with regular authentication. Previously you would store clientId, clientSecret, subscriptionId, and tenantId in a json secret called AZURE_CREDENTIALS, and use this in the GitHub login action. This is not necessary with OIDC, and the action will instead request a token to use for temporary authentication.
The job or workflow run requires a permissions setting with id-token: write. You won’t be able to request the OIDC JWT ID token if the permissions setting for id-token is set to read or none.
The id-token: write setting allows the JWT to be requested from GitHub’s OIDC provider
permissions: id-token: write contents: read
This is the login action, and it is not supplied with any client secret for authentication.
- name: ‘Az CLI login’ uses: azure/login@v1 with: client-id: ${{ secrets.AAD_APP_ID }} tenant-id: ${{ secrets.AAD_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} enable-AzPSSession: true
This is your OIDC login verification (yours will be somewhat different):
Terraform has just recently started supporting OpenID Connect as authentication method (since v1.2.0 and AzureRM Provider 3.7.0). This requires some changes to your terraform backend configuration. Terraform OIDC documentation here. I opted for using CLI input backend-config, to avoid putting info in code, but to each their own.
You need to update your existing workflows to support OIDC.
Note these settings in main.tf:
Bicep does not care how you authenticate, as long as you are authenticated. This means that only your workflows need updating.
Congratulations! You have now authenticated with OpenID Connect from GitHub Actions to Azure. Your first step towards a future free of client secrets 😎
You’ll find a workflow for Bicep deployment here, and one for Terraform deployment here.
Please don’t hesitate to give me a comment if you find something not working or an obvious mistake!