hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.61k stars 4.65k forks source link

Azure Blob SAS token invalid #26385

Open tpcgold opened 5 months ago

tpcgold commented 5 months ago

Is there an existing issue for this?

Community Note

Terraform Version

1.13.1

AzureRM Provider Version

3.105.0

Affected Resource(s)/Data Source(s)

azurerm_storage_account_sas

Terraform Configuration Files

# Configure the Azure provider
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.105.0"
    }
    random = {
      source  = "hashicorp/random"
      version = ">=3.5.1"
    }
    azapi = {
      source  = "Azure/azapi"
      version = "1.13.1"
    }
  }

  required_version = ">= 1.1.0"
}

provider "azurerm" {
  subscription_id     = your_subscription_id
  storage_use_azuread = true
  features {}
}

resource "azurerm_resource_group" "rg" {
  location = "switzerlandnorth"
  name     = "example"
}

resource "azurerm_virtual_network" "vnet" {
  name                = "example"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "subnet" {
  name                 = "example"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.2.0/24"]
  service_endpoints    = ["Microsoft.Sql", "Microsoft.Storage"]

resource "azurerm_storage_account" "example" {
  name                     = "example"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "RAGRS"

  network_rules {
    default_action             = "Deny"
    virtual_network_subnet_ids = [azurerm_subnet.subnet.id]
    ip_rules = [
      your_ip
    ]
  }
}

resource "azapi_resource" "example" {
  type      = "Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01"
  name      = "example-container"
  parent_id = "${azurerm_storage_account.example.id}/blobServices/default"
  body = jsonencode({
    properties = {
      defaultEncryptionScope      = "$account-encryption-key"
      denyEncryptionScopeOverride = false
      metadata                    = {}
      publicAccess                = "None"
    }
  })
  depends_on = [
    azurerm_storage_account.example
  ]
}

data "azurerm_storage_account_sas" "example" {
  connection_string = azurerm_storage_account.example.primary_connection_string
  https_only        = true

  resource_types {
    service   = true
    container = true
    object    = true
  }

  services {
    blob  = true
    queue = false
    table = false
    file  = false
  }

  start  = "2024-01-01"
  expiry = "2025-01-01"

  permissions {
    read    = true
    write   = true
    delete  = true
    list    = true
    add     = true
    create  = true
    update  = true
    filter  = true
    tag     = false
    process = false
  }
}

output "example" {
  value     = "${data.azurerm_storage_account_sas.example.sas}"
  sensitive = true
}

Debug Output/Panic Output

-

Expected Behaviour

SAS Token valid

Actual Behaviour

SAS token in the output is invalid as it's not following the requirements of https://learn.microsoft.com/en-us/rest/api/storageservices/create-service-sas

one example is the signedPermissions (sp) field order is not correct as is should be in following order (accoring to https://learn.microsoft.com/en-us/rest/api/storageservices/create-service-sas#specify-permissions): racwdxltmeop but the order is mixed in the terraform output

Steps to Reproduce

terraform apply example script read output SAS token

Important Factoids

No response

References

No response

magodo commented 5 months ago

@tpcgold Could you please share the detailed error message when you use this SAS token? I checked the Portal behavior, e.g. when you are listing blobs in a container, the request is like below:

https://aacctestdt0606.blob.core.windows.net/%24logs?restype=container&comp=list&prefix=&delimiter=%2F&marker=&maxresults=30&include=metadata&sv=2022-11-02&ss=bqtf&srt=sco&sp=rwdlacuptfxiy&se=2024-06-20T17:27:57Z&sig=xxx

The sp here is not following the order you shared. Suspicously the order is enforced in an earlier sv, but relaxed since a later one.

tpcgold commented 5 months ago

the url is created like this in terraform

output "sas_url_staging" {
  value     = "${azurerm_storage_account.example.primary_blob_endpoint}${azapi_resource.example.name}${data.azurerm_storage_account_sas.example.sas}"
  sensitive = true
}

which leads to a url like: https://example.blob.core.windows.net/example-container?sv=2017-07-29&ss=b&srt=s&sp=rwdlacuf&se=2025-01-01&st=2024-01-01&spr=https&sig=<signature>

the error output of the call:

<?xml version="1.0" encoding="utf-8"?>
<Error>
    <Code>AuthenticationFailed</Code>
    <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:{uuid}
Time:{timestamp}</Message>
    <AuthenticationErrorDetail>Signature fields not well formed.</AuthenticationErrorDetail>
</Error>
magodo commented 5 months ago

@tpcgold It turns out the signed_version is too old (2017-07-29). You can explicitly set it to 2022-11-02, which shall have support for the new permissions like filter.

tpcgold commented 5 months ago

ok, I'll test with the explicit configuration. anyway, this seems to be a bug in the terraform provider script as the default seems to be 2017-07-29 🤔