microsoft / azure-pipelines-terraform

Azure Pipelines tasks for installing Terraform and running Terraform commands in a build or release pipeline.
MIT License
95 stars 59 forks source link

Make Documentation For YAML to Allow Backend in Sub1 and Environment In Sub2 #188

Open rruenroeng opened 9 months ago

rruenroeng commented 9 months ago

Hi there,

I've been struggling to find the correct setup that will accommodate my use-case.

My Goal To have the Terraform Backend live in a RG/Storage Account/Container/File in a different subscription than the subscription it is targeting to stand up infrastructure

Why? My company would like to keep our state files and other services that support all of our build environments consolidated in one subscription that is kept separate from the subscriptions where our infrastructure and software is being deployed for development, testing, and production.

What I've Tried So Far I'm using the latest and greatest versions of everything. Terraform/Azurerm/The Terraform Extension Tasks/etc.

Option 1 I have tried creating two service connections.

With this setup I've:

Option 2 I have tried allowing a single service connection to have pretty wide-spread privileges in the environment where it deploys resources and very limited access to the state file in a second subscription.

With this step I've:

Is there a proper way to do what I'm attempting? I have played around with the providers in my state file, but I don't think they are being respected. I am mostly convinced that what I'm trying to do isn't possible at this point.

mericstam commented 9 months ago

there seems to be a bug introduced. related to #189 I am investigating

mericstam commented 9 months ago

as you can see in #189 I do as you do in option 1 and it works for me. backend is initialized in the init step. So if you have several jobs terraform init step always has to run before plan , show, etc. The one thing I found out was you can not have two different authorization schemes. so the service connections need to be of the same type. (Service Principal, Managed Identity or Workload Identity Federation)

rruenroeng commented 9 months ago

Hi @mericstam ! Thank you for responding so quickly. Are you able to go through all of the steps using option 1? If so, what is your exact setup?

I am not using two authorization schemes among my service connections. They are all of the same type.

I'm excited to hear what you find!

deadlydog commented 8 months ago

The one thing I found out was you can not have two different authorization schemes. so the service connections need to be of the same type. (Service Principal, Managed Identity or Workload Identity Federation)

I believe we're having the same issue. We do the terraform init with an Azure DevOps service connection for Azure subscription A that uses Workload Identity Federation. The next step in the Azure Pipeline is a terraform apply step that uses a different service connection for Azure subscription B, and is setup to use an Azure Service Principal with a Client Secret. The terraform init step completes successfully, but the terraform apply fails with the following error:

Error: error loading state: Error retrieving keys for Storage Account "[TerraformStateFileStorageAccountName]": autorest/Client#Do: Preparing request failed: StatusCode=0 -- Original Error: clientCredentialsToken: received HTTP status 401 with response: {"error":"invalid_client","error_description":"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app '***'.\r\nTrace ID: 8383629a-630d-4f93-9f93-b9349c010700\r\nCorrelation ID: ec30b0d8-bc86-43a6-933f-1e1e94837cca\r\nTimestamp: 2023-10-12 22:59:42Z","error_codes":[7000215],"timestamp":"2023-10-12 22:59:42Z","trace_id":"8383629a-630d-4f93-9f93-b9349c010700","correlation_id":"ec30b0d8-bc86-43a6-933f-1e1e94837cca","error_uri":"https://login.microsoftonline/[.](https://login.microsoftonline.com/error?code=7000215%22})

This flow worked fine before converting the first service connection from using a Service Principal Client Secret to using Workload Identity Federation auth.

Any updates on this, or additional actions we can try? Thanks.

deadlydog commented 8 months ago

Just to follow up on this, we were able to convert our 2nd service connection to use Workload Identity Federation as well and that fixed this issue. So indeed the issue does look to be when the terraform init and the terraform plan/apply service connections use different authentication mechanisms; as long as they both use Service Principle Client Secrets or both use WIF then everything is fine, but you cannot use one auth mechanism with the 1st service connection and a different auth type with the 2nd service connection.

mericstam commented 8 months ago

I will check if we can support two service connections of different types, if not I will update the docs (They are outdated and due to be updated anyways)