Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend/azure: subscription_id infer from Azure CLI & a way to skip *unnecessary* management plane API call #36623

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

magodo
Copy link
Contributor

@magodo magodo commented Mar 4, 2025

This PR consists of two changes:

  1. Infer subscription_id from Azure CLI if not specified. The subscription_id is required since terraform-provider-azurerm v4 (see: provider: make subscription_id a required provider property in v4.0 terraform-provider-azurerm#26621). My last PR Backend/azure/update to latest sdks #36258 aligns this with the azurerm provider, whilst causing breaking changes unfortunately.

    The commit 0c57798 chooses to fallback to the Azure CLI default subscription, only if the user is using CLI to authenticate.

    If the maintainer accepts breaking change and is fine to align with the azurerm behavior, I'll revert the above commit and mark subscription_id as required.

  2. Avoid management plane call if not necessary.

    There are four auth scenarios of the blob/container:

    1. User specifies the SAS token
    2. User specifies the shared access key
    3. User specified to use AAD auth (and credential provided)
    4. None of the above, management plane API call needed to list the shared access key and use it to auth

    For 1, 2 and 3, the management plane API can be skipped in most of the cases, except the target storage account is using private DNS zone endpoint. The blob/container data plane client requires the user to specify the base URI, which is not deterministic if the storage account opt in the private DNS zone endpoint. In this case, an additional management plane GET is required against the storage account, to retrieve the blob endpoint. While if private DNS zone endpoint is not used, the base URI can be composed in a fixed pattern, with the storage account name and container&blob name. Hence no management plane API call is needed.

    The user is expected to use the subscription_id and resource_group_name to indicate the above intent: Only if both are specified, the additional GET call will be invoked to get the accurate blob endpoint.

    (NOTE: the subscription_id can be inferred from the Azure CLI if unspecified)

Fixes #36596
Fixes #36595

Target Release

1.11.1

Test

Unit Test

$ TF_ACC=1 go test -timeout=20h -parallel=20 ./...
PASS
ok      github.com/hashicorp/terraform/internal/backend/remote-state/azure      217.074s

Scenario Test

The following test is done locally, with an empty terraform state stored in a storage blob. The goal is to test that the management plane APIs are called as expected.

SAS auth without resource_group_name specified

Expect no management plane API.

terraform {
  backend "azurerm" {
    storage_account_name = "acctesttfstate"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
    sas_token            = "****"
  }
}
💤  httptap -- ~/go/bin/terraform plan
╷
│ Warning: Provider development overrides are in effect
│
│ The following provider development overrides are set in the CLI configuration:
│  - magodo/restful in /home/magodo/go/bin
│  - magodo/demo in /home/magodo/go/bin
│  - hashicorp/azurerm in /home/magodo/go/bin
│
│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
╵
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (181 bytes)
Acquiring state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 201 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (181 bytes)

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
Releasing state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)

SAS auth with resource_group_name specified

Expect management plane API.

terraform {
  backend "azurerm" {
    resource_group_name  = "acctest-tfstate"
    storage_account_name = "acctesttfstate"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
    sas_token            = "****"
  }
}
💤  httptap -- ~/go/bin/terraform plan
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> GET https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate?api-version=2023-01-01
<--- 200 https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate?api-version=2023-01-01 (1733 bytes)
╷
│ Warning: Provider development overrides are in effect
│
│ The following provider development overrides are set in the CLI configuration:
│  - hashicorp/azurerm in /home/magodo/go/bin
│  - magodo/restful in /home/magodo/go/bin
│  - magodo/demo in /home/magodo/go/bin
│
│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
╵
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (181 bytes)
Acquiring state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 201 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (181 bytes)

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Releasing state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=****
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease&sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2025-03-04T14:48:43Z&st=2025-03-04T06:48:43Z&spr=https&sig=**** (0 bytes)

Shared access key auth without resource_group_name specified

Expect no management plane API.

terraform {
  backend "azurerm" {
    storage_account_name = "acctesttfstate"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
    access_key           = "****"
  }
}
💤  httptap -- ~/go/bin/terraform plan
╷
│ Warning: Provider development overrides are in effect
│
│ The following provider development overrides are set in the CLI configuration:
│  - hashicorp/azurerm in /home/magodo/go/bin
│  - magodo/restful in /home/magodo/go/bin
│  - magodo/demo in /home/magodo/go/bin
│
│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
╵
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
Acquiring state lock. This may take a few moments...
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 201 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Releasing state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)

Shared access key auth with resource_group_name specified

Expect management plane API.

terraform {
  backend "azurerm" {
    resource_group_name  = "acctest-tfstate"
    storage_account_name = "acctesttfstate"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
    access_key           = "****"
  }
}
💤  httptap -- ~/go/bin/terraform plan
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> GET https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate?api-version=2023-01-01
<--- 200 https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate?api-version=2023-01-01 (1733 bytes)
╷
│ Warning: Provider development overrides are in effect
│
│ The following provider development overrides are set in the CLI configuration:
│  - hashicorp/azurerm in /home/magodo/go/bin
│  - magodo/restful in /home/magodo/go/bin
│  - magodo/demo in /home/magodo/go/bin
│
│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
╵
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
Acquiring state lock. This may take a few moments...
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 201 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Releasing state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)

AAD auth with CLI without resource_group_name specified

Expect no management plane API.

terraform {
  backend "azurerm" {
    storage_account_name = "acctesttfstate"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
    use_azuread_auth     = true
  }
}
$  httptap ~/go/bin/terraform plan
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)
Acquiring state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 201 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
Releasing state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)

AAD auth with CLI with resource_group_name specified

Expect management plane API.

terraform {
  backend "azurerm" {
    resource_group_name  = "acctest-tfstate"
    storage_account_name = "acctesttfstate"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
    use_azuread_auth     = true
  }
}
💤  httptap -- ~/go/bin/terraform plan
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> GET https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate?api-version=2023-01-01
<--- 200 https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate?api-version=2023-01-01 (1733 bytes)
╷
│ Warning: Provider development overrides are in effect
│
│ The following provider development overrides are set in the CLI configuration:
│  - hashicorp/azurerm in /home/magodo/go/bin
│  - magodo/restful in /home/magodo/go/bin
│  - magodo/demo in /home/magodo/go/bin
│
│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
╵
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
Acquiring state lock. This may take a few moments...
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 201 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
Releasing state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)

No auth method specified, defaults to listing shared access key and use it

Expect management plane API call

terraform {
  backend "azurerm" {
    resource_group_name  = "acctest-tfstate"
    storage_account_name = "acctesttfstate"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
  }
}
💤  httptap -- ~/go/bin/terraform plan
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> POST https://dc.services.visualstudio.com/v2/track
<--- 200 https://dc.services.visualstudio.com/v2/track (62 bytes)
---> GET https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate?api-version=2023-01-01
<--- 200 https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate?api-version=2023-01-01 (1733 bytes)
╷
│ Warning: Provider development overrides are in effect
│
│ The following provider development overrides are set in the CLI configuration:
│  - magodo/restful in /home/magodo/go/bin
│  - magodo/demo in /home/magodo/go/bin
│  - hashicorp/azurerm in /home/magodo/go/bin
│
│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
╵
---> POST https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate/listKeys?%24expand=kerb&api-version=2023-01-01
<--- 200 https://management.azure.com/subscriptions/****/resourceGroups/acctest-tfstate/providers/Microsoft.Storage/storageAccounts/acctesttfstate/listKeys?%24expand=kerb&api-version=2023-01-01 (380 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
Acquiring state lock. This may take a few moments...
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 201 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> GET https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (181 bytes)

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Releasing state lock. This may take a few moments...
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> HEAD https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=metadata (0 bytes)
---> PUT https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease
<--- 200 https://acctesttfstate.blob.core.windows.net/tfstate/prod.terraform.tfstate?comp=lease (0 bytes)

CHANGELOG entry

  • This change is user-facing and I added a changelog entry.
  • This change is not user-facing.

magodo added 2 commits March 4, 2025 11:19
There are four auth scenarios of the blob/container:
1. User specifies the SAS token
2. User specifies the shared access key
3. User specified to use AAD auth (and credential provided)
4. None of the above, management plane API call needed to list the shared access key and use it to auth

For 1, 2 and 3, the management plane API can be skipped in most of the cases, except the target storage account is using private DNS zone. The blob/container data plane client requires the user to specify the base URI, which is not deterministic if the storage account opt in the private DNS zone. In this case, an additional management plane `GET` is required against the storage account, to retrieve the blob endpoint. While if private DNS zone is not used, the base URI can be composed in a fixed pattern, with the storage account name and container&blob name. Hence no management plane API call is needed.

The user is expected to use the `subscription_id` and `resource_group_name` to indicate the above intent: Only if both are specified, the additional `GET` call will be invoked to get the accurate blob endpoint.

(NOTE: the `subscription_id` can be inferred from the Azure CLI if unspecified)
@magodo magodo requested review from a team as code owners March 4, 2025 05:49
Copy link
Contributor

github-actions bot commented Mar 4, 2025

Changelog Warning

Currently this PR would target a v1.12 release. Please add a changelog entry for in the .changes/v1.12 folder, or discuss which release you'd like to target with your reviewer. If you believe this change does not need a changelog entry, please add the 'no-changelog-needed' label.

@jaredfholgate
Copy link
Contributor

jaredfholgate commented Mar 4, 2025

@magodo For clarity, where you mention private dns zone, this is the Azure DNS zone endpoints preview feature: https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview#azure-dns-zone-endpoints-preview? I believe these are public DNS zones? Just want to avoid confusion for anyone using private endpoints, which do require private dns zones, but don't require the management API call.

Further, this is still a breaking change for most users, since up until now supplying resource_group_name and subscription_id have been required.

An alternative solution here could be to have an explicit setting to look up the endpoint for those customers using the preview feature. Something like use_endpoint_lookup. That way we can avoid the breaking change altogether for now. I appreciate that resource_group_name and subscription_id are redundant in this scenario. We can update the docs to add clarity around this though and for new users, they can exclude them.

I'm only suggesting this to avoid impacting existing users when they move to 1.11. I feel that the smoother experience for them would be beneficial and the docs can help anyone using the preview feature.

I can help with the docs if you like, as I made the last major update to them.

UPDATE: To be clear, rightly or wrongly, the docs currently indicate that resource_group_name is required:

As such, the majority of people would have included that in their backend config (even if it isn't really required). The breaking change here would be that including resource_group_name now requires an elevated permission on the storage account.

If we can revert to the previous behaviour (where I am guessing it just ignores resource_group_name in this scenario), but add a new setting to enable users of Azure DNS zone endpoints, that would be preferential.

@rlaveycal
Copy link

The starting point for this PR should be the behaviour as per 1.10

i.e. Neither subscription id nor resource group are mandatory.

Managed Identity Principal mode (use_msi = true) does not require subscription id and does not require Azure CLI. It is not covered by your tests

terraform {
  backend "azurerm" {
    storage_account_name = "acctesttfstate"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
    use_azuread_auth     = true
    use_msi              = true
  }
}

OIDC auth can work in the same way (use_oidc = true)

We need a 1.11.1 that reverts the breaking change ASAP. Any new functionality can wait until a properly tested 1.12.

@magodo
Copy link
Contributor Author

magodo commented Mar 5, 2025

@magodo For clarity, where you mention private dns zone, this is the Azure DNS zone endpoints preview feature: https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview#azure-dns-zone-endpoints-preview?

You are right, sorry for the wrong wording... I've updated the description of this PR.

Further, this is still a breaking change for most users, since up until now supplying resource_group_name and subscription_id have been required.
...

Unfortunately, the backend document seems not correct in some places. E.g. even When authenticating using a Managed Identity (MSI), the resource_group_name can be unspecified if the SA is authenticating via AAD. The cause of the confusion comes from the fact that there are two layers of authentication: AuthN for ARM/Storage access token, and AuthN for storage account data plane access (incl. access key, SAS and AAD auth).

Regarding the use_endpoint_lookup, I'm hesitate to compliate the matters as the resource_group_name in those cases are redundent to specify. This is more of a undefined/incorrectly defined behavior before, and is out of the scope for compatibility, IMO.

I'll try to summarize all the scenarios and test them out.

A basic illustration about what's going on:

image

(Again, the complexity comes from the fact that mixing AutN for different levels together)

@jaredfholgate
Copy link
Contributor

jaredfholgate commented Mar 5, 2025

@magodo For clarity, where you mention private dns zone, this is the Azure DNS zone endpoints preview feature: https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview#azure-dns-zone-endpoints-preview?

You are right, sorry for the wrong wording... I've updated the description of this PR.

Further, this is still a breaking change for most users, since up until now supplying resource_group_name and subscription_id have been required.
...

Unfortunately, the backend document seems not correct in some places. E.g. even When authenticating using a Managed Identity (MSI), the resource_group_name can be unspecified if the SA is authenticating via AAD. The cause of the confusion comes from the fact that there are two layers of authentication: AuthN for ARM/Storage access token, and AuthN for storage account data plane access (incl. access key, SAS and AAD auth).

Regarding the use_endpoint_lookup, I'm hesitate to compliate the matters as the resource_group_name in those cases are redundent to specify. This is more of a undefined/incorrectly defined behavior before, and is out of the scope for compatibility, IMO.

I'll try to summarize all the scenarios and test them out.

A basic illustration about what's going on:

image

(Again, the complexity comes from the fact that mixing AutN for different levels together)

I understand the docs are incorrect, but if we move forward with this it will impact a lot of people. I appreciate they will just need to remove resource_group_name, but for some customers that could be a significant task. Prior to this, it worked as expected with the settings per the docs. If we move forward with this, we need some way to inform users moving to 1.11.x.

Could be we add a deprecation warning in 1.11.x and then make the breaking change in 1.12.x? My suggestion is:

  • Silently fail on the management plane auth attempt, but show a deprecation warning to users telling them it will start failing in 1.12.x if they don't remove resource_group_name from the config or add the storage account read permissions.
  • Then continue with the data plane auth with the derived URI.

Further suggestions:

I appreciate it is probably too late for this, but I am personally against the inclusion or exclusion of certain parameters to determine auth methods. I think it is confusing for end users and is not transparent. This is proven by the fact that the peer reviewed docs are incorrect, even the people writing it don't know how it works... It would be much better to explicitly specify the auth method they want to use and there is precedent for that already with use_cli, use_oidc, use_azuread_auth, use_msi, etc. Adding a new one for this scenario won't make the situation any worse than it already is.

In the future I think we should consider adding an auth_type variable that takes an input string for one of the auth methods listed in this table: https://developer.hashicorp.com/terraform/language/backend/azurerm#authentication. That way there is no confusion on user intent and the code can tell the user if they are missing a required input.

@jaredfholgate
Copy link
Contributor

@magodo I have created a docs PR that is aligned with the changes as you have proposed them and would work if you decide to use the deprecation approach. I am not 100% sure these are correct, but hoping you and others can review for correctness. Here is the PR: #36641

@magodo
Copy link
Contributor Author

magodo commented Mar 5, 2025

@jaredfholgate I agree that nclusion or exclusion of certain parameters to determine different behavior is not a good choice! I'll update the code and flow to be as what it was before, especially for the SA endpoint lookup part, and silently ignore those redundent properties if users have specified.

Meanwhile, I'll add a new attribute to allow users to opt in the endpoint lookup.

@magodo
Copy link
Contributor Author

magodo commented Mar 6, 2025

A new property is introduced: lookup_blob_endpoint. When this is set to true, a GET will be called to the SA to get the exact blob endpoint. Otherwise, the endpoint is constructed in a fixed pattern, hence no storageAccounts/read is needed.

Meanwhile, I've performed the following test.

index AAD Auth Setup 1 Storage Auth Method Lookup EP Succeed or Error storageAccounts/read Needed? storageAccounts/listkeys Needed?
1 N SAS N Y N N
2 N Access Key N Y N N
3 N AAD Auth (Storage) N unable to build authorizer for Storage API - -
4 N Unspecified N unable to build authorizer for Resource Manager API - -
5 N SAS Y unable to build authorizer for Resource Manager API - -
6 N Access Key Y unable to build authorizer for Resource Manager API - -
7 N AAD Auth (Storage) Y unable to build authorizer for Storage API - -
8 N Unspecified Y unable to build authorizer for Resource Manager API - -
9 Y SAS N Y N N
10 Y Access Key N Y N N
11 Y AAD Auth (Storage) N Y N N
12 Y Unspecified N Y Y2 Y
13 Y SAS Y Y Y N
14 Y Access Key Y Y Y N
15 Y AAD Auth (Storage) Y Y Y N
16 Y Unspecified Y Y Y Y
  1. All the AAD Auth is using Azure CLI. Not setup means Azure CLI has logged out.
  2. The storageAccounts/read operation can be avoided technically, whilst it is needed to accomodate the current implemnetation (not to make the code confusing). This should be fine as the higher priviledged operation storageAccounts/listkeys is required here.

Note, when either Storage Auth Method is unspecified, or Lookup EP is set, the resource_group_name and subscription_id are required, though the subscription_id can be inferred from Azure CLI in this test setup. Therefore, the corresponding test has the resource_group_name defined.

Lastly, I've only used Azure CLI for the AAD auth method here, as the other AAD auth method shall behave the same, except the subscription_id is not inferred and additional properties might need to specifiy.

Update

I've also verified with client ID + client secret for the AAD auth.

Copy link
Member

@mbfrahry mbfrahry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @magodo, these changes look good but I think we need more testing around lookup_blob_endpoint

var err error
client.azureAdStorageAuth, err = auth.NewAuthorizerFromCredentials(ctx, *config.AuthConfig, config.AuthConfig.Environment.Storage)
if err != nil {
return nil, fmt.Errorf("unable to build authorizer for Storage API: %+v", err)
}
default:
// ARM authN is required only when no auth method is specified, which falls back to listing the access key via ARM API.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you expand what authN is? I believe it's ARM Authentication but I just want it to be clear in the comments for when we come back to this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. AuthN: Authentication, AuthZ: Authorization.

resourceManagerAuth, err := auth.NewAuthorizerFromCredentials(ctx, *config.AuthConfig, config.AuthConfig.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("unable to build authorizer for Resource Manager API: %+v", err)
// Besides, ARM authN is required to lookup the blob endpoint.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Besides, ARM authN is required to lookup the blob endpoint.
// if `config.LookupBlobEndpoint` is true, we need to authenticate with ARM to lookup the blob endpoint

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if err != nil {
return nil, fmt.Errorf("new shared key authorizer: %v", err)
default:
// Neither shared access key nor sas token specified, not using AAD auth either. Calling management plane API to get the key.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Neither shared access key nor sas token specified, not using AAD auth either. Calling management plane API to get the key.
// Neither shared access key, sas token, or AAD Auth were specified so we have to call the management plane API to get the key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if err != nil {
return nil, fmt.Errorf("new shared key authorizer: %v", err)
default:
// Neither shared access key nor sas token specified, not using AAD auth either. Calling management plane API to get the key.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Neither shared access key nor sas token specified, not using AAD auth either. Calling management plane API to get the key.
// Neither shared access key, sas token, or AAD Auth were specified so we have to call the management plane API to get the key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -49,6 +49,13 @@ func New() backend.Backend {
Description: "The blob key to use in the Storage Container.",
},

"lookup_blob_endpoint": {
Copy link
Member

@mbfrahry mbfrahry Mar 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a test for this?

I do see that other PR around docs but I think we should merge that PR into this one so we don't accidentally have conflicting information if they don't get merged at the same time

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type: schema.TypeBool,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("ARM_USE_DNS_ZONE_ENDPOINT", false),
Description: "Whether to look up the storage account blob endpoint, instead of composing the endpoint in a fixed pattern. This is necessary when the storage account uses the Azure DNS zone endpoint.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unclear on what this line means instead of composing the endpoint in a fixed pattern. I'd recommend expanding on what that means more or just removing it

Suggested change
Description: "Whether to look up the storage account blob endpoint, instead of composing the endpoint in a fixed pattern. This is necessary when the storage account uses the Azure DNS zone endpoint.",
Description: "Whether to look up the storage account blob endpoint. This is necessary when the storage account uses the Azure DNS zone endpoint.",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed. The endpoint is always needed, if not looking it up, we'll construct it using the fixed pattern: ``https://.blob.core.windows.net, which ends up with URL https://.blob.core.windows.net//` for a blob.

@magodo
Copy link
Contributor Author

magodo commented Mar 7, 2025

@mbfrahry I've added the test and passed it:

$ TF_ACC=1 go test -v -timeout=20h -parallel=20 -run='TestAccBackendAzureADAuthBasicWithBlobEndpointLookup'
=== RUN   TestAccBackendAzureADAuthBasicWithBlobEndpointLookup
=== PAUSE TestAccBackendAzureADAuthBasicWithBlobEndpointLookup
=== CONT  TestAccBackendAzureADAuthBasicWithBlobEndpointLookup
...
--- PASS: TestAccBackendAzureADAuthBasicWithBlobEndpointLookup (166.12s)
PASS
ok      github.com/hashicorp/terraform/internal/backend/remote-state/azure      166.126s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants