Secure Secrets Management in Terraform Part1: Leveraging AWS KMS

Secure Secrets Management in Terraform Part1: Leveraging AWS KMS

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.

Related Posts

AWS IAM Roles For Kubernetes Service Accounts (IRSA)

AWS IAM Roles For Kubernetes Service Accounts (IRSA)

In the world of Kubernetes and AWS, managing access to AWS resources from your Kubernetes cluster can be tricky.

Read More
Chat With Your AWS Resources Using ChatGPT

Chat With Your AWS Resources Using ChatGPT

In the ever-evolving world of cloud computing, where efficiency and productivity are paramount, developers and DevOps engineers often find themselves navigating the complexities of AWS infrastructure.

Read More
Welcome to AWS Morocco’s first newsletter!

Welcome to AWS Morocco’s first newsletter!

Dear AWS Enthusiasts, We’re thrilled to announce the launch of the AWS Morocco Newsletter, your new go-to source for all things AWS within our vibrant Moroccan tech community!

Read More