From 6ce1780f7b9794c68e82dbd8069cc0bc8434e087 Mon Sep 17 00:00:00 2001 From: Jerome Wolff Date: Thu, 6 Feb 2025 12:20:04 +0100 Subject: [PATCH 1/2] Add ephemeral storage encryption --- README.md | 9 ++-- main.tf | 113 +++++++++++++++++++++++++++++++++++++++++++++++---- variables.tf | 6 +++ versions.tf | 2 +- 4 files changed, 118 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 71ddc4f..43862bc 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ performance and health. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [enable\_container\_insights](#input\_enable\_container\_insights) | Enable CloudWatch Container Insights for the cluster. | `bool` | `true` | no | +| [encrypt\_ephemeral\_storage](#input\_encrypt\_ephemeral\_storage) | Encrypt the ECS ephemeral storage for the cluster. | `bool` | `false` | no | | [encrypt\_execute\_command\_session](#input\_encrypt\_execute\_command\_session) | Encrypt execute command session for the cluster. | `bool` | `false` | no | | [logging\_execute\_command\_session](#input\_logging\_execute\_command\_session) | Log execute command session for the cluster. | `string` | `"DEFAULT"` | no | | [name](#input\_name) | Name of the ECS cluster. | `string` | n/a | yes | @@ -63,13 +64,15 @@ performance and health. | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 4.36 | +| [aws](#provider\_aws) | >= 5.59 | ## Resources -- resource.aws_cloudwatch_log_group.container_insights (main.tf#62) -- resource.aws_cloudwatch_log_group.main (main.tf#55) +- resource.aws_cloudwatch_log_group.container_insights (main.tf#75) +- resource.aws_cloudwatch_log_group.main (main.tf#68) - resource.aws_ecs_cluster.main (main.tf#10) +- data source.aws_caller_identity.current (main.tf#95) +- data source.aws_iam_policy_document.kms_ephemeral (main.tf#96) # Examples ### Basic Example diff --git a/main.tf b/main.tf index f3049e5..404a899 100644 --- a/main.tf +++ b/main.tf @@ -19,23 +19,36 @@ resource "aws_ecs_cluster" "main" { } } + dynamic "configuration" { for_each = var.encrypt_execute_command_session || var.logging_execute_command_session != "DEFAULT" ? [true] : [] content { - execute_command_configuration { - kms_key_id = var.encrypt_execute_command_session ? module.kms[0].key_id : null - logging = var.logging_execute_command_session + dynamic "execute_command_configuration" { + for_each = var.encrypt_execute_command_session || var.logging_execute_command_session != "DEFAULT" ? [true] : [] + + content { + kms_key_id = var.encrypt_execute_command_session ? module.kms[0].key_id : null + logging = var.logging_execute_command_session - dynamic "log_configuration" { - for_each = var.logging_execute_command_session == "OVERRIDE" ? [true] : [] + dynamic "log_configuration" { + for_each = var.logging_execute_command_session == "OVERRIDE" ? [true] : [] - content { - cloud_watch_encryption_enabled = false - cloud_watch_log_group_name = aws_cloudwatch_log_group.main[0].name + content { + cloud_watch_encryption_enabled = false + cloud_watch_log_group_name = aws_cloudwatch_log_group.main[0].name + } } } } + + dynamic "managed_storage_configuration" { + for_each = var.encrypt_ephemeral_storage ? [true] : [] + + content { + fargate_ephemeral_storage_kms_key_id = module.kms_ephemeral[0].key_id + } + } } } @@ -67,3 +80,87 @@ resource "aws_cloudwatch_log_group" "container_insights" { tags = var.tags } + +module "kms_ephemeral" { + count = var.encrypt_ephemeral_storage ? 1 : 0 + + source = "geekcell/kms/aws" + version = ">= 1.0.0, < 2.0.0" + policy = data.aws_iam_policy_document.kms_ephemeral[0].json + + alias = "ecs/cluster/${var.name}/ephemeral-storage" + tags = var.tags +} + +data "aws_caller_identity" "current" {} +data "aws_iam_policy_document" "kms_ephemeral" { + count = var.encrypt_ephemeral_storage ? 1 : 0 + + statement { + sid = "Enable IAM User Permissions." + effect = "Allow" + actions = ["kms:*"] + resources = ["*"] + + principals { + identifiers = ["*"] + type = "AWS" + } + } + + statement { + sid = "Allow generate data key access for Fargate tasks." + effect = "Allow" + actions = ["kms:GenerateDataKeyWithoutPlaintext"] + + principals { + identifiers = ["fargate.amazonaws.com"] + type = "Service" + } + + condition { + test = "StringEquals" + variable = "kms:EncryptionContext:aws:ecs:clusterAccount" + values = [data.aws_caller_identity.current.account_id] + } + + condition { + test = "StringEquals" + variable = "kms:EncryptionContext:aws:ecs:clusterName" + values = [var.name] + } + + resources = ["*"] + } + + statement { + sid = "Allow grant creation permission for Fargate tasks." + effect = "Allow" + actions = ["kms:CreateGrant"] + + principals { + identifiers = ["fargate.amazonaws.com"] + type = "Service" + } + + condition { + test = "StringEquals" + variable = "kms:EncryptionContext:aws:ecs:clusterAccount" + values = [data.aws_caller_identity.current.account_id] + } + + condition { + test = "StringEquals" + variable = "kms:EncryptionContext:aws:ecs:clusterName" + values = [var.name] + } + + condition { + test = "ForAllValues:StringEquals" + variable = "kms:GrantOperations" + values = ["Decrypt"] + } + + resources = ["*"] + } +} diff --git a/variables.tf b/variables.tf index e42e5e9..39469b6 100644 --- a/variables.tf +++ b/variables.tf @@ -23,6 +23,12 @@ variable "encrypt_execute_command_session" { type = bool } +variable "encrypt_ephemeral_storage" { + description = "Encrypt the ECS ephemeral storage for the cluster." + default = false + type = bool +} + variable "logging_execute_command_session" { description = "Log execute command session for the cluster." default = "DEFAULT" diff --git a/versions.tf b/versions.tf index 0c5a0cf..dc99906 100644 --- a/versions.tf +++ b/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.36" + version = ">= 5.59" } } } From dcb1f24e6efb265c1c983bf0dac8a9d183d163d9 Mon Sep 17 00:00:00 2001 From: Jerome Wolff Date: Thu, 6 Feb 2025 14:35:06 +0100 Subject: [PATCH 2/2] Add managed storage encryption --- README.md | 9 +++++---- main.tf | 19 ++++++++++++------- variables.tf | 6 ++++++ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 43862bc..58a6619 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ performance and health. | [enable\_container\_insights](#input\_enable\_container\_insights) | Enable CloudWatch Container Insights for the cluster. | `bool` | `true` | no | | [encrypt\_ephemeral\_storage](#input\_encrypt\_ephemeral\_storage) | Encrypt the ECS ephemeral storage for the cluster. | `bool` | `false` | no | | [encrypt\_execute\_command\_session](#input\_encrypt\_execute\_command\_session) | Encrypt execute command session for the cluster. | `bool` | `false` | no | +| [encrypt\_managed\_storage](#input\_encrypt\_managed\_storage) | Encrypt the ECS managed storage for the cluster. | `bool` | `false` | no | | [logging\_execute\_command\_session](#input\_logging\_execute\_command\_session) | Log execute command session for the cluster. | `string` | `"DEFAULT"` | no | | [name](#input\_name) | Name of the ECS cluster. | `string` | n/a | yes | | [tags](#input\_tags) | Tags to add to the ECS cluster. | `map(any)` | `{}` | no | @@ -68,11 +69,11 @@ performance and health. ## Resources -- resource.aws_cloudwatch_log_group.container_insights (main.tf#75) -- resource.aws_cloudwatch_log_group.main (main.tf#68) +- resource.aws_cloudwatch_log_group.container_insights (main.tf#80) +- resource.aws_cloudwatch_log_group.main (main.tf#73) - resource.aws_ecs_cluster.main (main.tf#10) -- data source.aws_caller_identity.current (main.tf#95) -- data source.aws_iam_policy_document.kms_ephemeral (main.tf#96) +- data source.aws_caller_identity.current (main.tf#100) +- data source.aws_iam_policy_document.kms_ephemeral (main.tf#101) # Examples ### Basic Example diff --git a/main.tf b/main.tf index 404a899..3c0943d 100644 --- a/main.tf +++ b/main.tf @@ -19,9 +19,13 @@ resource "aws_ecs_cluster" "main" { } } - dynamic "configuration" { - for_each = var.encrypt_execute_command_session || var.logging_execute_command_session != "DEFAULT" ? [true] : [] + for_each = ( + var.encrypt_execute_command_session || + var.logging_execute_command_session != "DEFAULT" || + var.encrypt_ephemeral_storage || + var.encrypt_managed_storage + ) ? [true] : [] content { dynamic "execute_command_configuration" { @@ -43,10 +47,11 @@ resource "aws_ecs_cluster" "main" { } dynamic "managed_storage_configuration" { - for_each = var.encrypt_ephemeral_storage ? [true] : [] + for_each = var.encrypt_ephemeral_storage || var.encrypt_managed_storage ? [true] : [] content { - fargate_ephemeral_storage_kms_key_id = module.kms_ephemeral[0].key_id + kms_key_id = var.encrypt_managed_storage ? module.kms[0].key_id : null + fargate_ephemeral_storage_kms_key_id = var.encrypt_ephemeral_storage ? module.kms_ephemeral[0].key_id : null } } } @@ -82,19 +87,19 @@ resource "aws_cloudwatch_log_group" "container_insights" { } module "kms_ephemeral" { - count = var.encrypt_ephemeral_storage ? 1 : 0 + count = var.encrypt_ephemeral_storage || var.encrypt_managed_storage ? 1 : 0 source = "geekcell/kms/aws" version = ">= 1.0.0, < 2.0.0" policy = data.aws_iam_policy_document.kms_ephemeral[0].json - alias = "ecs/cluster/${var.name}/ephemeral-storage" + alias = "ecs/cluster/${var.name}/managed-storage" tags = var.tags } data "aws_caller_identity" "current" {} data "aws_iam_policy_document" "kms_ephemeral" { - count = var.encrypt_ephemeral_storage ? 1 : 0 + count = var.encrypt_ephemeral_storage || var.encrypt_managed_storage ? 1 : 0 statement { sid = "Enable IAM User Permissions." diff --git a/variables.tf b/variables.tf index 39469b6..acd6197 100644 --- a/variables.tf +++ b/variables.tf @@ -29,6 +29,12 @@ variable "encrypt_ephemeral_storage" { type = bool } +variable "encrypt_managed_storage" { + description = "Encrypt the ECS managed storage for the cluster." + default = false + type = bool +} + variable "logging_execute_command_session" { description = "Log execute command session for the cluster." default = "DEFAULT"