Use GitHub Actions integrated with Azure AD via OIDC to create an Azure API Management resource instance

Akihiro Nishikawa
Microsoft Azure
Published in
6 min readMar 15, 2022

The original entry (Japanese) is here.

Previously I wrote an entry about GitHub Actions. In that entry, I used a service principal’s secret to call Azure Login action in GitHub Actions flow.

Recently OpenID Connect (OIDC) integration with Azure AD was delivered. It allows us to integrate GitHub Actions with Azure AD, so we don’t have to use a service principal’s secret. The following documents show us how to connect GitHub and Azure with OIDC.

In this article, I explore the way to create integration between Azure AD and GitHub Actions via OIDC and use GitHub Actions to create Azure API Management instances.

Steps

The following steps are required to create GitHub Actions flow. In this article, I choose the following options.

  • Azure CLI (PowerShell is okay)
  • GitHub-hosted Linux runner (Windows is okay)
  1. Create an application for GitHub Actions in Azure AD
  2. Create a service principal for the application created in #1
  3. Assign subscription-scoped Contributor role to the service principal created in #2
  4. Add federated identity credential to the application created in #1
  5. Create three secrets in GitHub Secret. Each secret stores…
    - Application ID for the application created in #1
    - Tenant ID for Azure AD
    - Azure subscription ID
  6. Use a GitHub Actions flow (Azure AD Login flow) to verify if OIDC authentication works
  7. Add ARM template(s) and related resources, or Bicep code(s) for instance provisioning to a GitHub repository
  8. Modify the GitHub Actions flow created in #6 to add a step for provisioning an API Management instance
  9. Verify the flow

1. Create an application for GitHub Actions in Azure AD

Run the following command to create an application for GitHub Actions.

az ad app create --display-name <Application Name>

Output should be similar to the following example (some attributes are masked and abbreviated). Take a note of appId and objectId.

2. Create a service principal for the application created in #1

Run the following command to create a service principal.

az ad sp create --id <appId for Application created in #1>

Output should be similar to the following example (some attributes are masked and abbreviated). Take a note of objectId (which is Object ID for just created service principal).

3. Assign subscription-scoped Contributor role to the service principal created in #2

Run the following command to assign the role to the service principal created in #2.

az role assignment create --role contributor --subscription <subscription_id> --assignee-object-id <object Id for the service principal created in #2> --assignee-principal-type ServicePrincipal

Output should be similar to the following example (some attributes are masked and abbreviated).

4. Add federated identity credential to the application created in #1

Run the following command to call REST API below. For more details, check the following URL.

As the document below mentioned, subject configuration is a little bit tricky. This is a command example using ‘repository’ and ‘branch’.

az rest --method POST --uri 'https://graph.microsoft.com/beta/applications/<ObjectId of Application created in #1>/federatedIdentityCredentials' --body '{"name":"name for federated identity information", "issuer":"https://token.actions.githubusercontent.com", "subject":"repo:<GitHub username>/<repository>:refs/heads/<branch>", "description":"<comments for federated identity credential>", "audiences":["api://AzureADTokenExchange"]}'

Output should be similar to the following example (some attributes are masked and abbreviated).

All configuration in Azure side are done! After that, let us configure some points for GitHub Actions.

5. Create three secrets in GitHub Secret

Create 3 secrets to use in GitHub Actions. Scope for these secrets can be configured in either repository level, environment level, or organization level. However, each secret’s key name is fixed and unmodifiable.

  • AZURE_CLIENT_ID (appId for Application created in #1)
  • AZURE_TENANT_ID (Azure AD tenant ID associated with a subscription)
  • AZURE_SUBSCRIPTION_ID (literally, Azure Subscription ID)

6. Use a GitHub Actions flow (Azure AD Login flow) to verify if OIDC authentication works

You can easily test OIDC authentication with the YAML mentioned in the following document.

In my environment, connection test in PowerShell takes longer than that in Azure CLI (CLI : approximately 30 sec, PowerShell : approximately 60 sec). In this evaluation, performance gap investigation is out of scope.

7. Add ARM template(s) and related resources, or Bicep code(s) for instance provisioning to a GitHub repository

API Management instance is provisioned via an ARM template, which is available via GitHub and create an instance with Managed Identity enabled.

Create an ARM template (azuredeploy.json) and a parameter file (azuredeploy.parameters.json) in a repository.

8. Modify the GitHub Actions flow created in #6 to add a step for provisioning an API Management instance

The following action is used to create an instance via the ARM template (and the parameter file). This action, made by Microsoft, is not the same as one used in last entry because I would like to override configuration(s) in the parameter file.

The following actions, Azure CLI Action and Checkout Action, are used to create a resource group used in instance provisioning phase. This operation should be done in not ARM template but flow.

Created flow is available in GitHub. $(date +%s) is used in the flow to create unique resource group name. An ARM template function , utcNow(), is only available for setting default value in parameter(s) declaration. That means using this function in the flow is not available.

The following is a sample of a parameter file (azuredeploy.parameters.json). When creating the instance with consumption tier (serverless), skuCount should be set to zero. This configuration is the same as one in previous entry.

9. Verify if the flow works

You should see the flow work fine —it creates a resource group whose name is generated with random number, and an API Management instance (consumption tier) is created in the resource group.

When checking the created API Management instance, you should see system managed identity enabled.

Appendix

Sample flow created in this entry is available via the following URL.

--

--

Akihiro Nishikawa
Microsoft Azure

Cloud Solution Architect @ Microsoft, and JJUG (Japan Java Users Group) board member. ♥Java (JVM/GraalVM) and open-source technologies. All views are my own.