diff --git a/README.md b/README.md index ff9254d..2c5bc8a 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,14 @@ Source code referenced by the blog post: https://hyperscience.com/tech-blog/runn | cloudwatch\_schedule\_expression | AWS cron schedule expression | `string` | n/a | yes | | ecr\_repo\_name | Name of the ECR repo that contains the Docker image of your cron job | `string` | n/a | yes | | ecs\_cluster\_name | (Optional) Name of the ECS Cluster that you want to execute your cron job. Defaults to your task name if no value is supplied | `string` | `""` | no | -| extra\_container\_defs | Additional configuration that you want to add to your task definition (see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html for all options) | `map(any)` | `{}` | no | +| ecs\_task\_execution\_role\_name | If the default AWS ECSTaskExecutionRole is not sufficient for your needs, you can provide your own ECS Task Execution Role here. The module will attach a CloudWatch policy for logging purposes. | `string` | `""` | no | +| extra\_container\_defs | Additional configuration that you want to add to your task definition (see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html for all options) | `any` | `{}` | no | | image\_tag | Docker tag of the container that you want to run | `string` | n/a | yes | | subnet\_ids | Subnets where the job will be run | `list(string)` | n/a | yes | | task\_cpu | CPU units to allocate to your job (vCPUs \* 1024) | `number` | `1024` | no | | task\_memory | In MiB | `number` | `2048` | no | | task\_name | Name of the task for resource naming | `string` | n/a | yes | -| task\_role\_arn | IAM role ARN for your task if it needs to access any AWS resources | `any` | `null` | no | +| task\_role\_arn | IAM role ARN for your task if it needs to access any AWS resources. IMPORTANT: This must have an AssumeRolePolicy that includes the 'ecs-tasks.amazonaws.com' provider!! | `any` | `null` | no | ## Outputs diff --git a/main.tf b/main.tf index 1ee4877..b1bca38 100644 --- a/main.tf +++ b/main.tf @@ -52,7 +52,7 @@ resource "aws_ecs_task_definition" "this" { family = var.task_name container_definitions = jsonencode(local.container_definitions) task_role_arn = var.task_role_arn - execution_role_arn = aws_iam_role.task_execution_role.arn + execution_role_arn = local.ecs_task_execution_role_arn requires_compatibilities = ["FARGATE"] network_mode = "awsvpc" cpu = tostring(var.task_cpu) @@ -151,8 +151,11 @@ resource "aws_sns_topic_policy" "task_failure" { // IAM Resources // ------------- // We create 2 IAM roles: -// 1. A Task Execution role used to run the ECS task and log output to cloudwatch +// 1. A Task Execution role used to run the ECS task and log output to cloudwatch. This can be overridden by the user if they are using a +// non-default ECSTaskExecutionRole. // 2. A second role used by Cloudwatch to launch the ECS task when the timer is triggered +// +// Users can add a 3rd role if the ECS Task needs to access AWS resources. // Task Execution Role // Includes essential ecs access and cloudwatch logging permissions @@ -180,24 +183,39 @@ data "aws_iam_policy_document" "task_execution_cloudwatch_access" { } } +data "aws_iam_role" "task_execution_role" { + count = var.ecs_task_execution_role_name != "" ? 1 : 0 + + name = var.ecs_task_execution_role_name +} + +locals { + ecs_task_execution_role_arn = var.ecs_task_execution_role_name != "" ? data.aws_iam_role.task_execution_role[0].arn : aws_iam_role.task_execution_role[0].arn + ecs_task_execution_role_name = var.ecs_task_execution_role_name != "" ? data.aws_iam_role.task_execution_role[0].name : aws_iam_role.task_execution_role[0].name +} + resource "aws_iam_role" "task_execution_role" { + count = var.ecs_task_execution_role_name == "" ? 1 : 0 + name = "${var.task_name}-execution" assume_role_policy = data.aws_iam_policy_document.task_execution_assume_role.json } -resource "aws_iam_policy" "task_execution_role" { +resource "aws_iam_policy" "task_execution_logging_policy" { name = "${var.task_name}-logging" policy = data.aws_iam_policy_document.task_execution_cloudwatch_access.json } resource "aws_iam_role_policy_attachment" "ecs_task_execution" { - role = aws_iam_role.task_execution_role.name + count = var.ecs_task_execution_role_name == "" ? 1 : 0 + + role = local.ecs_task_execution_role_name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" } resource "aws_iam_role_policy_attachment" "ecs_task_execution_cloudwatch_access" { - role = aws_iam_role.task_execution_role.name - policy_arn = aws_iam_policy.task_execution_role.arn + role = local.ecs_task_execution_role_name + policy_arn = aws_iam_policy.task_execution_logging_policy.arn } // Cloudwatch execution role @@ -225,7 +243,7 @@ data "aws_iam_policy_document" "cloudwatch" { effect = "Allow" actions = ["iam:PassRole"] resources = concat([ - aws_iam_role.task_execution_role.arn + local.ecs_task_execution_role_arn ], var.task_role_arn != null ? [var.task_role_arn] : []) } } diff --git a/variables.tf b/variables.tf index 1e093ab..b5a49bd 100644 --- a/variables.tf +++ b/variables.tf @@ -48,3 +48,8 @@ variable "task_role_arn" { default = null description = "IAM role ARN for your task if it needs to access any AWS resources. IMPORTANT: This must have an AssumeRolePolicy that includes the 'ecs-tasks.amazonaws.com' provider!!" } + +variable "ecs_task_execution_role_name" { + default = "" + description = "If the default AWS ECSTaskExecutionRole is not sufficient for your needs, you can provide your own ECS Task Execution Role here. The module will attach a CloudWatch policy for logging purposes." +} \ No newline at end of file