Skip to content

Instantly share code, notes, and snippets.

@mtranter
Last active December 14, 2021 10:23
Show Gist options
  • Save mtranter/ce8ebd3e5b02cd28767d37cbfc99481c to your computer and use it in GitHub Desktop.
Save mtranter/ce8ebd3e5b02cd28767d37cbfc99481c to your computer and use it in GitHub Desktop.
Terraform Modules Blog
locals {
key_attributes = [
for k in [var.hash_key, var.range_key] : {
name = k.name
type = k.type
} if k != null
]
gsi_attributes = flatten([
for gi in var.global_secondary_indexes : [
for k in [gi.hash_key, gi.range_key] : {
name = k.name
type = k.type
} if k != null
]
]
)
gsi_map = {
for k in var.global_secondary_indexes : k.name => k
}
attributes = { for a in toset(concat(local.key_attributes, local.gsi_attributes)) : a.name => a.type }
}
resource "aws_dynamodb_table" "table" {
hash_key = var.hash_key.name
range_key = var.range_key == null ? null : var.range_key.name
name = var.name
dynamic "global_secondary_index" {
for_each = local.gsi_map
iterator = each
content {
name = each.value.name
hash_key = each.value.hash_key.name
range_key = each.value.range_key.name
}
}
dynamic "attribute" {
for_each = local.attributes
content {
name = attribute.key
type = attribute.value
}
}
}
resource "aws_kms_alias" "alias" {
target_key_id = aws_kms_key.key.id
name = "alias/dynamodb/${replace(var.name, ".", "_")}"
}
data "aws_caller_identity" "me" {}
data "aws_region" "current" {}
resource "aws_kms_key" "key" {
description = "Key for encrypting dynamo table ${var.name}"
enable_key_rotation = true
policy = <<EOF
{
"Version": "2012-10-17",
"Id": "DynamoTable${var.name}KeyPolicy",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::${data.aws_caller_identity.me.account_id}:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid" : "Allow access through Amazon DynamoDB for all principals in the account that are authorized to use this DynamoDB table",
"Effect" : "Allow",
"Principal" : {
"AWS" : "*"
},
"Action" : [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:CreateGrant", "kms:DescribeKey" ],
"Resource" : "*",
"Condition" : {
"StringEquals" : {
"kms:ViaService" : "dynamodb.${data.aws_region.current.name}.amazonaws.com",
"kms:CallerAccount" : "${data.aws_caller_identity.me.account_id}"
}
}
},
{
"Sid" : "Allow DynamoDB Service with service principal name dynamodb.amazonaws.com to describe the key directly",
"Effect" : "Allow",
"Principal" : {
"Service" : "dynamodb.amazonaws.com"
},
"Action" : [ "kms:Describe*", "kms:Get*", "kms:List*" ],
"Resource" : "*"
}
]
}
EOF
}
locals {
key_attributes = [
for k in [var.hash_key, var.range_key] : {
name = k.name
type = k.type
} if k != null
]
gsi_attributes = flatten([
for gi in var.global_secondary_indexes : [
for k in [gi.hash_key, gi.range_key] : {
name = k.name
type = k.type
} if k != null
]
]
)
gsi_map = {
for k in var.global_secondary_indexes : k.name => k
}
attributes = { for a in toset(concat(local.key_attributes, local.gsi_attributes)) : a.name => a.type }
}
resource "aws_dynamodb_table" "table" {
hash_key = var.hash_key.name
range_key = var.range_key == null ? null : var.range_key.name
name = var.name
point_in_time_recovery {
enabled = true
}
server_side_encryption {
enabled = true
kms_key_arn = aws_kms_key.key.arn
}
dynamic "global_secondary_index" {
for_each = local.gsi_map
iterator = each
content {
name = each.value.name
hash_key = each.value.hash_key.name
range_key = each.value.range_key.name
}
}
dynamic "attribute" {
for_each = local.attributes
content {
name = attribute.key
type = attribute.value
}
}
}
module "users_service_table" {
source = "./modules/aws/dynamodb_table"
name = "UsersServiceTable"
hash_key = {
name = "Id"
type = "S"
}
range_key = {
name = "Sort"
type = "S"
}
global_secondary_indexes = [{
name = "InvertedIndex"
hash_key = {
name = "Sort"
type = "S"
}
range_key = {
name = "Id"
type = "S"
}
}]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment