jason-johnson / azure-pipelines-tasks-terraform

Azure Pipelines extension for Terraform
MIT License
121 stars 52 forks source link

Error in terraform init, while using workload identity federation in Azure DevOps. TypeError: "Cannot read property 'retrieveSecret' of undefined" #372

Closed tcostantini closed 9 months ago

tcostantini commented 9 months ago

Describe the bug Error in terraform init, while using workload identity federation in Azure DevOps. TypeError: "Cannot read property 'retrieveSecret' of undefined". Version of the TerraformCLI task, 1.0.2. Cloud provider, Azure.

To Reproduce Steps to reproduce the behavior:

  1. Create an Azure app registration
  2. Create an Azure Resource Manager service connection of type "Workload Identity federation with OpenID Connect (manual)". Note the Issuer and Subject identifier. Save it as a draft
  3. Add federated credentials to the app registered in step 1, using the Issuer and Subject identifier noted in step 3
  4. Reopen the service connection, and click on Verify and Save.
  5. Create a pipeline which uses the TerraformCLI task 1.0.2 with the "init" command

Expected behavior The init step should run without errors using the service connection

Actual behavior The init step errors out with "##[error]TypeError: Cannot read property 'retrieveSecret' of undefined". Using the usual clientid + secret service connection, the init step works (even using the same app registration).

Screenshots Error in devops:

image

Pipeline Logs logs_81148-redacted.zip

Agent Configuration

Additional context Add any other context about the problem here.

jason-johnson commented 9 months ago

@jaredfholgate is this related to your new feature or something else?

jaredfholgate commented 9 months ago

@jaredfholgate is this related to your new feature or something else?

I am unsure. Will need to try to replicate and report back.

jaredfholgate commented 9 months ago

I get the same issue, but not seeing this call in the code. I suspect this is something on the Azure DevOps side that has changed or may be a temporary issue as has been working until recently.

I see there were a lot of reports of this issue back in May: https://github.com/search?q=TypeError%3A+Cannot+read+property+%27retrieveSecret%27+of+undefined&type=issues&p=1

I will continue to take a look as time allows and report back if I find anything.

jaredfholgate commented 9 months ago

The Microsoft DevLabs task is working fine, so may be related to dependency versions or similar.

jaredfholgate commented 9 months ago

I have narrowed it down to being this getEndpointAuthorization function call:

https://github.com/microsoft/azure-pipelines-task-lib/blob/cea7412512a6980646350854731833f289553b5b/node/task.ts#L532

This is only called for Workload identity federation.

It is called via the function getSystemAccessToken: https://github.com/microsoft/azure-pipelines-tasks-common-packages/blob/71eaf44f46088bc6cfe11686f7a90024a377c740/common-npm-packages/artifacts-common/webapi.ts#L25C21-L25C45

The getSystemAccessToken function is called from getFederatedToken: https://github.com/microsoft/azure-pipelines-tasks-common-packages/blob/71eaf44f46088bc6cfe11686f7a90024a377c740/common-npm-packages/artifacts-common/webapi.ts#L44

This function getFederatedToken is called from here in the task: https://github.com/jason-johnson/azure-pipelines-tasks-terraform/blob/7763c7f8ffcff72e4b6f02361523b722040ccba3/tasks/terraform-cli/src/context/azdo-task-context.ts#L267C57-L267C57

jaredfholgate commented 9 months ago

The DevLabs task is referencing version 4.1.0 of azure-pipelines-task-lib.

This task is referencing version 3.4.0 of azure-pipelines-task-lib.

They both have the same version of azure-pipelines-tasks-artifacts-common, which is 2.225.0.

I'm wondering if updating that npm package may help to resolve it.

Both tasks are calling the same method. I am testing with the exact same pipeline with the same project, service connection, etc, just replacing the code for the task.

The relevant section of the debug logs for the DevLabs task look like this

##[debug]System.TeamProjectId=55876c40-f2c8-44ca-9144-68e109f5640e
##[debug]System.HostType=build
##[debug]System.PlanId=4a285b39-8ac7-4191-8db7-e253f115c822
##[debug]System.JobId=eaf0d931-b258-5b12-bfe1-109b8eae4e7a
##[debug]System.CollectionUri=https://dev.azure.com/jared-holgate-microsoft-demos/
##[debug]Getting credentials for local feeds
##[debug]SYSTEMVSSCONNECTION exists true
##[debug]Got auth token
##[debug]Got OIDC token

The equivalent debug logs for this task look like this

##[debug]System.TeamProjectId=55876c40-f2c8-44ca-9144-68e109f5640e
##[debug]System.HostType=build
##[debug]System.PlanId=4a2e5842-8ac7-4191-8db7-e253f115c822
##[debug]System.JobId=eaf0d931-b258-5b12-bfe1-109b8eae4e7a
##[debug]System.CollectionUri=https://dev.azure.com/jared-holgate-microsoft-demos/
##[debug]Getting credentials for local feeds
##[debug]allowTelemetryCollection=true
##[error]TypeError: Cannot read property 'retrieveSecret' of undefined

It is odd that the Vault object would be missing that function altogether, but JavaScript...

I think updating the npm package should be the first port of call and then dig deeper from there.

jason-johnson commented 9 months ago

Ok, that sounds good. How hard would it be to set up a test for this functionality? I have some of the tests turned off because the subscription I am using wouldn't be able to set up the necessary infrastructure (e.g. multiple subscriptions, management groups, etc.)

jaredfholgate commented 9 months ago

Ok, that sounds good. How hard would it be to set up a test for this functionality? I have some of the tests turned off because the subscription I am using wouldn't be able to set up the necessary infrastructure (e.g. multiple subscriptions, management groups, etc.)

Hi. I have built a new version and tested. It is working with the updated dependency.

In terms of adding a test, we can definitely do that. Will raise a separate PR for it an discuss getting access etc.

I think we should merge and release this PR ASAP in the meantime to get the functionality working .

jaredfholgate commented 9 months ago

@tcostantini Just a quick update. We have a fix for this and it has been merged, we are in the process of promoting and testing. Once it is live, I will send you another update and you can confirm that it is resolved for you. Thanks

jaredfholgate commented 9 months ago

@tcostantini The fix is now rolled out in version 1.0.3. I will close this issue for now, but please test and let me know.

tcostantini commented 9 months ago

@jaredfholgate thanks, I've tested it now, and with version 1.0.3 I'm not getting that error anymore, and it seems to go past a few steps.

However when it starts initializing the backend, I get a new error:

The backend configuration argument "oidc_token" given on the command line is not expected for the selected backend type.

, but I'm not passing the oidc_token argument.

This is the screenshot:

image

This is the command line that the logs show (with some details redacted): /agent/_work/_tool/terraform/1.2.7/x64/terraform init -backend-config=storage_account_name=<redacted> -backend-config=container_name=terraformstate -backend-config=key=dm/infra_environment_dev_oms_/001_Resource_Groups.tfstate -backend-config=resource_group_name=shared-nonprod-dm-uks-shared-rg-001 -backend-config=subscription_id=<redacted> -backend-config=tenant_id=<redacted> -backend-config=client_id=*** -backend-config=oidc_token=<redacted> -backend-config=use_oidc=true

Please note also that the token appears in plain text in that command.

I'm not sure if I'm missing something, but the pipeline and its parameters are the same as the ones I attached previously, except for the change of the task version from 1.0.2 to 1.0.3.

jaredfholgate commented 9 months ago

@jaredfholgate thanks, I've tested it now, and with version 1.0.3 I'm not getting that error anymore, and it seems to go past a few steps.

However when it starts initializing the backend, I get a new error:

The backend configuration argument "oidc_token" given on the command line is not expected for the selected backend type.

, but I'm not passing the oidc_token argument.

This is the screenshot: image

This is the command line that the logs show (with some details redacted): /agent/_work/_tool/terraform/1.2.7/x64/terraform init -backend-config=storage_account_name=<redacted> -backend-config=container_name=terraformstate -backend-config=key=dm/infra_environment_dev_oms_/001_Resource_Groups.tfstate -backend-config=resource_group_name=shared-nonprod-dm-uks-shared-rg-001 -backend-config=subscription_id=<redacted> -backend-config=tenant_id=<redacted> -backend-config=client_id=*** -backend-config=oidc_token=<redacted> -backend-config=use_oidc=true

Please note also that the token appears in plain text in that command.

I'm not sure if I'm missing something, but the pipeline and its parameters are the same as the ones I attached previously, except for the change of the task version from 1.0.2 to 1.0.3.

Which version of the azurerm provider are you using? Does it support OIDC?

jaredfholgate commented 9 months ago

Looks like it was introduced in 1.3.4.

tcostantini commented 9 months ago

Hi @jaredfholgate , you're right. I was using an older version of terraform 1.2.7 (not the azurerm provider). Testing it with version 1.5.7 it worked just fine. Thanks a lot for all your help with this!

jaredfholgate commented 9 months ago

Hi @jaredfholgate Jared Holgate FTE , you're right. I was using an older version of terraform 1.2.7 (not the azurerm provider). Testing it with version 1.5.7 it worked just fine. Thanks a lot for all your help with this!

Great, thanks for letting us know. Glad it is working for you now.