AWS Key Management Service makes it easy to create and manage cryptographic keys and control their use across a wide range of AWS services and in your applications. AWS KMS is a secure and resilient service that uses hardware security modules that have been validated under FIPS 140-2, or are in the process of being validated, to protect your keys. AWS KMS is integrated with AWS CloudTrail to provide you with logs of all key usage to help meet your regulatory and compliance needs.
Terraform provides first-class support for provisioning and maintaining Key Management Service resources across providers. Managing cryptographic keys is critical for securing data in cloud-native architectures. Whether evaluating Terraform pricing, Terraform enterprise features, or comparing Terraform vs Pulumi and CloudFormation, understanding key configuration helps ensure your infrastructure is both secure and compliant.
Core Concepts for KMS in Terraform
Terraform uses native resource blocks to define and manage keys.
Key concepts include:
- Resource declarations for KMS providers e.g., AWS, GCP, Azure
- Lifecycle rules for rotation, deletion, and versioning
- Interpolation to reference key ARNs in downstream modules
AWS KMS is a managed service that makes it easy for you to create and control the cryptographic keys that are used to protect your data. AWS KMS is integrated with many AWS Services and integrates with AWS CloudTrail to log use of your KMS keys for auditing, regulatory, and compliance needs.
AWS KMS uses an Envelope encryption strategy to protect the keys that encrypt data. Envelope encryption is the practice of encrypting plaintext data with a data key, and then encrypting the data key with a second key, known as the root key. AWS KMS protects the encryption keys by storing and managing them securely. Root keys never leave the AWS KMS unencrypted.
Key resource policy along with IAM policies controls the access to the AWS KMS APIs.
AWS KMS keys can be AWS owned, AWS managed or customer managed. Some AWS Services encrypt the data, by default, with an AWS owned key or an AWS managed key. Some AWS Services support customer managed keys.
Module Options for Creating Keys and Replicas
A Terraform module to create an Amazon KMS Key or Replica KMS key including optional integration with Mozilla SOPS is available.
Capabilities include:
- Optional Create a primary KMS key in either single/multi-region
- Optional Create a replica KMS key in a different region of the primary multi-region KMS key
- Optional Create a corresponding SOPS file containing the primary KMS or replica KMS arn
- Optional Create a KMS Grant including encryption constraints
The primary KMS key you initially created was created as a multi-region KMS key. You can create a primary KMS key or a replica of a multi-region primary KMS key for use with the Mozilla SOPS tool.
This solution is a set of Terraform modules that provision symmetric customer managed AWS KMS keys for use by the target AWS Services. You can optionally manage the key resource policy for the cross-account access via the AWS Services and the account principals. An additional module is included that supports creating multi-region replica keys in another region.
The full set of features is listed here. The solution also provides three example scenarios of how the solution solves common enterprise use cases.
| Feature | Description |
|---|---|
| Primary key creation | Single region or multi-region primary KMS key |
| Replica key creation | Replica KMS key in a different region of primary multi-region key |
| SOPS integration | Corresponding SOPS file containing primary or replica KMS ARN |
| KMS Grant | Optional grant with encryption constraints |
| Cross-account policy | Optional management of key resource policy for cross-account access |
Defining an AWS KMS Key with Terraform
Prerequisites for a typical configure and manage keys tutorial include:
- Terraform v1.x evaluate Terraform pricing and Terraform Cloud cost across teams
- AWS CLI configured with proper IAM permissions
- An existing Terraform Cloud or Terraform Enterprise workspace Terraform enterprise features include policy enforcement and collaboration
- Airflow environment for ELT orchestration
Along the way, reference Terraform Cloud cost considerations, Terraform managed service options, and Terraform support plans for production deployment.
Define an AWS KMS Key
hcl
resource "aws_kms_key" "data_key" {
description = "KMS key for ELT data encryption"
deletion_window_in_days = 30
enable_key_rotation = true
tags = {
Environment = "production"
}
}
Expose the key ARN for use in other modules or DAG tasks:
hcl
output "data_key_arn" {
value = aws_kms_key.data_key.arn
}
Outputs for key information can be exported for other Terraform configurations:
hcl
output "kms_key_id" {
description = "The KMS key ID"
value = aws_kms_key.main.key_id
}
output "kms_key_arn" {
description = "The KMS key ARN"
value = aws_kms_key.main.arn
}
output "kms_alias_arn" {
description = "The KMS alias ARN"
value = aws_kms_alias.main.arn
}
Integrate with an Airflow ELT DAG
Use the Terraform key in your DAG to encrypt data at rest. A simplified Airflow DAG using TerraformOperator and a Python task can reference the key ARN output.
Terraform version and provider constraints are commonly defined as:
hcl
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0.0"
}
}
}
hcl
provider "aws" {
region = "us-east-1"
}
Key Policy Configuration and Restricting Default Access
Key resource policy along with IAM policies controls access to AWS KMS APIs.
A restrictive key policy example defines:
hcl
resource "aws_kms_key" "this" {
description = "Restricted kms key policy example"
policy = data.aws_iam_policy_document.restricted_key_policy.json
}
Variable definition for a custom policy:
hcl
variable key_policy {
description = "key policy"
type = list(object({
sid = optional(string)
effect = string
actions = list(string)
resources = list(string)
principals = optional(list(object({
type = string
identifiers = list(string)
})))
conditions = optional(list(object({
test = optional(string),
variable = string,
values = list(string)
})))
}))
default = []
}
Caller identity and locals for account scoped policy:
hcl
data "aws_caller_identity" "current" {}
locals {
aws_account_id = data.aws_caller_identity.current.account_id
default_key_policy = [
{
sid = "Enable root access and prevent permission delegation"
effect = "Allow"
principals = [
{
type = "AWS"
identifiers = [local.aws_account_id]
}
]
actions =
A default blueprint can include the following custom policy statements:
Enable root access and prevent permission delegation
Effect Allow
Principal AWS arn:aws:iam::123456789012:root
Action kms:*
Resource *
Condition StringEquals aws:PrincipalType AccountAllow access for key administrators
Effect Allow
Principal AWS arn:aws:iam::123456789012:role/TERRAFORM and arn:aws:iam::123456789012:role/ADMIN
Action kms:Create, kms:Describe, kms:Enable, kms:List, kms:Put, kms:Update, kms:Revoke, kms:Disable, kms:Get, kms:Delete, kms:TagResource, kms:UntagResource, kms:ScheduleKeyDeletion, kms:CancelKeyDeletion
Resource *Enable read access to all identities
Effect Allow
Principal AWS arn:aws:iam::123456789012:root
Action kms:List, kms:Get, kms:Describe*
Resource *
The key policy allows the following permissions:
First statement: The AWS root user account has full access to the key.
Second statement: The principals role ADMIN and TERRAFORM has access to perform management operations on the key.
Third statement All account principals are able to read the key.
Instead, it allows any principal in AWS account 123456789012 to have root access to the KMS key as long as you have attached the required permissions to the IAM entity.
Common Mistakes and Safeguards
Locking yourself out. If you remove the root account access from the key policy and no remaining principal can update the policy, you can't modify the key anymore. The only way to recover is to contact AWS support.
Forgetting grants. Some AWS services like EBS and RDS use grants instead of direct key policies. Make sure the roles that interact with these services have kms:CreateGrant permission.
Deleting keys too quickly. The minimum deletion window is 7 days. Always use the maximum of 30 days for production keys. Better yet, disable the key first and wait before scheduling deletion.
You'll need to handle key rotation manually for these.
Create separate keys for different services, always include root account access in key policies, and never set the deletion window below 30 days for production.
Conclusion
KMS keys are the backbone of encryption on AWS. Customer-managed keys give you control over who can access your encrypted data, audit trails through CloudTrail, and automatic key rotation. Terraform makes key provisioning auditable and repeatable.
A robust Terraform create KMS key workflow combines primary and multi-region replica key creation, optional SOPS integration, and granular key policy management. Lifecycle rules for rotation, deletion, and versioning should be explicitly defined. Key ARNs should be interpolated into downstream modules and outputs.
Production deployments benefit from explicit deletionwindowindays set to 30, enablekey_rotation set to true, and tag governance. Cross-account access is managed through key resource policy alongside IAM policies, with grants used where services require them.
Terraform Cloud cost considerations, Terraform managed service options, and Terraform support plans remain relevant for team scale and policy enforcement. With Terraform Enterprise features including policy enforcement and collaboration, and proper caller identity scoping, key policies can be restricted to prevent permission delegation while preserving root account recovery.
Encryption is only as strong as your key management, and Terraform makes it auditable.