在使用 Azure 的 terraform 中,是否可以创建密钥保管库机密并在同一 运行 的同一文件中引用该机密?

In terraform using Azure, is it possible to create a key vault secret and reference that secret in the same file on the same run?

我正在尝试生成随机用户名和密码,将它们存储在密钥保管库中,然后立即(在存储后)检索它们并将它们用作 sql 服务器创建中的变量。

考虑这段代码:

resource "random_string" "username" {
  length = 24
  special = true
  override_special = "%@!"
}

resource "random_password" "password" {
  length = 24
  special = true
  override_special = "%@!"
}

# # Create KeyVault Secret
resource "azurerm_key_vault_secret" "sql-1-username" {
  name         = "sql-server-1-username"
  value        = random_string.username.result
  key_vault_id = azurerm_key_vault.key_vault.id
  tags = merge(local.common_tags, tomap({"type" = "key-vault-secret-username"}), tomap({"resource" = azurerm_mssql_server.sql-server_1.name}))
  depends_on = [azurerm_key_vault.key_vault]
}

resource "azurerm_key_vault_secret" "sql-1-password" {
  name         = "sql-server-1-password"
  value        = random_password.password.result
  key_vault_id = azurerm_key_vault.key_vault.id
  tags = merge(local.common_tags, tomap({"type" = "key-vault-secret-password"}), tomap({"resource" = azurerm_mssql_server.sql-server_1.name}))
  depends_on = [azurerm_key_vault.key_vault]
}

data "azurerm_key_vault_secret" "sql-server-1-username" {
  name = "sql-server-1-username"
  key_vault_id = azurerm_key_vault.key_vault.id
}

data "azurerm_key_vault_secret" "sql-server-1-password" {
  name = "sql-server-1-password"
  key_vault_id = azurerm_key_vault.key_vault.id
}

resource "azurerm_mssql_server" "sql-server_1" {
  name = "${local.resource-name-prefix}-sql-server-1"
  resource_group_name = local.resource-group-name
  location            = var.resource-location
  version                      = "12.0"
  administrator_login          = data.azurerm_key_vault_secret.sql-server-1-username.value
  administrator_login_password = data.azurerm_key_vault_secret.sql-server-1-password.value
  tags = merge(local.common_tags, tomap({"type" = "mssql-server"}))
}

当 运行通过 terraform 进行此操作时,我得到:

│ Error: KeyVault Secret "sql-server-1-username" <<<KEY VAULT>>> does not exist
│ 
│   with data.azurerm_key_vault_secret.sql-server-1-username,
│   on sql-server.tf line 31, in data "azurerm_key_vault_secret" "sql-server-1-username":
│   31: data "azurerm_key_vault_secret" "sql-server-1-username" {
│ 
╵
╷
│ Error: KeyVault Secret "sql-server-1-password" <<<KEY VAULT>>> does not exist
│ 
│   with data.azurerm_key_vault_secret.sql-server-1-password,
│   on sql-server.tf line 36, in data "azurerm_key_vault_secret" "sql-server-1-password":
│   36: data "azurerm_key_vault_secret" "sql-server-1-password" {
│ 

我理解,因为在 运行 时间 Terraform 正在尝试评估该秘密,但尚未创建。

我的问题是,有没有办法定义一个值,将其存储为密钥保管库机密,然后在 azurerm_key_vault_secret 资源完成后检索该值?

作为解决方法,我在密钥保管库秘密资源和 sql 服务器上为用户名和密码值放置了带有 ignore_change 的生命周期块。 应该 在密钥保管库中为我提供与 sql 服务器的 username/password 相同的值,但这感觉像是错误的解决方案。

更好的方法是什么?

azurerm_mssql_server 中使用 data.azurerm_key_vault_secret.* 时,它不考虑依赖性,因此没有创建 keyvault secret 它首先创建 sqlserver 因为它对文件创建的资源没有任何依赖性,这就是您收到错误的原因。

对于解决方案,如果您在同一文件中创建 keyvault secret,则不要使用 数据块,可以直接引用administrator_loginadministrator_login_passwordazurerm_key_vault_secret.sql-1-username.valueazurerm_key_vault_secret.sql-1-password.value.

您的代码如下所示:

resource "random_string" "username" {
  length = 24
  special = true
  override_special = "%@!"
}

resource "random_password" "password" {
  length = 24
  special = true
  override_special = "%@!"
}

# # Create KeyVault Secret
resource "azurerm_key_vault_secret" "sql-1-username" {
  name         = "sql-server-1-username"
  value        = random_string.username.result
  key_vault_id = azurerm_key_vault.key_vault.id
  tags = merge(local.common_tags, tomap({"type" = "key-vault-secret-username"}), tomap({"resource" = azurerm_mssql_server.sql-server_1.name}))
  depends_on = [azurerm_key_vault.key_vault]
}

resource "azurerm_key_vault_secret" "sql-1-password" {
  name         = "sql-server-1-password"
  value        = random_password.password.result
  key_vault_id = azurerm_key_vault.key_vault.id
  tags = merge(local.common_tags, tomap({"type" = "key-vault-secret-password"}), tomap({"resource" = azurerm_mssql_server.sql-server_1.name}))
  depends_on = [azurerm_key_vault_secret.sql-1-username]
}


resource "azurerm_mssql_server" "sql-server_1" {
  name = "${local.resource-name-prefix}-sql-server-1"
  resource_group_name = local.resource-group-name
  location            = var.resource-location
  version                      = "12.0"
  administrator_login          = azurerm_key_vault_secret.sql-1-username.value
  administrator_login_password = azurerm_key_vault_secret.sql-1-password.value
  tags = merge(local.common_tags, tomap({"type" = "mssql-server"}))
  depends_on = [azurerm_key_vault_secret.sql-1-password]
}