New: This blog post is available as an audio podcast generated by NotebookLM:

Azure Back to School

Info

Azure Back to School is a free annual community event which takes place every September.

See the full list of speakers and sessions for this year for more great Azure-related content.

Are you an Azure user who’s tired of managing service principals and their secrets? Ever seen an integration break because of an expired service principal secret? Or maybe you want to increase the security of your GitHub Actions workflows that deploys to your Azure environment? New to OpenID Connect, or just barely heard of it? If any of these questions apply to you, this session is for you!

Tip
Do you want to skip directly to the hands-on part? Go here.

OpenID Connect Link to heading

OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. It allows clients to verify the identity of the end-user based on the authentication performed by an authorization server, as well as to obtain basic profile information about the end-user in an interoperable and REST-like manner.

One of the biggest advantages for end-users is that this eliminates the need to create and store passwords or secrets to be able to authenticate. This also will remove a great deal of the overhead typically associated with rotating secrets before expiration and reduce the risk of leaking secrets.

To learn more about OpenID Connect you can see the official documentation here.

GitHub Actions and Azure Link to heading

GitHub Actions is a CI/CD platform that allows you to automate your software development workflows. It is tightly integrated with GitHub and allows you to build, test, and deploy your code right from GitHub.

For GitHub Actions and Azure you have several commonly used official marketplace actions like Azure/login for connecting your GitHub Actions workflows to Azure, Azure/powershell for running PowerShell scripts against Azure or Azure/cli for running Azure CLI commands against Azure.

If you have used any of these you’ve most likely written workflows that deploys to your Azure environment. Historically when doing this you would need to set up a service principal and add a set of secrets to your GitHub repository.

OpenID Connect on the Microsoft Identity Platform Link to heading

Microsoft Identity Platform is the identity platform for developers who build apps for consumers and businesses on Azure. It supports a range of standards including OpenID Connect.

If you are building services in Azure you can use workload identity federation to utilize OpenID Connect to authenticate and access resources or communicate with other services. This can easily be set up using federated credentials.

You can use the traditional application-type service principals which allows you to access your Azure resources from “anywhere”, or if your workload is running in Azure you can use managed identites.

Overview of the process of authenticating from an external workflow (e.g. GitHub Actions) to your Azure Resources using OpenID Connect. Diagram from Microsoft (CC BY 4.0).

Overview of the process of authenticating from an external workflow (e.g. GitHub Actions) to your Azure Resources using OpenID Connect. Diagram from Microsoft (CC BY 4.0).

Managed Identities Link to heading

If you are using service principals for deploying Azure Resources via Azure Resource Manager (through Bicep, ARM templates, PowerShell, Azure CLI, Terraform) you have most likely set up a service principal and secrets. When using a managed identity you get the following benefits:

  • 💪 Managed Identities can be created declaratively via Bicep or any tool that supports the Resource Manager API (i.e. no Azure AD/Graph API calls needed)
  • 🔐 Every management operation of the managed identity happens in the Azure Resources plane and respects Azure role-based access contol (RBAC)
  • ♻️ The lifecycle of a managed identity follows the lifecycle of your Azure Resources - if you delete a resource group with it it’s cleaned up automatically.
  • 🔑 Where as a service principal can have both secrets and federated credentials - with managed identities you can only use federated credentials which means no risk of secrets being leaked or usage outside your pre-approved external clients that supports federated credentials.
  • 💰 Managed Identities in Azure are completely free with no extra cost!

How to set up GitHub Actions to connect to Azure Link to heading

Tip
The steps listed below is available on GitHub with full PowerShell, Bicep and GitHub Actions workflow files!

Prerequisites Link to heading

To get started with setting up GitHub Actions for your Azure environment you need the following prerequisites:

For this guide we’re going to create a managed identity and use federated credentials to connect to Azure from GitHub Actions.

Create a managed identity Link to heading

First you need to connect to Azure with your user account and make sure you select the correct subscription. Run the following PowerShell commands to get started:

Connect-AzAccount # Follow the steps needed to sign in

Set-AzContext -SubscriptionId "<subscription-id>" # Replace with subscription id

Then continue to set some variables needed for deploying the managed identity:

$ResourceGroupName  = "managed-identity-rg" # Name of a new resource group
$Location           = "norwayeast"          # Location for the resource grop
$IdentityName       = "github-actions-mi"   # Name of the Managed Identity
$GhUserName         = "<your username>"     # Your GitHub username
$GhRepoName         = "<your repository>"   # Name of your existing repository
$GhEnvName          = "Azure" # For the Environment you will set up in GitHub
$RoleDefinitionName = "Owner" # The role you want to assign to the managed identity

After setting these variables you can run the following which creates a new resource group, creates a new managed identity, creates a role assignment for the managed identity and setting up the federated credentials for your managed identitiy.

#* Create resource group
$rg = New-AzResourceGroup -Name $ResourceGroupName -Location $Location

#* Create user assigned managed identity
$identity = New-AzUserAssignedIdentity -ResourceGroupName $rg.ResourceGroupName `
    -Name $IdentityName -Location $Location

#* Create subscription-level role assignment for the managed identity
New-AzRoleAssignment -PrincipalId $identity.PrincipalId -RoleDefinitionName  `
    $RoleDefinitionName -ObjectType "ServicePrincipal"

#* Create credentials for user assigned managed identity
New-AzFederatedIdentityCredentials -ResourceGroupName $rg.ResourceGroupName `
    -IdentityName $identity.Name -Name $GhRepoName `
    -Issuer "https://token.actions.githubusercontent.com" `
    -Subject "repo:${GhUserName}/${GhRepoName}:environment:${GhEnvName}"

#* Output subscription id, client id and tenant id
$out = [ordered]@{
    SUBSCRIPTION_ID = $(Get-AzContext).Subscription.Id
    CLIENT_ID = $identity.ClientId
    TENANT_ID = $identity.TenantId
}
Write-Host ($out | ConvertTo-Json | Out-String)

Make note of the output from the last command as this is needed in the next step!

Configure your GitHub Repository Link to heading

To do this step you can do one of two options:

If you have GitHub CLI installed you can continue to set up everything still using the command line (continue using the existing session). You will need to change directory to a local clone of your repository and then run:

cd <path-to-your-repo>

gh secret set SUBSCRIPTION_ID --body $out.SUBSCRIPTION_ID --env $GhEnvName
gh secret set CLIENT_ID --body $out.CLIENT_ID --env $GhEnvName
gh secret set TENANT_ID --body $out.TENANT_ID --env $GhEnvName

If you want to use the portal navigate to your repository in GitHub follow this guide to set up the secrets for your repository.

Note that you need to define the environment name using the same vaue as you used in the previous step, and copy the values from the output of the last command. The secret names needs to be (case-sensitive): SUBSCRIPTION_ID, CLIENT_ID and TENANT_ID.

Create a workflow in GitHub Actions Link to heading

Now that you have set up the managed identity and configured your GitHub repository you can create a workflow that uses the managed identity to deploy to your Azure environment.

Add the following file to your GitHub repository in the .github/workflows directory:

name: Azure OIDC Managed Identity Demo
on: [workflow_dispatch]

permissions:
  id-token: write
  contents: read

jobs:
  demo:
    runs-on: ubuntu-latest
    # Note: this needs to match the environment where the secrets are stored
    environment: Azure
    steps:
      - name: "Azure PowerShell login"
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.CLIENT_ID }}
          tenant-id: ${{ secrets.TENANT_ID }}
          subscription-id: ${{ secrets.SUBSCRIPTION_ID }}
          enable-AzPSSession: true

      - name: "Get resource groups"
        uses: azure/powershell@v2
        with:
          inlineScript: |
            Get-AzResourceGroup            
          azPSVersion: "latest"

Remember to run git add, git commit and git push to push the changes to your repository.

Run a workflow with GitHub Actions Link to heading

After pushing the workflow file to your repository you can navigate to Actions in your repository, find the Azure OIDC Managed Identity Demo workflow and run it:

GitHub Actions workflow

🥳 Congratulations! You have now successfully set up GitHub Actions to connect to your Azure environment using OpenID Connect and managed identities!

Tip
You can view full code examples in my repository where all of this (and some more) here!

Notes Link to heading

  • If you want a Bicep based deployment of managed identity you can use my demo repository which contains the necessary scripts, templates and workflows to get started. You can fork it to get quickly up and running.

  • If you want a quickstart for setting up a service principal instead of a managed identity you can use the the following script.

    • Note that users that use service principals and federated credentials have experienced issues with short-lived tokens expiring before the workflow is finished. This is a known issue, and does not occur (as far as I know) when using managed identities.
  • Not using Azure PowerShell but Azure CLI? See this guide.

  • Using Azure DevOps instead of GitHub? Support for workload identity federation ̃is launching in public preview in Q3 2023 has launched!

Next steps Link to heading