Generating secure passwords in Terraform can be challenging without a reliable method. The random_password resource from the Terraform Random provider solves this by creating strong, unpredictable passwords for infrastructure automation while ensuring proper security measures.
In this article, we will cover how to use random_password
for variable-length passwords, multi-user setups, secret storage, and importing existing passwords, along with key differences from random_string
.
The Terraform Random provider (random
) generates cryptographically secure pseudo-random values for use in Terraform configurations.
It provides resources like random_string
, random_id
, and random_pet
, which help create unique names, passwords, or tokens. These values persist in the Terraform state file but can be re-generated when their arguments change or when forced through lifecycle configurations.
It’s useful for creating unique resources in both production and testing environments where unique identifiers or credentials are required.
The Terraform random_password
resource, part of the Random provider, generates a secure, random password with specific length and complexity requirements. The generated value can be referenced in other resources, such as database configurations or secrets management tools, ensuring no hardcoded passwords exist in your configuration.
For example:
resource "random_password" "example" {
length = 16
special = true
upper = true
lower = true
numeric = true
override_special = "!@#%^&*"
}
output "generated_password" {
value = random_password.example.result
sensitive = true
}
The random_password
resource is declared with various parameters:
length
– Defines the number of characters in the passwordspecial
– Boolean flag to include special charactersupper
– Boolean flag to include uppercase letterslower
– Boolean flag to include lowercase lettersnumeric
– Boolean flag to include numbersoverride_special
– Custom set of special characters
Always mark the result of random_password
as sensitive = true
in any output or resource attribute that uses it. However, note that while this hides the value from Terraform CLI output, the password is still stored in plain text in the Terraform state file. To enhance security, consider using remote state storage with encryption, such as AWS S3 with server-side encryption enabled. (Learn more: Terraform security best practices)
Terraform requires the random
provider to use the random_password
resource.
resource "random_password" "secure_password" {
length = 20
special = false
upper = true
lower = true
numeric = true
}
output "secure_generated_password" {
value = random_password.secure_password.result
sensitive = true
}
The parameters we used here:
length = 20
: Specifies that the password will be 20 characters longspecial = false
: Ensures that special characters (!@#$%^&*()
, etc.) are not included, making the password suitable for systems that do not support special charactersupper = true
: Ensures that uppercase letters are includedlower = true
: Ensures that lowercase letters are includednumeric = true
: Ensures that numbers are included
The output
block defines secure_generated_password
, which displays the generated password when running Terraform. However, since sensitive = true
is set, the password will not appear in the CLI output to prevent accidental exposure.
Generate a password with a variable length
You can define a variable and reference it within the random_password
resource to generate a password with a dynamically adjustable length in Terraform.
For example:
provider "random" {}
variable "password_length" {
description = "Length of the generated password"
type = number
default = 16
}
resource "random_password" "dynamic_password" {
length = var.password_length
special = true
upper = true
lower = true
numeric = true
}
output "generated_password" {
value = random_password.dynamic_password.result
sensitive = true
}
The variable "password_length"
block allows setting the password length dynamically. Here, the default value is 16
, but this can be overridden when running Terraform. Then instead of specifying a fixed length, length = var.password_length
dynamically sets the password length based on the variable.
You can specify a different password length by passing a value using the Terraform CL:
terraform apply -var="password_length=20"
Generate passwords for multiple users
To generate unique passwords for multiple users in Terraform, you can use the random_password
resource with the for_each
or count
meta-argument.
In the example below, we’ll use for_each
:
provider "random" {}
variable "users" {
description = "List of users who need passwords"
type = list(string)
default = ["alice", "bob", "charlie"]
}
resource "random_password" "user_passwords" {
for_each = toset(var.users)
length = 16
special = true
upper = true
lower = true
numeric = true
}
output "user_passwords" {
value = { for user in var.users : user => random_password.user_passwords[user].result }
sensitive = true
}
The variable “users” stores a list of usernames that require passwords. We can modify that list to add or remove users dynamically.
To ensure a unique password is generated for each user, the random_password
resource iterates over each username in var.users
(converted to a set using toset()
).
You can also use a map instead of a list to store additional user metadata.
Storing generated passwords in a secret manager
Best practice dictates that generated passwords should be stored in a secure secrets manager rather than in Terraform state files.
In the example below, we’ll use random_password
and store it in AWS Secrets Manager using the aws_secretsmanager_secret
and aws_secretsmanager_secret_version
resources.
provider "aws" {
region = "us-east-1"
}
provider "random" {}
# Generate a random password
resource "random_password" "db_password" {
length = 20
special = true
upper = true
lower = true
numeric = true
}
# Create a secret in AWS Secrets Manager
resource "aws_secretsmanager_secret" "db_secret" {
name = "my-database-password"
}
# Store the generated password in AWS Secrets Manager
resource "aws_secretsmanager_secret_version" "db_secret_value" {
secret_id = aws_secretsmanager_secret.db_secret.id
secret_string = jsonencode({
username = "admin"
password = random_password.db_password.result
})
}
output "secret_arn" {
value = aws_secretsmanager_secret.db_secret.arn
}
The provider "aws"
block configures Terraform to interact with AWS services. Terraform requires proper authentication credentials, which can be provided via environment variables (AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
) or IAM roles if running on AWS infrastructure.
Once the password is generated, Terraform creates an AWS Secrets Manager secret using the aws_secretsmanager_secret
resource. This secret acts as a container for sensitive data, allowing controlled access through IAM policies.
The actual password is then stored inside this secret using the aws_secretsmanager_secret_version
resource. The secret_string
field is defined using jsonencode({ username = "admin", password = random_password.db_password.result })
, which securely structures the credentials as a JSON object containing both a username and password.
To avoid exposing the password in Terraform output, only the ARN (Amazon Resource Name) of the secret is displayed using an output
block. This ARN can be used to reference the secret securely in other AWS resources, such as RDS instances or Lambda functions. The actual password can be retrieved securely using the AWS CLI command:
aws secretsmanager get-secret-value --secret-id my-database-password --query SecretString --output text
If you are using a different secrets manager, such as, HashiCorp Vault, the vault_generic_secret
resource stores the password, and the vault
provider handles authentication and retrieval.
Because random_password
generates passwords rather than managing existing ones, direct import is not possible. However, you can work around this by defining a terraform.tfvars
file or using an external data source.
Using Terraform variables
You can manually specify the password as a variable and pass it to Terraform.
variable "imported_password" {
description = "Manually imported password"
type = string
sensitive = true
}
output "imported_password_output" {
value = var.imported_password
sensitive = true
}
Save your password in a terraform.tfvars
file:
imported_password = "YourExistingSecurePassword123!"
And run Terraform with:
terraform apply -var-file="terraform.tfvars"
Using an external data source
If the password is stored externally (e.g., in AWS Secrets Manager or HashiCorp Vault), you can fetch it dynamically using a data source.
data "aws_secretsmanager_secret_version" "imported_password" {
secret_id = "my-secret-password"
}
output "retrieved_password" {
value = data.aws_secretsmanager_secret_version.imported_password.secret_string
sensitive = true
}
random_password
and random_string
are both Terraform resources provided by the random
provider. random_password
is a specialized and safer choice for password generation due to its pre-configured, more robust character set. random_string
is more versatile and used for non-sensitive unique values, such as random resource names, bucket names, or database instance identifiers.
If you do use the random_string
for passwords, be sure to configure the special, upper
, lower
, and number
arguments appropriately, and consider using override_special
to precisely define the set of special characters to include.
Using Terraform’s random_password
resource simplifies credential management by generating secure, cryptographically random passwords within infrastructure as code. It avoids hardcoded secrets, ensuring consistency and security across deployments.
However, proper state management is critical to prevent unintended password exposure. As best practice, consider:
- Storing state in an encrypted backend, such as AWS S3 with KMS encryption
- Using a secure secrets manager (AWS Secrets Manager, HashiCorp Vault) instead of exposing credentials in state files
- Leveraging IAM roles for authentication rather than static credentials
We encourage you to explore how Spacelift makes it easy to work with Terraform. If you need help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, instead of using a static pair on your local machine, Spacelift is a fantastic tool for this.
If you want to learn more about Spacelift, create a free account today or book a demo with one of our engineers.
Note: New versions of Terraform are placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.
Automate Terraform Deployments with Spacelift
Automate your infrastructure provisioning, and build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization, and many more.