
Secure Secrets Management in Terraform Part1: Leveraging AWS KMS
- z4ck404
- Aws kms , Terraform , Secure development
- November 17, 2024
Secure Secrets Management in Terraform — Part1: Leveraging AWS KMS
One of the key principles of modern Infrastructure as Code is the secure management of sensitive information. In thins first part of our series about secure secrets management in Terraform/OpenTofu, we will focus on the use of AWS Key Management Service, better known as KMS, to securely encrypt and manage secrets with Terraform/OpenTofu.
Prerequisites
- AWS Account with appropriate permissions
- Terraform/OpenTofu installed
- AWS CLI configured
AWS KMS
First, let’s create a KMS key with proper permissions and configurations:
resource "aws_kms_key" "secrets_key" {
description = "KMS key for encrypting application secrets"
deletion_window_in_days = 7
enable_key_rotation = true
}
resource "aws_kms_alias" "secrets_key_alias" {
name = "alias/awsmorocco-key"
target_key_id = aws_kms_key.secrets_key.key_id
}
resource "aws_kms_key_policy" "example" {
key_id = aws_kms_key.secrets_key.id
policy = jsonencode({
Id = "example"
Statement = [
{
Action = "kms:*"
Effect = "Allow"
Principal = {
AWS = "*"
}
Resource = "*"
Sid = "Enable IAM User Permissions"
},
]
Version = "2012-10-17"
})
}
After applying this configuration, you can find the key in the AWS Console under KMS > Customer managed keys :

Encrypting Secrets with AWS CLI
Now that we have our KMS key set up, we can use it to encrypt sensitive values using the AWS CLI:
aws kms encrypt \
--key-id alias/awsmorocco-key \
--plaintext fileb://<(echo -n "my-super-secret-password") \
--output text \
--query CiphertextBlob \
--region us-east-1
This command will output a base64-encoded encrypted string that you can safely store in your Terraform configurations
Using Encrypted Values in Terraform:
Create variables to store the encrypted values:
# variables.tf
variable "encrypted_db_password" {
description = "KMS encrypted database password"
type = string
default = "AQICAHhw31bEpV7TSsANCrrf6ZKimnQvVlNeIPn2xFDmUQPjOAGLFV0lcS4XiuwfqRIC1YI+AAAAdjB0BgkqhkiG9w0BBwagZzBlAgEAMGAGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM/MZEgbuuMwVNBHJ1AgEQgDNUMmkSJO/f1t5w5JIWLc2MmGyU4/Az5IypmMuTTShUqRArmYsyzvA/G54jekuCyip7VmA="
# the best way is to use a valuesfiles: terraform.tfvars
# encrypted_db_password = "AQICAHhw31bEpV7TSsANCrrf6ZKimnQvVlNeIPn2xFDmUQPjOAGLFV0lcS4XiuwfqRIC1YI+AAAAdjB0BgkqhkiG9w0BBwagZzBlAgEAMGAGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM/MZEgbuuMwVNBHJ1AgEQgDNUMmkSJO/f1t5w5JIWLc2MmGyU4/Az5IypmMuTTShUqRArmYsyzvA/G54jekuCyip7VmA="
}
variable "encrypted_api_key" {
type = string
default = ""
}
Create data sources to decrypt the values:
### data sources
data "aws_kms_secrets" "application_secrets" {
secret {
name = "db_password"
payload = var.encrypted_db_password
}
# You can decrypt multiple secrets in one block
# secret {
# name = "api_key"
# payload = var.encrypted_api_key
# }
}
# Access the decrypted value
locals {
db_password = data.aws_kms_secrets.application_secrets.plaintext["db_password"]
#api_key = data.aws_kms_secrets.application_secrets.plaintext["api_key"]
}
Use the decrypted values in your resources:
### Provision resources and provide the decrypted values
resource "aws_db_instance" "db" {
identifier = "awsmorocco-db"
engine = "mysql"
instance_class = "db.t3.micro"
username = "awsmorocco-admin-user-1"
password = local.db_password # Using the decrypted
parameter_group_name = "default.mysql8.0"
skip_final_snapshot = true
allocated_storage = 10
}
Best Practices for KMS Usage
1 — Key Rotation
- Enable automatic key rotation as we did in our configuration
- Consider using different keys for different environments
2 — Access Control
- Implement least-privilege access in your key policies
- Use separate keys for different applications or services
3 — Monitoring
- Enable AWS CloudTrail to audit KMS key usage
- Set up alerts for unauthorized access attempts
4 — Security
- Never store unencrypted sensitive values in version control
- Use separate key aliases for different environments
- Implement proper backup and recovery procedures
Next Steps
In Part 2 of this series, we’ll explore how to integrate AWS Secrets Manager with our KMS setup for more advanced secrets management capabilities.
Conclusion
Using AWS KMS with Terraform provides a secure way to manage encrypted secrets in your infrastructure code. By following these practices, you can ensure that your sensitive data remains protected while still being accessible to your authorized applications and services.
ℹ️ Terraform code is available here
Secure Secrets Management in Terraform — Part1: Leveraging AWSKMS was originally published in AWSMorocco on Medium, where people are continuing the conversation by highlighting and responding to this story.