Ken Muse

Automating Azure OIDC Application Federation


I was recently asked if I knew how to automate creating Azure Entra ID (formerly Active Directory) applications. More specifically, they wanted to know if they could use PowerShell to automate creating the OIDC federation between Azure AD and GitHub. To do this, we just need to use a few PowerShell modules that save us the trouble of crafting several REST calls. These modules work with PowerShell 5.x and 7.x.

To get started, you need to install two modules:

1Install-Module Az.Accounts
2Install-Module Az.Resources

Next, you need to log in to Azure. I like to specify the subscription to use so that I can also automate any resource permissions requirements. The tenant is specified to ensure that I’m in the right Entra ID instance. To support a dev container, I’m using device authentication; that’s not required.

1Connect-AzAccount -Subscription $subscriptionId -Tenant $tenantId -UseDeviceAuthentication

I recommend always starting by looking for an existing application. If you find one, you can update it or halt processing. This ensures you don’t end up with multiple applications with the same name.

1$sp = Get-AzADServicePrincipal -DisplayName $appName
2
3if ($sp) {
4    Write-Verbose "Application '${appName}' already exists"
5    return
6}

If no principal is returned, we need to create one. When an Azure service principal is created in PowerShell, it also creates an associated application (saving us a step).

1$sp = New-AzADServicePrincipal -DisplayName $appName
2$app = Get-AzADApplication -ApplicationId $sp.AppId

Unfortunately, this process also creates a secret for the application. We’re using OIDC sign-in, so we don’t need a secret. Since I don’t need the secret, we can remove it.

1$app |  Remove-AzADAppCredential

Now, we need to define our federated credential. It will need a friendly name, $fedCredentialName, that identifies it in the Azure portal. Optionally, you can add a description, $description, to provide more details. To support GitHub, two things are required:

  • The GitHub Actions IdP must be specified as the issuer: https://token.actions.githubusercontent.com.
  • A $subject that identifies when a request from a given repository workflow should be accepted. As an example, repo:MyOrg/MyRepo:environment:dev would allow deploying to a dev environment from a workflow in the MyOrg/MyRepo repository.

We can create a Hashtable with these values, then use that to create the federated credential. Since I don’t care about the output from that step, I will pipe it to Out-Null.

 1$federatedCredential = @{
 2    Name = $fedCredentialName
 3    # Description = $description
 4    ApplicationObjectId = $app.Id
 5    Audience = @('api://AzureADTokenExchange')
 6    Issuer = 'https://token.actions.githubusercontent.com'
 7    Subject = $subject
 8}
 9
10New-AzADAppFederatedCredential @$federatedCredential | Out-Null

And that’s it. If you check the Azure portal, you’ll see the application has been created. Opening the application, you can find the federated credential definition.

Happy DevOp’ing!