From b788be533b24f67232f6284812e7609052acdb4f Mon Sep 17 00:00:00 2001 From: Oanh Nguyen Date: Tue, 22 Oct 2024 23:17:02 +0700 Subject: [PATCH] Add some policy statements --- modules/ecs-task-role/README.md | 8 ++-- modules/execution-role/README.md | 21 +++++---- modules/execution-role/main.tf | 73 +++++++++++++++++++++++++++-- modules/execution-role/variables.tf | 48 +++++++++++++++++++ modules/task-role/README.md | 8 +++- modules/task-role/main.tf | 31 ++++++++++-- modules/task-role/variables.tf | 6 +++ 7 files changed, 174 insertions(+), 21 deletions(-) diff --git a/modules/ecs-task-role/README.md b/modules/ecs-task-role/README.md index 25173f2..c793f59 100644 --- a/modules/ecs-task-role/README.md +++ b/modules/ecs-task-role/README.md @@ -73,11 +73,11 @@ module "task_role" { | [enable\_ssm\_core\_policy](#input\_enable\_ssm\_core\_policy) | Enable to attach AmazonSSMManagedInstanceCore to task role | `bool` | `true` | no | | [path](#input\_path) | The path to the IAM role | `string` | `"/"` | no | | [permissions\_boundary\_arn](#input\_permissions\_boundary\_arn) | The permissions boundary of the IAM role | `string` | `""` | no | -| [readable\_s3\_arns](#input\_readable\_s3\_arns) | The list of S3 ARN that can be read from | `list(string)` |
[
"arn:aws:s3:::*"
]
| no | -| [sendable\_ses\_arns](#input\_sendable\_ses\_arns) | The list of SES domain identity ARN that can be sent from | `list(string)` |
[
"arn:aws:ses:*:*:*"
]
| no | +| [readable\_s3\_arns](#input\_readable\_s3\_arns) | The list of S3 ARN that can be read from | `list(string)` |
[
"arn:aws:s3:::*"
]
| no | +| [sendable\_ses\_arns](#input\_sendable\_ses\_arns) | The list of SES domain identity ARN that can be sent from | `list(string)` |
[
"arn:aws:ses:*:*:*"
]
| no | | [tags](#input\_tags) | The list of tags to apply to the IAM role | `map(string)` | `{}` | no | -| [writable\_log\_group\_arns](#input\_writable\_log\_group\_arns) | The list of Log group ARN that can be written to | `list(string)` |
[
"arn:aws:logs:::*"
]
| no | -| [writable\_s3\_arns](#input\_writable\_s3\_arns) | The list of S3 ARN that can be written to | `list(string)` |
[
"arn:aws:s3:::*"
]
| no | +| [writable\_log\_group\_arns](#input\_writable\_log\_group\_arns) | The list of Log group ARN that can be written to | `list(string)` |
[
"arn:aws:logs:::*"
]
| no | +| [writable\_s3\_arns](#input\_writable\_s3\_arns) | The list of S3 ARN that can be written to | `list(string)` |
[
"arn:aws:s3:::*"
]
| no | ## Outputs diff --git a/modules/execution-role/README.md b/modules/execution-role/README.md index ef265ab..9a1ec53 100644 --- a/modules/execution-role/README.md +++ b/modules/execution-role/README.md @@ -7,7 +7,7 @@ This submodule help create an IAM assumable role for ECS Task Execution Role ```hcl module "task_execution_role" { source = "rabiloo/ecs/aws//modules/ecs-execution-role" - version = "~>0.3.0" + version = "~>0.3.1" name = "custom-ecs-execution-role" path = "/service-roles/" @@ -17,12 +17,8 @@ module "task_execution_role" { Managed = "Terraform" } - statements = { - Logs = { - actions = ["logs:CreateLogStream", "logs:PutLogEvents"] - resources = ["*"] - } - } + enable_write_log_streams = true + enable_pull_ecr_images = true } ``` @@ -48,8 +44,9 @@ No modules. | Name | Type | |------|------| +| [aws_iam_policy.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -61,12 +58,20 @@ No modules. | [name](#input\_name) | The name of the IAM role | `string` | n/a | yes | | [create](#input\_create) | Determines whether resources will be created (affects all resources) | `bool` | `true` | no | | [description](#input\_description) | The description of the IAM role | `string` | `null` | no | +| [enable\_pull\_ecr\_images](#input\_enable\_pull\_ecr\_images) | Controls if the task execution role will be permitted to pull ECR private repositories | `bool` | `false` | no | +| [enable\_read\_secrets](#input\_enable\_read\_secrets) | Controls if the task execution role will be permitted to get/read SecretsManager secrets | `bool` | `false` | no | +| [enable\_read\_ssm\_params](#input\_enable\_read\_ssm\_params) | Controls if the task execution role will be permitted to get/read SSM parameters | `bool` | `false` | no | +| [enable\_write\_log\_streams](#input\_enable\_write\_log\_streams) | Controls if the task execution role will be permitted to put/write CloudWatch log streams | `bool` | `false` | no | | [path](#input\_path) | The path to the IAM role | `string` | `"/"` | no | | [permissions\_boundary\_arn](#input\_permissions\_boundary\_arn) | The permissions boundary of the IAM role | `string` | `null` | no | | [policy\_arns](#input\_policy\_arns) | The list of IAM policy ARN be attached to IAM role | `map(string)` | `{}` | no | +| [pullable\_ecr\_images](#input\_pullable\_ecr\_images) | List of ECR private repositories the task execution role will be permitted to pull | `list(string)` |
[
"*"
]
| no | +| [readable\_secrets](#input\_readable\_secrets) | List of SecretsManager secret ARNs the task execution role will be permitted to get/read | `list(string)` |
[
"arn:aws:secretsmanager:*:*:secret:*"
]
| no | +| [readable\_ssm\_params](#input\_readable\_ssm\_params) | List of SSM parameter ARNs the task execution role will be permitted to get/read | `list(string)` |
[
"arn:aws:ssm:*:*:parameter/*"
]
| no | | [statements](#input\_statements) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage | `any` | `{}` | no | | [tags](#input\_tags) | TheA map of tags to add to all resources | `map(string)` | `{}` | no | | [use\_name\_prefix](#input\_use\_name\_prefix) | Determines whether the IAM role name is used as a prefix | `bool` | `true` | no | +| [writable\_log\_streams](#input\_writable\_log\_streams) | List of CloudWatch log streams the task execution role will be permitted to put/write | `list(string)` |
[
"*"
]
| no | ## Outputs diff --git a/modules/execution-role/main.tf b/modules/execution-role/main.tf index ed40963..8ef1f8d 100644 --- a/modules/execution-role/main.tf +++ b/modules/execution-role/main.tf @@ -6,7 +6,7 @@ locals { name_prefix = "${trimsuffix(var.name)}-" - create_custom_policy = var.create && length(var.statements) > 0 + create_custom_policy = var.create && (length(var.statements) > 0 || var.enable_read_ssm_params || var.enable_read_secrets || var.enable_write_log_streams || var.enable_pull_ecr_images) } data "aws_iam_policy_document" "assume_role" { @@ -48,6 +48,65 @@ resource "aws_iam_role_policy_attachment" "this" { data "aws_iam_policy_document" "custom" { count = local.create_custom_policy ? 1 : 0 + dynamic "statement" { + for_each = var.enable_write_log_streams ? [1] : [] + + content { + sid = "WriteLogs" + actions = [ + "logs:CreateLogStream", + "logs:PutLogEvents", + ] + resources = var.writable_log_streams + } + } + + dynamic "statement" { + for_each = var.enable_pull_ecr_images ? [1] : [] + + content { + sid = "GetECRToken" + actions = [ + "ecr:GetAuthorizationToken", + ] + resources = ["*"] + } + } + + dynamic "statement" { + for_each = var.enable_pull_ecr_images ? [1] : [] + + content { + sid = "PullECRImages" + actions = [ + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + ] + resources = var.pullable_ecr_images + } + } + + dynamic "statement" { + for_each = var.enable_read_ssm_params ? [1] : [] + + content { + sid = "GetSSMParams" + actions = ["ssm:GetParameters"] + resources = var.readable_ssm_params + } + } + + dynamic "statement" { + for_each = var.enable_read_secrets ? [1] : [] + + content { + sid = "GetSecrets" + actions = ["secretsmanager:GetSecretValue"] + resources = var.readable_secrets + } + } + dynamic "statement" { for_each = var.statements @@ -90,11 +149,19 @@ data "aws_iam_policy_document" "custom" { } } -resource "aws_iam_role_policy" "custom" { +resource "aws_iam_policy" "custom" { count = local.create_custom_policy ? 1 : 0 name = var.use_name_prefix ? null : var.name name_prefix = var.use_name_prefix ? local.name_prefix : null policy = data.aws_iam_policy_document.custom[0].json - role = aws_iam_role.this[0].id + description = "Task execution role IAM policy" + tags = var.tags +} + +resource "aws_iam_role_policy_attachment" "custom" { + count = local.create_custom_policy ? 1 : 0 + + role = aws_iam_role.this[0].id + policy_arn = aws_iam_policy.custom[0].arn } diff --git a/modules/execution-role/variables.tf b/modules/execution-role/variables.tf index a44fe66..cff84a6 100644 --- a/modules/execution-role/variables.tf +++ b/modules/execution-role/variables.tf @@ -65,3 +65,51 @@ variable "statements" { type = any default = {} } + +variable "enable_read_ssm_params" { + description = "Controls if the task execution role will be permitted to get/read SSM parameters" + type = bool + default = false +} + +variable "readable_ssm_params" { + description = "List of SSM parameter ARNs the task execution role will be permitted to get/read" + type = list(string) + default = ["arn:aws:ssm:*:*:parameter/*"] +} + +variable "enable_read_secrets" { + description = "Controls if the task execution role will be permitted to get/read SecretsManager secrets" + type = bool + default = false +} + +variable "readable_secrets" { + description = "List of SecretsManager secret ARNs the task execution role will be permitted to get/read" + type = list(string) + default = ["arn:aws:secretsmanager:*:*:secret:*"] +} + +variable "enable_write_log_streams" { + description = "Controls if the task execution role will be permitted to put/write CloudWatch log streams" + type = bool + default = false +} + +variable "writable_log_streams" { + description = "List of CloudWatch log streams the task execution role will be permitted to put/write" + type = list(string) + default = ["*"] +} + +variable "enable_pull_ecr_images" { + description = "Controls if the task execution role will be permitted to pull ECR private repositories" + type = bool + default = false +} + +variable "pullable_ecr_images" { + description = "List of ECR private repositories the task execution role will be permitted to pull" + type = list(string) + default = ["*"] +} diff --git a/modules/task-role/README.md b/modules/task-role/README.md index 769bf4f..e7e52fe 100644 --- a/modules/task-role/README.md +++ b/modules/task-role/README.md @@ -7,7 +7,7 @@ This submodule help create an IAM assumable role for ECS Task ```hcl module "task_role" { source = "rabiloo/ecs/aws//modules/task-role" - version = "~>0.3.0" + version = "~>0.3.1" name = "custom-ecs-task-role" path = "/service-roles/" @@ -17,6 +17,8 @@ module "task_role" { Managed = "Terraform" } + enable_execute_command = true + statements = { Logs = { actions = ["logs:CreateLogStream", "logs:PutLogEvents"] @@ -49,8 +51,9 @@ No modules. | Name | Type | |------|------| +| [aws_iam_policy.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -65,6 +68,7 @@ No modules. | [name](#input\_name) | The name of the IAM role | `string` | n/a | yes | | [create](#input\_create) | Determines whether resources will be created (affects all resources) | `bool` | `true` | no | | [description](#input\_description) | The description of the IAM role | `string` | `null` | no | +| [enable\_execute\_command](#input\_enable\_execute\_command) | Specifies whether to enable Amazon ECS Exec for the tasks within the service | `bool` | `false` | no | | [path](#input\_path) | The path to the IAM role | `string` | `"/"` | no | | [permissions\_boundary\_arn](#input\_permissions\_boundary\_arn) | The permissions boundary of the IAM role | `string` | `null` | no | | [policy\_arns](#input\_policy\_arns) | The list of IAM policy ARN be attached to IAM role | `map(string)` | `{}` | no | diff --git a/modules/task-role/main.tf b/modules/task-role/main.tf index 0a29eaa..05d11c2 100644 --- a/modules/task-role/main.tf +++ b/modules/task-role/main.tf @@ -13,7 +13,7 @@ locals { region = data.aws_region.current.name name_prefix = "${trimsuffix(var.name)}-" - create_custom_policy = var.create && length(var.statements) > 0 + create_custom_policy = var.create && (length(var.statements) > 0 || var.enable_execute_command) } data "aws_iam_policy_document" "assume_role" { @@ -66,7 +66,22 @@ resource "aws_iam_role_policy_attachment" "this" { } data "aws_iam_policy_document" "custom" { - count = var.create && length(var.statements) > 0 ? 1 : 0 + count = local.create_custom_policy ? 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.statements @@ -110,11 +125,19 @@ data "aws_iam_policy_document" "custom" { } } -resource "aws_iam_role_policy" "custom" { +resource "aws_iam_policy" "custom" { count = local.create_custom_policy ? 1 : 0 name = var.use_name_prefix ? null : var.name name_prefix = var.use_name_prefix ? local.name_prefix : null policy = data.aws_iam_policy_document.custom[0].json - role = aws_iam_role.this[0].id + description = "Task role IAM policy" + tags = var.tags +} + +resource "aws_iam_role_policy_attachment" "custom" { + count = local.create_custom_policy ? 1 : 0 + + role = aws_iam_role.this[0].id + policy_arn = aws_iam_policy.custom[0].arn } diff --git a/modules/task-role/variables.tf b/modules/task-role/variables.tf index a44fe66..02abcda 100644 --- a/modules/task-role/variables.tf +++ b/modules/task-role/variables.tf @@ -65,3 +65,9 @@ variable "statements" { type = any default = {} } + +variable "enable_execute_command" { + description = "Specifies whether to enable Amazon ECS Exec for the tasks within the service" + type = bool + default = false +}