Connect GitHub with Azure using OIDC
Using OIDC to log in to Azure within a GitHub Action offers multiple advantages:
- It avoids complex secrets, such as:
- No need for periodic secret renewal
- Use of managed identity, and gain fine control over role assignment and scope
Summary:
- Create a user-assigned managed identity
- Assign roles to the user-assigned managed identity
- Configure a federated identity credential
- Configure the GitHub repository
The aleternative is to create a Service Principal, with a secret, assigning the roles to the Service Principal, and create a secret in GitHub with the following format:
{
"tenantId": "<ID of the tenant>",
"subscriptionId": "<ID of the subscription>",
"clientId": "<ID of the SPN (Application (client) ID)>",
"clientSecret": "SPN secret"
}
In the GitHub action, use the creds
parameter in the azure/login@v2
step:
- name: 'Login via Azure CLI'
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
User-assigned managed identity
Azure portal
In the Azure Portal, create a user-assigned managed identity
Set the propreties of the identity:
- Select or create a group
- Select the region for the resources
- Set the name (Azure resource name abbreviations)
- Click on Next to set the tags, otherwise, click on Review + Create:
Set the tags, eventually, and click on Next.
Review the information, and click on Create.
Azure CLI
Login to Azure:
az login
Run the following commands:
az identity create --name <identity name> --resource-group <group name> [--location <location>] [--tags tagname=tagvalue tagname=tagvalue]
az identity list [--resource-group <group name>]
Managed identity roles
To deploy Azure resources, the Managed Identity should be:
- Contributor
- [Opion] Role Based Access Control Administrator, if the MI is used to configure roles
The scope may a a resource group, a set of resource groups, a subscription, depending on the orgnization's governance.
Note: for Terraform deployments, the Managed Identity can be assigned the Storage Blob Data Contributor role for the storage account where the Terraform states are stored.
Azure Portal
In the Azure Portal, click on Access Control (IAM) from the object on which the MI's role is applied:
Click on Add, and the Add role assignment:
Select the Privileged administrator roles, and the select the role:
- Contributor
- Role Based Access Control Administrator
Click on Next
Click on Managed identity radio button, the click on + Select members. Select the MI, and the click on Next:
Select the condition, if asked. The Allow user to assign all roles except privileged administrator roles Owner, UAA, RBAC is recommanded for the Role Based Access Control Administrator role. Click on Next or Review + assign:
Check the information, and click on Review + assign:
Azure CLI
Login to Azure:
az login
Run the following commands:
az role assignment create --role <role name> --assignee <assignee name>| --assignee-principal-type ServicePrincipal ServicePrincipal --assignee-object-id <assignee object id, principal id> --scope <resource id. e.g.: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/MyVm> [--condition <condition> --description <description>]
az role assignment list --assignee-object-id --assignee <assignee name>|--assignee-object-id <assignee object id, principal id>
Roles:
Contributor
Role Based Access Administrator
Configure a federated identity credential
Azure Portal
In the Azure Portal, open the Federated Credential pane from the Settings menu under the Managed Identity object:
Click on + Add credential:
Select GitHub Actions deploying Azure resources scenario.
Set:
- The GiHub organization name,
- The GitHub repository name,
- The enity type, between Environment, Branch, Pull Request or Tag,
- The name of the entity,
- The name of the credential
Azure CLI
Login to Azure:
az login
Run the following commands:
az identity federated-credential create --name <name of the federated credential> --identity-name <identity name> --resource-group <resource group name> --issuer https://token.actions.githubusercontent.com --subject repo:https://github.com/<organization name>/<repository name>:environment:<environment name> --audiences api://AzureADTokenExchange
az identity federated-credential list --identity-name <identity name> --resource-group <resource group name>
Configure the GitHub repository
In the GitHub repository, ensure the entity exists. For the environment, check the repository settings and the environment pane, under the code and automation section.
Create the following secrets in the GitHub repository, eventually within the environment:
AZURE_CLIENT_ID
: the ID (client ID) of the user-assigned managed identity,AZURE_SUBSCRIPTION_ID
: the ID of the subscriptionAZURE_TENANT_ID
: the ID of the tenant
In your GitHub action, add the permissions
section at the top, and reference the client-id
, subscription-id
and tenant-id
paramters / secrets in the azure/login@v2
step:
# ...
permissions:
id-token: write
contents: read
# ...
jobs:
# ...
steps:
#...
- name: Azure login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}