Connect to Azure from Github Actions

Connect to Azure from Github Actions

Introduction

This is part of a series of posts exploring how to interact with different data services in Azure from Github and Azure DevOps. In this post, I will show you how to authenticate Github Actions with Azure.

Pre Requisites

To follow along with this you are going to need:

  • An Azure subscription
  • A Github account
  • Permissions to create service principals in Azure
  • Permissions to create secrets in Github

Options for authenticating with Azure

The primary objective is to use Azure login action to authenticate with Azure to allow you to interact with other resources. According to the docs, there are two ways to authenticate:

  • Service principal with secrets
  • OpenID Connect (OIDC) with an Azure service principal using a Federated Identity Credential

Lots of words, but what does it mean? Let’s break it down…

In both cases you need to use a service principal to authenticate. Consider a service principal as a security object within Microsoft Entra that represents an application. This service principal can be assigned to roles in Azure to grant access to resources.

Service principal with secrets

You can create a secret for a service principal and that secret will allow you to authenticate with Azure as the aforementioned service principal. This approach has been the most common way to authenticate however, there is some downsides. The secret must be stored somewhere in order to be used by your application, and secrets also have an expiry date therefore, secrets need to be rotated. If a secret expires and you haven’t rotated it then no access for you! What I have seen happen in many cases is that a secret will be set to a really long expiry date so that it doesn’t need rotating regularly, but the longer a secret is in use the more likely it is to be compromised.

OpenID Connect (OIDC) with an Azure service principal using a Federated Identity Credential

Wordy…let’s just call it Service Principal with federated credentials. How this works is by defining a trust between Azure and Github specifically for this service principal. This credential is restricted in scope and there are no secrets to manage.

Create service principals

I am going to set up two service principals, one for each method of authentication. Service principals are set up in App registrations in Microsoft Entra admin center . These menus can move about a bit so rather than providing you a path, use the search menu…

the search bar is being used in Entra Administrator to find App Registrations

We will create two service principals, one called github-actions-with-secret and one called github-actions-with-federated-credential. Create a new registration and give it a name, repeat for the second service principal.

Creating a new app registration in Entra Administrator

You should now have two registered applications…

Two service principals are listed as app registrations in Entra Administrator

Create client secret

To create the client secret, open up the service principal and navigate to the certificates & secrets section. Click on New client secret and give it a description and an expiry date.

Creating a new client secret for a service principal in Entra Administrator

Once the secret is created, you will need to make a note of the secret value as once you leave this page it will not be displayed again!

The client secret is displayed in Microsoft Entra Administrator

Final step, is to make a note of the client ID and the tenant ID, both of which will be needed to construct our secret in Github.

The client ID and tenant ID are displayed in the overview of the service principal in Microsoft Entra Administrator

Create a federated credential

To create a federated credential, open up the service principal and navigate to the certificates & secrets section. Click on Add credential.

Creating a new federated credential for a service principal in Entra Administrator

There is a bit more to configure here, first you need to select the scenario to restrict the scope to Github, open the drop down and choose Github Actions.

Selecting the scenario for the federated credential in Entra Administrator

You are then required to select the repository that you want to restrict access to. This configuration will further restrict the scope, meaning we will only be able to authenticate from the configured repository.

Selecting the repository for the federated credential in Entra Administrator

Once created, you will need to make a note of the client ID and the tenant ID, both of which will be needed to construct our secrets in Github.

The client ID and tenant ID are displayed in the overview of the service principal in Microsoft Entra Administrator

Set permissions in Azure

For this demo I want the service principals to be able to authenticate with Azure and list the resource groups that are present. This is a basic example to demonstrate the authentication and permissions are working. To do this I need to permit the service principals to read the resource groups in the subscription. From the subscription, navigate to the Access control (IAM) section and click on Add role assignment.

Adding a role assignment to a service principal in Microsoft Entra Administrator

Select reader from the available function roles…

Selecting the reader role for a service principal in Microsoft Entra Administrator

Then select the members heading and search for the service principals in the blade that pops out from the right. Click on them both to add them to the member list.

Adding the service principals to the role assignment in Microsoft Entra Administrator

Once complete, click on Review + assign to confirm the role membership.

Reviewing the role assignment in Microsoft Entra Administrator

Create secrets in Github

Next we need to set up secrets in our Github repository so that our workflow can use them to authenticate with Azure. Our service principal with secrets requires one secret, this will be a json object containing the client ID, the client secret, the tenant ID and the subscription ID. Using the IDs that you made a note of, construct a json object that looks like this:

{
  "clientId": "1356e546-581c-4467-b41a-1918c34502ee",
  "clientSecret": "rar8Q~aE~ZYzBvDLAPRhfBAwhoZh6QkE5xxdfafg",
  "tenantId": "0254d59d-89d5-41c7-9e33-11098d2e624e",
  "subscriptionId": "ef95fb65-0da2-446c-ae17-827ce305e304"
}

Navigate to your repository and click on the settings tab, find actions under secrets and variables, and click on New repository secret.

Creating a new secret in Github

Give the secret a name, for example AZURE_CREDENTIALS. Paste in the json object and click Add secret. Repeat this for the service principal with federated credentials, creating three secrets as follows:

  • AZURE_CLIENT_ID which will contain the client ID from the github-actions-with-federated-credential service principal.
  • AZURE_TENANT_ID which will contain the tenant ID from the github-actions-with-federated-credential service principal.
  • AZURE_SUBSCRIPTION_ID which will contain the same subscription ID as used above.
Creating a new secret in Github

Once complete you should have a list of secrets that look like this:

Four secrets listed AZURE_CLIENT_ID, AZURE_CREDENTIALS, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID

Now we are ready to set up a workflow and authenticate with Azure!

Create a workflow

For this demo I am going to create two simple workflows that authenticate with Azure and list the resource groups in a subscription. This is a basic example to demonstrate the authentication and permissions are working. The first workflow will use the service principal with secrets and the second will use the service principal with federated credentials.

I have created a new repository for these demos, you can find that here .

Workflows are defined in a .yml file in the .github/workflows directory of your repository. I have created two workflows, one called with-secret.yml and one called with-federated-credential.yml. I won’t cover all aspects of a github workflow in this post, but I will show you the steps that are relevant to authenticating with Azure. The steps are defined in the jobs section of the workflow file and look like this:

steps:
  - name: Connect to Azure
    uses: azure/login@v1
    with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}
        enable-AzPSSession: true
  - name: List Resource Groups
    uses: azure/powershell@v1
    with:
      azPSVersion: latest
      inlineScript: |
        Get-AzResourceGroup | ft        

The first step is called Connect to Azure, it uses the azure/login action to authenticate with Azure. We are passing two inputs to this action, the first is the secret that we created earlier and the second is to enable a PowerShell session. This is required because we are going to use the azure/powershell action to list the resource groups in the subscription.

The second step is called List Resource Groups, it uses the azure/powershell action to run a PowerShell script that lists the resource groups in the subscription.

The second workflow is almost identical, the only difference is that we will replace the creds input with individual inputs for the respective secrets as you can see below:

steps:
  - name: Connect to Azure
    uses: azure/login@v1
    with:
      client-id: ${{ secrets.AZURE_CLIENT_ID }}
      tenant-id: ${{ secrets.AZURE_TENANT_ID }}
      subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      enable-AzPSSession: true
  - name: List Resource Groups
    uses: azure/powershell@v1
    with:
      azPSVersion: latest
      inlineScript: |
        Get-AzResourceGroup | ft        

Each secret we created earlier is mapped to an input in the azure/login action.

Run the workflows

I have set up the workflows to auto-run when changes are made to their respective files, so pushing these changes to the repository will trigger the workflows. The workflows will run and you can see the output in the actions tab of the repository.

The output of the workflow in the actions tab of the repository

Drilling into both workflows, you can see that they have both authenticated with Azure using their respective authentication methods:

The output of the workflow in the actions tab of the repository
The output of the workflow in the actions tab of the repository

Finally, you can see that both workflows have listed the resource groups in the subscription:

The output of the workflow in the actions tab of the repository

Next steps

This is a basic example to demonstrate the authentication and permissions are working. In a real world scenario you would want to use a service principal with federated credentials to authenticate with Azure from Github Actions. From here, you can extend the workflows to interact with other Azure resources, for example deploying resources, running scripts, or interacting with data services. This will require you to assign service principals to roles in Azure to grant access to the resources you want to interact with. You can also set up alternative federated credentials for different repositories, or different scenarios, to extend the scope of your workflows.

In future posts I will explore how to use Github Actions to interact with other Azure resources. I will also cover how to do similar tasks in Azure DevOps.

#mtfbwy



Recent Posts

How to Search for a Lost File in the Git Log

How to Search for a Lost File in the Git Log

  • 2024-04-27
  • 4 minutes to read

I have lost a file in my Git repository. How can I find it by searching the git log?

Read More
No Such Shell Function 'Zle Line Init' in Zsh

No Such Shell Function 'Zle Line Init' in Zsh

  • 2024-04-25
  • 3 minutes to read

Troubleshooting the error message "no such shell function 'zle line init'" in zsh when using OhMyPosh.

Read More
Getting Started With Python in Vscode

Getting Started With Python in Vscode

  • 2024-04-05
  • 2 minutes to read

This post will help you get started with Python in Vscode and identify some of the useful extensions to install.

Read More