I want to deploy an RDS database to AWS with a secret from AWS Secrets Manager. I have:
├─ environments
│ └─ myenv
│ ├── main.tf
│ ├── locals.tf
│ └── variables.tf
└─ modules
├─ db
│ ├── main.tf
│ └── variables.tf
└─ secrets
└── main.tf
In myenv/main.tf
I define a module mydb
that has modules/db/main.tf
as source
where a resource database is defined. Save for the password it all works, I specify values in blocks in myenv
and the values "trickle down".
But for the credentials, I don't want to hard code them in myenv
of course.
Instead in modules/secrets
I define
data "aws_secretsmanager_secret_version" "my_credentials" {
# Fill in the name you gave to your secret
secret_id = "my-secret-id"
}
and with another block:
locals {
decoded_secrets = jsondecode(data.aws_secretsmanager_secret_version.my_credentials.secret_string)
}
I decode the secrcets and now I want to reference them as e.g. local.decoded_secrets.username
in myenv/main
. That is my interpretation of the tutorials. But it doesn't work: If I put the locals
block in myenv
it cannot reference data
, and when I put it in modules/secrets
then myenv
cannot reference locals
.
How can I combine the values of these two modules in my myenv/main
?
You have a few options available to you here to pass the secret to the database module.
The smallest thing you need to do from your existing setup would be to call both modules at the same time and pass an output from the secrets module to the database module like this:
.
├── environments
│ └── myenv
│ ├── locals.tf
│ ├── main.tf
│ └── variables.tf
└── modules
├── db
│ ├── main.tf
│ └── variables.tf
└── secrets
├── main.tf
└── outputs.tf
output "secret_id" {
value = aws_secretsmanager_secret_version.secret.secret_id
}
module "secrets" {
source = "../../modules/secrets"
# ...
}
module "db" {
source = "../../modules/db"
# ...
secret_id = module.secrets.secret_id
}
A better approach however might be to have the database module create and manage its own secret and not require the secret to be passed into the database module as a parameter at all. If you wanted to reuse the secrets module with other modules then you could make it a child module of the database module or if this is the only place you currently use the secrets module then unnesting these makes things simpler.
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
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
}
resource "aws_db_instance" "database" {
# ...
password = aws_secretsmanager_secret_version.database_password.secret_string
}