For organizations to encrypt their data in a cloud-native approach AWS provides a fully managed service AWS KMS, a high-performance key management system with the “pay as you go” model to lower costs and reduce their administration burden compared to self-managed hardware security module (HSM).
By choosing AWS KMS organizations get three options for encryption key management:
- AWS KMS with customer or AWS-managed keys
- AWS KMS with BYOK
- AWS KMS with a KMS custom key store key management backed by CloudHSM
Terraform AWS provider version 3.64.0 introduced new resource aws_kms_replica_key
by which we can create Customer Managed Key (CMK).
In this blog post, we will walkthrough the steps for creating a multi-region CMK using the resource aws_kms_replica_key
which was introduced newly in Terraform AWS provider version 3.64.0.
Multi-Region keys come in handy for data security scenarios - Disaster recovery, Global data management, Distributed signing applications, Active-active applications that spun multiple regions.
As we need the resource type aws_kms_replica_key
from Terraform AWS provider the below block helps to add this to our project. Make sure you have atleast 3.64.0 version to achieve this.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.64.0"
}
}
}
Multi-Region keys are not global. You create a multi-Region primary key and then replicate it into regions that you select within an AWS partition. Then you manage the Multi-Region key in each region independently.
In our case we will have the primary key created in Singapore region while the replicas in Sydney and Jakarta respectively.
# Singapore
provider "aws" {
region = "ap-southeast-1"
}
# Sydney
provider "aws" {
alias = "secondary"
region = "ap-southeast-2"
}
# Jakarta
# 3.70.0 Terraform AWS Provider release will use AWS SDK v1.42.23
# which adds ap-southeast-3 to the list of regions for the standard AWS partition.
# https://github.com/hashicorp/terraform-provider-aws/issues/22252
provider "aws" {
alias = "tertiary"
region = "ap-southeast-3"
skip_region_validation = true
}
NOTE: If you are trying to create a KMS replica in
JAKARTA
region you will encounter an error as below
Error: Invalid AWS Region: ap-southeast-3
with provider["registry.terraform.io/hashicorp/aws"].tertiary,
This is becuase support for ap-southeast-3
was added in AWS SDK v1.42.23 and used in Terraform AWS Provider v3.70.0. The temporary solution for this would be to add skip_region_validation = true
statement in the provider block.
Unlike other AWS resource policies, a AWS KMS key policy does not automatically give permission to the account or any of its users. To give permission to account administrators, the key policy must include an explicit statement that provides this permission, like this one.
data "aws_iam_policy_document" "kms" {
# Allow root users full management access to key
statement {
effect = "Allow"
actions = [
"kms:*"
]
resources = ["*"]
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
}
# Allow other accounts limited access to key
statement {
effect = "Allow"
actions = [
"kms:CreateGrant",
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey",
]
resources = ["*"]
# AWS account IDs that need access to this key
principals {
type = "AWS"
identifiers = var.account_ids
}
}
}
Creating multi-region primary key
resource "aws_kms_key" "primary" {
description = "CMK for AWS CB Blog"
enable_key_rotation = true
policy = data.aws_iam_policy_document.kms.json
multi_region = true
}
Resource :aws_kms_key
is used to create a single-region OR multi-region primary KMS key.
As this is a multi-region key the id
& key_id
has mrk- as prefix.
terraform show -json terraform.tfstate | jq '.values.root_module.resources[0].values.id'
"mrk-01641fdcadec421f9ed2665c7d78ef9c"
terraform show -json terraform.tfstate | jq '.values.root_module.resources[0].values.key_id'
"mrk-01641fdcadec421f9ed2665c7d78ef9c"
You can also refer to KMS key using its alias. Resource : aws_kms_alias
is used to create an alias.
resource "aws_kms_alias" "alias" {
target_key_id = aws_kms_key.primary.id
name = format("alias/%s", lower("AWS_CB_CMK"))
}
NOTE: "name" must begin with 'alias/' and be comprised of only [a-zA-Z0-9:/_-]
Creating multi-region replica keys
resource "aws_kms_replica_key" "secondary" {
provider = aws.secondary
description = "Multi-Region replica key"
deletion_window_in_days = 7
primary_key_arn = aws_kms_key.primary.arn
}
resource "aws_kms_replica_key" "tertiary" {
provider = aws.tertiary
description = "Multi-Region replica key"
deletion_window_in_days = 7
primary_key_arn = aws_kms_key.primary.arn
}
Resource :aws_kms_replica_key
is used to create a multi-region replica key. Here we are passing explicitly the provider alias (aws.secondary & aws.tertiary) to create the keys in Sydney & Jakarta region.
You need to set a waiting period of 7 (min) - 30 (max, default) days for deleting the KMS key.
We thus have a primary key in Singapore region with its replica in Sydney & Jakarta respectively.
While you implement this and in continuation of this blog we will see
- How we can consume this key in encrypting an S3 bucket to configure AWS CloudTrail
- Configure an SQS
- Integrating Azure Sentinel to consume AWS CloudTrail data.
Source Code for above setup available here
Top comments (0)