【问题标题】:How can I reference a value from a different module?如何引用来自不同模块的值?
【发布时间】:2021-02-16 16:07:38
【问题描述】:

我想使用来自 AWS Secrets Manager 的密钥将 RDS 数据库部署到 AWS。我有:

├─ environments
│   └─ myenv
│       ├── main.tf
│       ├── locals.tf
│       └── variables.tf
└─ modules
    ├─ db
    │   ├── main.tf
    │   └── variables.tf
    └─ secrets
        └── main.tf

myenv/main.tf 中,我定义了一个模块mydb,其中modules/db/main.tfsource,其中定义了资源数据库。保存密码,一切正常,我在myenv 中指定块中的值和“涓滴”值。 但是对于凭证,我当然不想在myenv 中硬编码它们。 而是在modules/secrets 我定义

data "aws_secretsmanager_secret_version" "my_credentials" {
  # Fill in the name you gave to your secret
  secret_id = "my-secret-id"
}

还有另一个方块:

locals {
  decoded_secrets = jsondecode(data.aws_secretsmanager_secret_version.my_credentials.secret_string)
}

我解码了这些秘密,现在我想引用它们,例如local.decoded_secrets.usernamemyenv/main。这是我对教程的解释。但它不起作用:如果我将locals 块放入myenv,它不能引用data,当我把它放入modules/secrets 时,myenv 不能引用locals。 如何在我的myenv/main 中组合这两个模块的值?

【问题讨论】:

  • 是否有理由认为密钥需要位于单独的模块中,而不是 db 模块的一部分?这将大大简化它。
  • @ydaetskcoR 实际上有几个 db 实例,每个都有自己的秘密,所以我想我最好将关注点分离到它们自己的模块中,并从 myenv 协调。但我想我可以合并它们。
  • 您的db 模块仍然创建一个数据库,对吗?而且您不会在这些数据库之间共享秘密吗?在这种情况下,将此处的secrets 模块折叠到db 模块中似乎更干净。
  • @ydaetskcoR 我的数据库模块定义了一个单一的数据库资源并且没有秘密共享

标签: amazon-web-services terraform terraform-provider-aws terraform-aws-modules


【解决方案1】:

secrets 模块中定义一个output。在db 模块中定义一个input。将secrets 的输出值传递给db 中的输入属性。

例如,如果您在secrets 中定义了一个名为“password”的输出,在db 中定义了一个名为“password”的输入,那么在您的 db 模块声明中您将传递如下值:

module "secrets" {
  source = "../modules/secrets"
}

module "db" {
  source = "../modules/db"
  password = module.secrets.password

}

【讨论】:

  • 虽然这回答了问题,但如果您查看了问题上的 cmets,您会发现通过将秘密模块折叠到此处的数据库模块中,有一种更简单的方法,因为它们没有不需要它们单独组合。如果他们也需要其他模块的 secrets 模块,那么他们也可以将 secrets 模块称为数据库模块的子模块,并且仍然有比这更好的结果,为他们的数据库模块提供更清晰的 API。跨度>
  • @ydaetskcoR 我不认为“更好”或“更清洁”,只是不同。我的回答实际上是我在很多 Terraform 代码中看到的一种非常常见的模式。 1. 它使您可以选择在 Terraform 内部管理密码,或者通过完全在 terraform 之外的其他方式管理密码。 2. DB 密码通常需要传递给其他东西,例如将连接到数据库的应用程序,因此在 DB 模块之外需要该值是非常常见的。
  • 对于您对如何使用它们的控制较少的模块(例如 Terraform Registry 中的模块),但您正在编写自己的模块供内部使用,您可以简化界面通过让模块以您期望的方式处理事物(例如,它直接在其中创建资源或在需要外部管理它们的地方创建资源,然后您将其传递给模块使用数据源来获取 ID 的人类可读的东西)而不是让调用者每次都指定一个数据源)。在这里,OP 建议他们使用更简单的模式。
【解决方案2】:

您可以在此处使用一些选项将密钥传递给数据库模块。

您需要从现有设置中做的最小的事情是同时调用两个模块并将秘密模块的输出传递给数据库模块,如下所示:

.
├── environments
│   └── myenv
│       ├── locals.tf
│       ├── main.tf
│       └── variables.tf
└── modules
    ├── db
    │   ├── main.tf
    │   └── variables.tf
    └── secrets
        ├── main.tf
        └── outputs.tf

modules/secrets/outputs.tf

output "secret_id" {
  value = aws_secretsmanager_secret_version.secret.secret_id
}

环境/myenv/main.tf

module "secrets" {
  source = "../../modules/secrets"
  # ...
}

module "db" {
  source    = "../../modules/db"
  # ...
  secret_id = module.secrets.secret_id
}

然而,更好的方法可能是让数据库模块创建和管理自己的密钥,并且根本不需要将密钥作为参数传递到数据库模块。如果您想将 secrets 模块与其他模块一起重用,则可以将其设为数据库模块的子模块,或者如果这是您当前使用 secrets 模块的唯一地方,那么取消嵌套会使事情变得更简单。

嵌套模块

modules/db/main.tf

module "database_password_secret_id" {
  source = "../secrets"
  # ...
}

data "aws_secretsmanager_secret_version" "database_password" {
  secret_id = module.database_password_secret_id.secret_id
}

取消嵌套模块

.
├── environments
│   └── myenv
│       ├── locals.tf
│       ├── main.tf
│       └── variables.tf
└── modules
    └── db
        ├── main.tf
        ├── secrets.tf
        └── variables.tf

modules/db/secrets.tf

resource "aws_secretsmanager_secret" "database_password" {
  name = "database-password"
}

resource "random_password" "database_password" {
  length = 32
}

resource "aws_secretsmanager_secret_version" "database_password" {
  secret_id     = aws_secretsmanager_secret.example.id
  secret_string = random_password.database_password.result
}

modules/db/main.tf

resource "aws_db_instance" "database" {
  # ...
  password = aws_secretsmanager_secret_version.database_password.secret_string
}

【讨论】:

    猜你喜欢
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    • 1970-01-01
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    相关资源
    最近更新 更多