Deploying to Azure: Secure Your GitHub Workflow with OIDC


OpenID Connect (OIDC) authentication for GitHub Actions and Azure deployments is a real game-changer in the world of security. It significantly enhances security when deploying to your Azure environment. In this blog post, I’ll explain why to use OIDC, walk through setting up an Azure AD application with federated credentials using Azure CLI, and demonstrate it in action within a GitHub repository.

Table of Contents

Why use OIDC?

Let’s face it, managing secrets for cloud deployments can be a real headache. But what if I told you there’s a way to deploy to Azure without storing any long-lived secrets in your GitHub repos? Sounds too good to be true, right? Enter OIDC authentication!

OIDC authentication eliminates the need for storing long-lived cloud secrets in your GitHub repositories. Instead, it uses short-lived tokens, enhancing security and simplifying secret management (No need to remember any secrets or keep them stored securely – awesome!).

OpenID Connect (OIDC) allows your GitHub Actions workflows to access resources in Azure, without needing to store the Azure credentials as long-lived GitHub secrets. – https://docs.github.com

Setting up OIDC Authentication

Now, I know what you’re thinking. “Great, another complicated setup process.” But trust me, it’s not as daunting as it seems. Let’s break it down using Azure CLI:

1. Create a Microsoft Entra application with a service principal

# Create Azure AD application registration
az ad app create --display-name "GitHub-To-Azure-Example" --query appId -o tsv

# Store the app ID in a variable
APP_ID=$(az ad app list --display-name "GitHub-To-Azure-Example" --query [].appId -o tsv)

# Create service principal
az ad sp create --id $APP_ID

2. Configure a federated identity credential on the application

# Add OIDC federation credentials
az ad app federated-credential create \
  --id $APP_ID \
  --parameters '{
    "name": "github-oidc-branch",
    "issuer": "https://token.actions.githubusercontent.com",
    "subject": "repo:thomast1906/azure-oidc-example:ref:refs/heads/main",
    "description": "GitHub Actions OIDC - Branch Workflows (main)",
    "audiences": ["api://AzureADTokenExchange"]

The subject field can be configured in different ways:

  • For workflows triggered by pull requests: repo:/:pull-request
  • For jobs tied to an environment: repo:/:environment:
  • For jobs not tied to an environment: repo:/:ref:

A quick view in Azure, we can see the service principal and OIDC federation creation above has been successful:

Service Principal in Azure showing OIDC connection setup to GitHub

3. Assign appropriate roles to your service principal

# Create role assignment reader for Service Principal
az role assignment create --assignee $APP_ID --role Reader --scope /subscriptions/

In this example, I have provided the service principal with reader access to my Azure Subscription

GitHub Workflow example

Now that we have created the required OIDC setup in Azure, lets look at setting up the GitHub workflow

Add the required secrets

Firstly, lets get the required secret values:

1. Azure Subscription ID:

AZURE_SUBSCRIPTION_ID=$(az account show --query id -o tsv)

2. Azure Tenant ID

AZURE_TENANT_ID=$(az account show --query tenantId -o tsv)

3. Service Principal Client ID

AZURE_CLIENT_ID=$(az ad sp list --display-name "GitHub-To-Azure-Example" --query [].appId -o tsv)

After running the above commands, you can use the variables $AZURE_SUBSCRIPTION_ID, $AZURE_TENANT_ID, and $AZURE_CLIENT_ID to access the respective values

To use these values in your GitHub Actions workflow, you’ll need to add them as secrets in your GitHub repository:

  1. Go to your GitHub repository
  2. Navigate to Settings > Secrets and variables > Actions
  3. Click on “New repository secret”
  4. Add each secret separately:
    • Name: AZURE_SUBSCRIPTION_ID, Value: (output of the first command)
    • Name: AZURE_TENANT_ID, Value: (output of the second command)
    • Name: AZURE_CLIENT_ID, Value: (output of the third command)
GitHub secrets added that where created with the above Azure CLI

Example workflow

Now that the required GitHub repository secrets have been added, lets add an example workflow:

name: Example OIDC Workflow for Azure
on: [push]

permissions:
  id-token: write
  contents: read

jobs:
  login-to-azure:
    runs-on: ubuntu-latest
    steps:
      - name: 'Az CLI login'
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: 'Run az commands to verify login'
        run: |
          az account show
          az group list

This workflow does the following:

  1. Sets the necessary permissions for OIDC token generation
  2. Uses the azure/login@v2 action to authenticate
  3. Runs some basic Azure CLI commands to verify the connection

Some notes to point out from the workflow:

Permissions

permissions:
  id-token: write
  contents: read

Crucial for OIDC authentication. It’s telling GitHub that this workflow needs permission to write ID tokens (that’s the OIDC token) and read repository contents. Without these permissions, the OIDC authentication won’t work

Authentication to the service principal (using OIDC)

steps:
  - name: 'Az CLI login'
    uses: azure/login@v1
    with:
      client-id: ${{ secrets.AZURE_CLIENT_ID }}
      tenant-id: ${{ secrets.AZURE_TENANT_ID }}
      subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

Using the azure/login@v1 action to authenticate with Azure. The cool part? We’re not using any long-lived secrets here. Instead, we’re providing the client ID, tenant ID, and subscription ID as GitHub secrets

OIDC Security Considerations

When implementing OIDC, keep these security best practices in mind:

  1. Always set conditions for token issuance to prevent unauthorized access
  2. Regularly review access permissions
  3. Use the principle of least privilege when assigning roles

Implementing OIDC authentication in GitHub Actions for Azure deployments significantly enhances your security posture. It eliminates the need for long-lived secrets, simplifies credential management, and provides more granular control over authentication and authorisation

Awesome, by following the above, you will have successfully connected to your Azure subscription within a GitHub workflow using OIDC, a more secure and CI/CD pipeline

Have you tried implementing OIDC in your workflows yet? I’d love to hear about your experiences! Drop a comment below and let’s geek out together. And hey, if you found this helpful, why not share it with your dev buddies? After all, sharing is caring in the world of tech!

GitHub repository containing the above example code


Share this content:

I am a passionate blogger with extensive experience in web design. As a seasoned YouTube SEO expert, I have helped numerous creators optimize their content for maximum visibility.

Leave a Comment