We’re excited to share some current updates that enhance the expertise of utilizing Workload identification federation (OpenID Join) with Azure DevOps and Terraform on Microsoft Azure.
Many working elements have come collectively to make this attainable and we’ll share these right here.
We’re additionally more than happy to announce model 5 of the Microsoft DevLabs Terraform Process, which helps ID Token refresh by default.
What’s ID Token Refresh?
Workload identification federation requires an ID Token issued from the identification supplier, in our case Azure DevOps. This ID Token has a brief lifespan of ~5 minutes by design. It’s instantly exchanged for an entry token, which has an extended lifespan and is used to authenticate to Microsoft Azure. You may learn extra right here.
Nevertheless, there are a lot of circumstances the place you possibly can have breaks or lengthy operating jobs which will have to request a brand new entry token. On this state of affairs a brand new ID Token is required because the outdated one may have expired and can’t be used. ID Token Refresh is the aptitude of the operating activity to request a brand new ID Token and trade it for an entry token when it is aware of the earlier token has expired.
An error you may even see when a token instances out with out ID Token Refresh is AADSTS700024: Shopper assertion will not be inside its legitimate time vary
.
An instance state of affairs is operating Terraform init utilizing CLI args for the backend. These would get cached within the plan file after which if there’s a delay in approving the apply, it will lead to a timeout error because the ID Token was cached within the plan file. Terraform check for integration testing is one other state of affairs the place you’ll traditionally see token time outs.
You may learn extra concerning the SDK implementation right here.
What has modified to assist ID Token Refresh?
In Terraform, the supplier is answerable for the authentication to Azure. As such it’s the suppliers duty to refresh credentials when it wants them. Subsequently each Azure supplier needed to be up to date to assist ID Token Refresh. This contains the next suppliers:
There’s additionally the azurerm backend for distant state, which is a part of the core Terraform CLI, which additionally wanted to be up to date to assist ID Token Refresh.
Asserting Microsoft DevLabs Terraform Process Model 5
We’re more than happy to announce a brand new model of the Terraform Duties that makes use of ID Token Refresh by default when working with a Workload identification federation service connection. This activity abstracts away the necessity so that you can perceive the settings, however we share these later within the article. You could find the up to date activity right here.
We’ve additionally up to date the documentation for the duty with YAML primarily based examples.
Right here is an instance of utilizing the brand new activity with ID Token Refresh:
- activity: TerraformTask@5
displayName: Run Terraform Init
inputs:
supplier: 'azurerm'
command: 'init'
backendServiceArm: 'your-service-connection'
backendAzureRmStorageAccountName: 'your-stg-name'
backendAzureRmContainerName: 'your-container-name'
backendAzureRmKey: 'state.tfstate'
- activity: TerraformTask@5
identify: terraformPlan
displayName: Run Terraform Plan
inputs:
supplier: 'azurerm'
command: 'plan'
commandOptions: '-out tfplan'
environmentServiceNameAzureRM: 'your-service-connection'
# Solely runs if the 'terraformPlan' activity has detected adjustments the in state.
- activity: TerraformTask@5
displayName: Run Terraform Apply
situation: and(succeeded(), eq(variables['terraformPlan.changesPresent'], 'true'))
inputs:
supplier: 'azurerm'
command: 'apply'
commandOptions: 'tfplan'
environmentServiceNameAzureRM: 'your-service-connection'
How is ID Token Refresh configured?
This part covers utilizing ID Token Refresh with the Azure CLI activity in case you aren’t utilizing the Microsoft DevLabs Terraform activity.
There are three settings with widespread surroundings variables carried out throughout the suppliers and backend which are required:
ARM_OIDC_AZURE_SERVICE_CONNECTION_ID
: The service connection IDARM_OIDC_REQUEST_URL
: The API endpoint used to request the ID Token (this makes use ofSYSTEM_OIDCREQUESTURI
by default)ARM_OIDC_REQUEST_TOKEN
: The token used to request the ID Token (that is the System.AccessToken in Azure DevOps)
ARM_OIDC_AZURE_SERVICE_CONNECTION_ID
Every of the suppliers and the backend now assist a variable for supplying the Azure DevOps Service Connection ID. That is required for ID Token Refresh to know which service connection to request an ID Token for with the related topic claims.
ARM_OIDC_REQUEST_URL
Azure DevOps exposes an endpoint that enables an API name to generate an ID Token with the topic claims wanted for Workload identification federation. This endpoint makes use of the service connection context as equipped by the service connection ID. This endpoint is required for ID token refresh to request a brand new ID Token on expiry.
Azure DevOps exposes this URL in an surroundings variable known as SYSTEM_OIDCREQUESTURI
. Every of the suppliers and backend search for this surroundings variable and use it by default. This implies we don’t really want to provide ARM_OIDC_REQUEST_URL
explicitly, as you possibly can see within the instance under.
ARM_OIDC_REQUEST_TOKEN
The ID Token request URL requires authentication with a token. This token is routinely generated within the context of the Azure DevOps pipeline. The token could be discovered within the inbuilt variable known as System.AccessToken
. System.AccessToken
will not be set as an surroundings variable by default per the docs, so you should explicitly set that to the ARM_OIDC_REQUEST_TOKEN
surroundings variable.
NOTE: We plan to assist setting the surroundings variable
SYSTEM_ACCESSTOKEN
as a substitute in future iterations.
Instance utilization
Here’s a fundamental instance of configuring it with the Azure CLI activity:
- activity: AzureCLI@2
displayName: 'Terraform'
inputs:
azureSubscription: my-service-connection
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
$subscriptionId = $(az account present --query id -o tsv)
$env:ARM_TENANT_ID = $env:AZURESUBSCRIPTION_TENANT_ID
$env:ARM_SUBSCRIPTION_ID = $subscriptionId
$env:ARM_CLIENT_ID = $env:AZURESUBSCRIPTION_CLIENT_ID
$env:ARM_OIDC_AZURE_SERVICE_CONNECTION_ID = $env:AZURESUBSCRIPTION_SERVICE_CONNECTION_ID
$env:ARM_USE_OIDC = "true"
terraform init `
-backend-config="storage_account_name=my-storage-accont" `
-backend-config="container_name=my-container" `
-backend-config="key=terraform.tfstate" `
-backend-config="use_azuread_auth=true"
terraform plan -out tfplan
terraform apply tfplan
env:
ARM_OIDC_REQUEST_TOKEN: $(System.AccessToken)
For extra complete examples, see the templates in our code pattern .
What subsequent?
Please attempt it out and provides us suggestions.
We’re already engaged on some enhancements to scale back the variety of surroundings variables you should provide, however please tell us what else you’d wish to see.
Recognition
This has been an enormous effort throughout a number of groups. Particularly we’d wish to thank:
- Zhaoting Weng (Microsoft) for updating all of the suppliers and backend
- Eric van Wijk (Microsoft) and Grzegorz Gurgul (Microsoft) for steerage and updating the Azure CLI activity
- Manuel Ericstam (Solidify) for steerage and publishing the Terraform Process