azurerm terraform authentication using oidc

It is confusing trying to understand which authentication method to use in terraform especially when there's concepts like managed identity and oidc. What is the difference and how to use it? 

OIDC authentication using Azure Devops task

Abit of confusion i think - but this setup here (https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_oidc), uses what identity that your service connection configures on - it can be a managed identity and it could be an app registration. It is NOT to say, you have a k8s workload identity setup and you wanted to use that managed identity (by passing service connection)

1. Setup service connection and federate:- 

Prereq 

1. Do you need to grant project collection admin to this service account

    No you don't but you need to provide it with BASIC license access.

2. Do you need to federate it to the workload identity? 
    Yes you do - if you use Azure Devops service connection, it setup the federation automatically for you. Then if you go into the Certificate secret -> You will see this configuration in the "Federated" credential.

Setting up managed identity manual:




2. Setting up terraform 

$idToken is generated automatically as documented here and this is passed to ARM_OIDC_TOKEN.


from terraform perspective ARM_USE_OIDC = true 

Given that this step uses AzureCLI@2 - and the azureSubscription is configured to a service connection - it will use this service principal as the ID. 

If it is a batch script, then it will use the workload identity instead. 



- task: AzureCLI@2
  inputs:
    azureSubscription: $(SERVICE_CONNECTION_ID)  ### Your will be using token generated by this service principal
    scriptType: bash
    scriptLocation: "inlineScript"
    inlineScript: |

       export ARM_CLIENT_ID=$servicePrincipalId
       export ARM_SUBSCRIPTION_ID=$(az account show | jq -r '.id')
       export ARM_TENANT_ID=$(az account show | jq -r '.tenantId')

        #check the service connection using workload identity federation authentication or service principal authentication
        #if using service principal authentication, will require the servicePrincipalKey

        if [[ -z "${idToken}" ]]; then
          echo "workload identity federation token is undefined"
          export ARM_CLIENT_SECRET=$servicePrincipalKey
        else
          echo "workload identity federation token is defined"
          export ARM_USE_OIDC=true
          export ARM_OIDC_TOKEN=$idToken
        fi
       
        terraform init
        trraform plan ........
        terraform apply ......
  env:
    ARM_USE_OIDC: true




Some common question

Do you need service principal federation for this? 

No you don't 

Why account you will be using under here to create resources? 

Service connection that you created for your Azure Devops project that is specified in AzureSubscription parameters. 

I only have to provide ARM_USE_OIDC=true? 

No, not really, you still need to configure ARM_CLIENT_ID, ARM_SUBSCRIPTION and ARM_TENANT_ID as shown above. 

When is this setup or approach make sense?

In a normal context, service connection gets created with their own service principal to manage Azure resources in that specific project. So we wanted least privileged permission given and restrict that to a resource group instead of a subscription - so it cannot overwrite other Azure resources for another project.  

In the workload identity setup context, this is to say, I have a agent running in my k8s cluster that has the permission to do things in Azure and I just need to specify which agent I would like to use. So this would work if you decided to go with agent pool as the way to managed your Azure resource.













 




Comments

Catherine Lowe said…
Thanks for breaking down the OIDC vs managed identity angle—it clears up a lot of confusion I’ve seen in projects. I ran into issues when mixing service principal federation with pipeline agents, so this context really helps. Do you think organizations already invested in Azure DevOps service connections should always prefer OIDC for new setups, or are there still cases where client secrets make sense?

Popular posts from this blog

gemini cli getting file not defined error

NodeJS: Error: spawn EINVAL in window for node version 20.20 and 18.20

vllm : Failed to infer device type