DEV Community

Cover image for Creating a multi-region key using terraform
Sujay Pillai for AWS Community Builders

Posted on • Updated on

Creating a multi-region key using terraform

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"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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"))
}
Enter fullscreen mode Exit fullscreen mode

NOTE: "name" must begin with 'alias/' and be comprised of only [a-zA-Z0-9:/_-]

AWS KMS CMK

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
}
Enter fullscreen mode Exit fullscreen mode

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.

MRK

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

Source Code for above setup available here

Oldest comments (0)