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:
- You do not have to store sensitive clientSecret.
- You do not have to regenerate your clientSecret.
- Your clientSecret does not expire and cause outages.
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:
- Create an app registration
- Create a GitHub repository (if you don’t already have one)
- Create a federated identity
- Create GitHub secrets for Azure information
- Create a simple workflow to test deployment
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.
Prereqs OIDC
- Create an Azure AD App Registration.
- Add federated credentials for the Azure Active Directory application.
- Create GitHub secrets for storing Azure configuration.
Create Azure AD App Registration
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.
Create GitHub secrets
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.
- AAD_APP_ID – Will be the app id/client id from script above
- AAD_TENANT_ID – The Azure AD tenant Id from script above
- AZURE_SUBSCRIPTION_ID – Subscription Id from script above
GitHub Workflow
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):
Deployments
Terraform
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
Bicep does not care how you authenticate, as long as you are authenticated. This means that only your workflows need updating.
Success!
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!
2 Replies to “Get rid of Client Secrets with OIDC on Github + Bicep & TF”