From ae412b3981a41d830284405295312b07d8db26c4 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 30 Oct 2023 13:31:35 -0400 Subject: [PATCH] feat: Add support for easily enabling ECS Exec support --- examples/fargate/main.tf | 3 +++ modules/container-definition/README.md | 1 + modules/container-definition/main.tf | 4 +++- modules/container-definition/variables.tf | 6 ++++++ modules/service/README.md | 3 +++ modules/service/main.tf | 20 ++++++++++++++++++-- wrappers/container-definition/main.tf | 1 + 7 files changed, 35 insertions(+), 3 deletions(-) diff --git a/examples/fargate/main.tf b/examples/fargate/main.tf index 6a97998..ba80b6e 100644 --- a/examples/fargate/main.tf +++ b/examples/fargate/main.tf @@ -61,6 +61,9 @@ module "ecs_service" { cpu = 1024 memory = 4096 + # Enables ECS Exec + enable_execute_command = true + # Container definition(s) container_definitions = { diff --git a/modules/container-definition/README.md b/modules/container-definition/README.md index 167c50f..215ef11 100644 --- a/modules/container-definition/README.md +++ b/modules/container-definition/README.md @@ -152,6 +152,7 @@ No modules. | [docker\_labels](#input\_docker\_labels) | A key/value map of labels to add to the container | `map(string)` | `{}` | no | | [docker\_security\_options](#input\_docker\_security\_options) | A list of strings to provide custom labels for SELinux and AppArmor multi-level security systems. This field isn't valid for containers in tasks using the Fargate launch type | `list(string)` | `[]` | no | | [enable\_cloudwatch\_logging](#input\_enable\_cloudwatch\_logging) | Determines whether CloudWatch logging is configured for this container definition. Set to `false` to use other logging drivers | `bool` | `true` | no | +| [enable\_execute\_command](#input\_enable\_execute\_command) | Specifies whether to enable Amazon ECS Exec for the tasks within the service | `bool` | `false` | no | | [entrypoint](#input\_entrypoint) | The entry point that is passed to the container | `list(string)` | `[]` | no | | [environment](#input\_environment) | The environment variables to pass to the container |
list(object({
name = string
value = string
}))
| `[]` | no | | [environment\_files](#input\_environment\_files) | A list of files containing the environment variables to pass to a container |
list(object({
value = string
type = string
}))
| `[]` | no | diff --git a/modules/container-definition/main.tf b/modules/container-definition/main.tf index e1c3e15..9054786 100644 --- a/modules/container-definition/main.tf +++ b/modules/container-definition/main.tf @@ -17,6 +17,8 @@ locals { var.log_configuration ) + linux_parameters = var.enable_execute_command ? merge({ "initProcessEnabled" : true }, var.linux_parameters) : var.linux_parameters + definition = { command = length(var.command) > 0 ? var.command : null cpu = var.cpu @@ -37,7 +39,7 @@ locals { image = var.image interactive = var.interactive links = local.is_not_windows && length(var.links) > 0 ? var.links : null - linuxParameters = local.is_not_windows && length(var.linux_parameters) > 0 ? var.linux_parameters : null + linuxParameters = local.is_not_windows && length(local.linux_parameters) > 0 ? local.linux_parameters : null logConfiguration = length(local.log_configuration) > 0 ? local.log_configuration : null memory = var.memory memoryReservation = var.memory_reservation diff --git a/modules/container-definition/variables.tf b/modules/container-definition/variables.tf index a59e92d..fd5b99b 100644 --- a/modules/container-definition/variables.tf +++ b/modules/container-definition/variables.tf @@ -59,6 +59,12 @@ variable "docker_security_options" { default = [] } +variable "enable_execute_command" { + description = "Specifies whether to enable Amazon ECS Exec for the tasks within the service" + type = bool + default = false +} + variable "entrypoint" { description = "The entry point that is passed to the container" type = list(string) diff --git a/modules/service/README.md b/modules/service/README.md index 81ebb3c..ea6354f 100644 --- a/modules/service/README.md +++ b/modules/service/README.md @@ -130,6 +130,9 @@ module "ecs_service" { # Disable creation of service and all resources create = false + # Enable ECS Exec + enable_execute_command = true + # Disable creation of the service IAM role; `iam_role_arn` should be provided create_iam_role = false diff --git a/modules/service/main.tf b/modules/service/main.tf index d41af69..6971d89 100644 --- a/modules/service/main.tf +++ b/modules/service/main.tf @@ -536,6 +536,7 @@ module "container_definition" { dns_servers = try(each.value.dns_servers, var.container_definition_defaults.dns_servers, []) docker_labels = try(each.value.docker_labels, var.container_definition_defaults.docker_labels, {}) docker_security_options = try(each.value.docker_security_options, var.container_definition_defaults.docker_security_options, []) + enable_execute_command = try(each.value.enable_execute_command, var.container_definition_defaults.enable_execute_command, var.enable_execute_command) entrypoint = try(each.value.entrypoint, var.container_definition_defaults.entrypoint, []) environment = try(each.value.environment, var.container_definition_defaults.environment, []) environment_files = try(each.value.environment_files, var.container_definition_defaults.environment_files, []) @@ -951,7 +952,22 @@ resource "aws_iam_role_policy_attachment" "tasks" { } data "aws_iam_policy_document" "tasks" { - count = local.create_tasks_iam_role && length(var.tasks_iam_role_statements) > 0 ? 1 : 0 + count = local.create_tasks_iam_role && (length(var.tasks_iam_role_statements) > 0 || var.enable_execute_command) ? 1 : 0 + + dynamic "statement" { + for_each = var.enable_execute_command ? [1] : [] + + content { + sid = "ECSExec" + actions = [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel", + ] + resources = ["*"] + } + } dynamic "statement" { for_each = var.tasks_iam_role_statements @@ -996,7 +1012,7 @@ data "aws_iam_policy_document" "tasks" { } resource "aws_iam_role_policy" "tasks" { - count = local.create_tasks_iam_role && length(var.tasks_iam_role_statements) > 0 ? 1 : 0 + count = local.create_tasks_iam_role && (length(var.tasks_iam_role_statements) > 0 || var.enable_execute_command) ? 1 : 0 name = var.tasks_iam_role_use_name_prefix ? null : local.tasks_iam_role_name name_prefix = var.tasks_iam_role_use_name_prefix ? "${local.tasks_iam_role_name}-" : null diff --git a/wrappers/container-definition/main.tf b/wrappers/container-definition/main.tf index 0ab42b9..4fddd7e 100644 --- a/wrappers/container-definition/main.tf +++ b/wrappers/container-definition/main.tf @@ -16,6 +16,7 @@ module "wrapper" { docker_labels = try(each.value.docker_labels, var.defaults.docker_labels, {}) docker_security_options = try(each.value.docker_security_options, var.defaults.docker_security_options, []) enable_cloudwatch_logging = try(each.value.enable_cloudwatch_logging, var.defaults.enable_cloudwatch_logging, true) + enable_execute_command = try(each.value.enable_execute_command, var.defaults.enable_execute_command, false) entrypoint = try(each.value.entrypoint, var.defaults.entrypoint, []) environment = try(each.value.environment, var.defaults.environment, []) environment_files = try(each.value.environment_files, var.defaults.environment_files, [])