Before we can automate our infrastructure as code, there is always to need to grant the required permissions to our release pipelines. For GitHub Actions, this typically involved creating a Service Principal with a client secret. By storing those credentials as GitHub secrets, your GitHub actions were able to connect to Azure. Thanks to Federated Credentials, we can avoid the need of managing secrets and avoid the pain of potential expirations.
Service principal vs Managed Identity
This passwordless authentication was already available on Service Principals and became recently available on User-Assigned Managed Identities. What you choose strongly depends on your use case. For my situation, I identified the following advantages of using this with a Managed Identity:
- It’s an Azure (not AAD) resource, so we can manage it through Bicep
- We can reuse this identity for the deploymentScripts, so all deploy actions run under the same identity
How to configure it?
Before you execute these steps, I assume that a GitHub repository is available and you have Admin rights. Execute the following steps for every environment. A user with Owner permissions on the Azure subscription(s) is needed.
Create Managed Identity
Let’s start by creating the Identity:
- Create a User-Assigned Managed Identity:
- In the Federated credentials tab, click + Add Credential and choose the GitHub Actions scenario.
- Configure all requested parameters. The most important aspect is that you restrict access to a specific environment. Later, during the GitHub setup, you will see the concept of that environment again.
Assign Azure Permissions
The identity must have sufficient permission to deploy. Grant the following subscription permissions, via the Azure role assignments tab:
- Contributor: required to create all Azure resources
- User Access Administrator: required to perform role assignments on managed identities
One remark: the fact that we require User Access Administrator rights to perform role-assignments on managed identities is a security issue. On one hand, it’s more secure, because we use secretless managed identities. On the other hand, it’s less secure, because we get too many access rights than actually needed. The Azure engineering teams are aware of this issue and are working an a promising solution for this.
Configure GitHub Credentials
Execute the following steps in your GitHub repository:
- Create a new environment (with the same name as above), in the Settings section of your GitHub repo:
- Within the environment, add the following secrets:
- AZURE_CLIENT_ID: the Client ID of the managed identity
- AZURE_TENANT_ID: the Azure AD tenant ID
- AZURE_SUBSCRIPTION_ID: the ID of the appropriate subscription
Configure your GitHub workflow
Last, but not least, you have to configure your GitHub workflow to use Open ID Connect with the specified environment secrets. You can find a working example here.
- Add permission settings to your workflow, to indicate that an access token has to be used
permissions: id-token: write contents: read
- Link the job to the correct environment
jobs: deploy-infra: name: Deploy Infra runs-on: windows-latest environment: prd
- Use the azure/login@v1 action to connect to Azure with the created secrets
- name: Log into Azure uses: azure/login@v1 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Conclusion
A fairly simple way to allow GitHub runners to authenticate against your Azure environment, without the hassle of shared secrets! That’s a great addition to both products and a nice example of a shared strategy vision GitHub and Azure.
Remember: sharing is caring!
Thanks
Toon