pulumi-azure-native
pulumi-azure-native copied to clipboard
Add support for Azure Pipelines credential
What happened?
pulumi 3.178.0 azure-native 3.4.0
We are running pulumi on Azure Pipelines using the Service Connections IdToken as ARM_OIDC_TOKEN
On long running operations we encounter the following error:
AADSTS700024: Client assertion is not within its valid time range. Current time: 2025-08-14T14:05:49.7389289Z, assertion valid from 2025-08-14T13:30:53.0000000Z, expiry time of assertion 2025-08-14T13:40:53.0000000Z.
We have had this issue occur recently on our terraform pipelines as well, seems Microsoft has changed the Token Lifetime recently, however we could fix it by setting the following ENV vars:
ARM_OIDC_AZURE_SERVICE_CONNECTION_ID
ARM_OIDC_REQUEST_URL
ARM_OIDC_REQUEST_TOKEN
As per Azure Devops Terraform Task and Improve Security Posture in Service Connections our task looks like this:
- task: AzureCLI@2
env:
ARM_OIDC_REQUEST_TOKEN: $(System.AccessToken)
AZDO_ORG_SERVICE_URL: $(System.CollectionUri)
SYSTEM_TEAMPROJECTID: $(System.TeamProjectId)
inputs:
azureSubscription: SERVICECONNECTIONNAME
scriptType: "pscore"
scriptLocation: "inlineScript"
inlineScript: |
$env:ARM_USE_OIDC = "true"
$env:ARM_OIDC_AZURE_SERVICE_CONNECTION_ID = $env:AZURESUBSCRIPTION_SERVICE_CONNECTION_ID
$env:ARM_OIDC_REQUEST_URL=$env:SYSTEM_OIDCREQUESTURI
$env:ARM_CLIENT_ID = $env:AZURESUBSCRIPTION_CLIENT_ID
$env:ARM_SUBSCRIPTION_ID=$(az account show --query id -o tsv)
$env:ARM_TENANT_ID = $env:AZURESUBSCRIPTION_TENANT_ID
terraform apply
displayName: Terraform Apply
Replicating this to pulumi azure-native is not possible, as the required ENV Vars are not supported.
Creating a workaround by using ${SYSTEM_OIDCREQUESTURI}?api-version=7.1&serviceConnectionId=${AZURESUBSCRIPTION_SERVICE_CONNECTION_ID} and feeding it into ARM_OIDC_REQUEST_URL does not work
as this auth_azidentity uses the Get Method which is probably Github related and
Azure Pipelines expects it to be Post Method as found here
The relevant go documentation on the AzurePipelinesCredential can be found here
Example
So I don't have a particular example on this, it mainly happens on long running pipeline operations. The only particular difference that we have established so far is that we are calling an additional provider azure-native config for a different subscription creating DNS Records in our hub subscription. It may be the case that the pulumi provider only initializes the additional provider config using the original idToken which is shortlived.
Output of pulumi about
pulumi 3.178.0 azure-native 3.4.0
Additional context
We would like to continue using OIDC based authentication as we have streamlined our pipelines to not use any secrets, so if you have additional workaround we would highly appreciate it.
Contributing
Vote on this issue by adding a 👍 reaction. To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).
Hi @AndreasMWalter, good news! I believe this is in progress here https://github.com/pulumi/pulumi-azure-native/pull/4242
Unfortunately #4242 will not address this issue, which I read as a feature request for the Azure DevOps Pipeline OIDC authentication method, akin to this:
- https://github.com/hashicorp/go-azure-sdk/pull/1139
- https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_oidc
@AndreasMWalter a new release of azure-native (3.8) is out with support for a new mode called DefaultAzureCredential. https://www.pulumi.com/blog/azure-native-defaultazurecredential-and-private-cloud/
I'm wondering whether DefaultAzureCredential would be effective here.
@AndreasMWalter a new release of azure-native (3.8) is out with support for a new mode called DefaultAzureCredential. https://www.pulumi.com/blog/azure-native-defaultazurecredential-and-private-cloud/
I'm wondering whether DefaultAzureCredential would be effective here.
I cannot check this before September 15th, however I don't believe so as DefaultAzureCredential only has a limited subset of credentials it uses in a specific order
@AndreasMWalter I believe that the WorkloadIdentityCredential will activate in the Pipelines environment.
Ahoi, we are trying do a quick test this week, I will report back
@EronWright
I'm wondering whether DefaultAzureCredential would be effective here.
AFAICT this cannot possibly work. There is no path in the SDK code leading from DefaultAzureCredential to AzurePipelineCredential, which is the piece of code that provides support for OIDC request URLs. WorkloadIdentityCredential in particular only looks at AZURE_FEDERATED_TOKEN_FILE.
If I may make a suggestion regarding how to fix the present issue:
- Add support for the azure-sdk-for-go's AzurePipelinesCredential, similarly to https://github.com/go-acme/lego/issues/2620 , and expose it through some
useAzurePipelinesCredentialconfig option. - Rename the existing
useOidcoption to something likeuseGithubOidc, since it is Github-specific and very confusing otherwise. Alternatively, add a new parameteroidcProvider: "github" | "azdo" | …to make choosing the OIDC provider explicit, or at the very least document thatuseOidcis meant exclusively for Github.
Note that AzurePipelinesCredential does some non-trivial things like appending additional Azure-specific parameters to the OIDC request URL, including the service connection ID provided by the user and an oidcAPIVersion, and – as mentioned before – setting the HTTP method to POST. Similarly, the current implementation for Github does other non-trivial things, like using HTTP GET and setting various headers.
So a generic OIDC authentication method likely won't be possible unless one wants to leave it to the user to configure all those knobs correctly. It'd probably make more sense to follow in the footsteps of go-acme/lego which uses azure-sdk-for-go's AzurePipelinesCredential (see above), and of terraform-azurerm-provider, which uses Hashicorp's go-azure-sdk's ADOPipelineOIDCAuthorizer.
Thanks @codethief. I like the idea of adding explicit support via useAzurePipelinesCredential, as this seems to be how other tools have solved it. Meanwhile, https://github.com/Azure/azure-sdk-for-go/issues/23181 tracks the upstream task of adding Azure Pipelines support to the DefaultAzureCredential.