0

我对 Terraform 很陌生。我正在尝试使用 sops 提供程序插件从 yaml 文件中加密秘密: Sops Provider

我需要为稍后的配置阶段创建一个 Terraform 用户对象,如下例所示:

users = [{
  name = "user123"
  password = "password12"
}]

我准备了一个 secrets.values.enc.yaml 文件来存储我的秘密数据:

yaml_users: 
  - name: user123
    password: password12

我已经使用“sops”命令加密了文件。我可以成功解密文件以进行测试。

现在我尝试使用 Terraform 中的加密文件来创建用户对象:

data "sops_file" "test-secret" {
  source_file = "secrets.values.enc.yaml"
}

# user data decryption
users = yamldecode(data.sops_file.test-secret.raw).yaml_users

不幸的是,我无法调试数据或“用户”的结构,因为 Terraform 不显示敏感数据。当我尝试在稍后的配置阶段使用该用户变量时,它似乎并不需要:

不能在 for_each 中使用一组字符串值映射。需要一个可迭代的集合。

当我对未加密的yaml 文件做同样的事情时,一切似乎都工作正常:

users = yamldecode(file("secrets.values.dec.yaml")).yaml_users

看起来 sops 提供程序解密不会创建我需要的数组或“可迭代集合”。

有谁知道如何使用 terraform sops 提供程序来解密一组键值对?像“adminpassword”这样的单个值工作正常。

4

1 回答 1

0

我认为此错误消息的“字符串映射集”部分是重要部分:for_each需要直接映射(在这种情况下,映射键成为实例标识符)或一组单独的字符串(在这种情况下,这些字符串成为实例标识符)。

您的示例 YAML 文件显示yaml_users被定义为 YAML 映射序列,它对应于转换为yamldecode.

要使用该数据结构,for_each您需要首先将其投影到一个映射中,其键将用作每个资源实例的唯一标识符。假设这些name值是适当唯一的,您可以对其进行投影,以便这些值是键:

data "sops_file" "test-secret" {
  source_file = "secrets.values.enc.yaml"
}

locals {
  users = tomap({
    for u in yamldecode(data.sops_file.test-secret.raw).yaml_users :
    u.name => u
  })
}

结果是敏感值在这里增加了额外的皱纹,因为 Terraform 不允许使用敏感值作为资源实例的标识符——这样做会导致无法在 UI 中显示资源实例地址,并且不可能在命令行上为需要它的命令描述实例。

但是,这看起来确实与我写这篇文章时函数示例中显示nonsensitive用例完全相同:您有一个当前完全标记为敏感的集合,但您知道它实际上只有一部分是敏感的所以你可以用来nonsensitive向 Terraform 解释如何将非敏感部分与敏感部分分开。locals这是我之前使用该函数的示例中块的更新版本:

locals {
  users = tomap({
    for u in yamldecode(data.sops_file.test-secret.raw).yaml_users :
    nonsensitive(u.name) => u
  })
}

如果我做出正确的假设,即只有密码是敏感的并且用户名可以公开,上面将产生一个合适的数据结构,其中用户名在键中可见,但仍会标记单个元素一样敏感。

local.users然后满足 resource 的所有期望for_each,因此您应该能够将它与您需要为每个用户系统地重复的任何其他资源一起使用。

请注意,Terraform 对敏感值的跟踪仅用于 UI 目的,不会阻止此密码作为使用它们的资源的一部分保存在状态中。如果您使用 Terraform 来管理敏感数据,那么您应该将生成的状态快照本身视为敏感工件,并注意存储它们的位置和方式。

于 2022-02-03T23:43:55.827 回答