terraform 后端状态文件存储使用密钥而不是 AD 帐户

terraform backend state file storage using keys instead of AD account

在持久存储到 Azure 存储帐户时,Terraform 似乎将密钥用于后端状态文件。我希望为不同的服务主体使用具有专用文件夹但没有跨文件夹写访问权限的单个存储帐户。我试图避免不同服务主体意外覆盖状态文件。但由于 Terraform 使用密钥更新存储帐户,从技术上讲,每个服务主体都有权更新每个文件。并且开发人员必须注意不要意外引用错误的状态文件进行更新。关于如何防止这种情况的任何想法?

您可以使用为容器生成的 SAS 令牌,仅供该服务主体使用,而不供其他服务主体使用。

我用下面的东西测试过:

data "terraform_remote_state" "foo" {
  backend = "azurerm"
  config = {
    storage_account_name = "cloudshellansuman"
    container_name       = "test"
    key                  = "prod.terraform.tfstate"
   sas_token = "sp=racwdl&st=2021-09-28T05:49:01Z&se=2023-04-01T13:49:01Z&sv=2020-08-04&sr=c&sig=O87nHO01sPxxxxxxxxxxxxxsyQGQGLSYzlp6F8%3D"

  }
}
provider "azurerm" {
  features {}
  use_msi = true
  subscription_id = "948d4068-xxxxx-xxxxxx-xxxxxxxxxx"
  tenant_id = "72f988bf-xxxx-xxxxx-xxxxxx-xxxxxxx"
}

resource "azurerm_resource_group" "test" {
    name="xterraformtest12345"
    location ="east us"
}

但是,如果我将容器名称更改为另一个容器,那么我将无法写入,因为它会错误提示身份验证失败,因为 SAS 令牌是针对 Test 容器而不是 Test1 容器。

有关如何为容器生成 SAS 令牌以及如何为 terraform 设置后端 azurerm 的更多信息,请参考以下链接:

Generate shared access signature (SAS) token for containers and blobs with Azure portal. | Microsoft Docs

Use Azure storage for Terraform remote state


在将 storage blob data contributor/owner 角色分配给将使用该特定容器的服务主体后,您可以将容器身份验证方法设置为 azure ad user account

然后你可以使用如下的东西:

data "terraform_remote_state" "foo" {
  backend = "azurerm"
  config = {
    storage_account_name = "cloudshellansuman"
    container_name       = "test1"
    key                  = "prod.terraform.tfstate"
    subscription_id = "b83c1ed3-xxxx-xxxxxx-xxxxxxx"
    tenant_id = "72f988bf-xxx-xxx-xxx-xxx-xxxxxx"
    client_id = "f6a2f33d-xxxx-xxxx-xxx-xxxxx"
    client_secret = "y5L7Q~oiMOoGCxm7fK~xxxxxxxxxxxxxxxxx"
    use_azuread_auth =true
  }
}

provider "azurerm"{
    subscription_id = "b83c1ed3-xxxx-xxxxxx-xxxxxxx"
    tenant_id = "72f988bf-xxx-xxx-xxx-xxx-xxxxxx"
    client_id = "f6a2f33d-xxxx-xxxx-xxx-xxxxx"
    client_secret = "y5L7Q~oiMOoGCxm7fK~xxxxxxxxxxxxxxxxx"
    features {}
}

data "azurerm_resource_group" "test" {
    name="resourcegroupname"
}

resource "azurerm_virtual_network" "example" {
  name                = "example-network"
  resource_group_name = data.azurerm_resource_group.test.name
  location            = data.azurerm_resource_group.test.location
  address_space       = ["10.254.0.0/16"]
}

输出:

如果服务主体没有为容器分配角色,则会出现如下错误:

注意:对于第一个场景,我使用了托管系统标识,但服务主体也可以实现同样的效果。