diff --git a/modules/service_role/CHANGELOG.md b/modules/service_role/CHANGELOG.md new file mode 100644 index 0000000..f23c4aa --- /dev/null +++ b/modules/service_role/CHANGELOG.md @@ -0,0 +1,3 @@ +## [1.0] - 2021-11-21 + +* Creates a service role module diff --git a/modules/service_role/README.md b/modules/service_role/README.md new file mode 100644 index 0000000..fdf4ff1 --- /dev/null +++ b/modules/service_role/README.md @@ -0,0 +1,33 @@ +# Service Role + +This module provisions an IAM role that will be assumed by one or more AWS services. + +## Usage + +```terraform +module "service_role" { + source = "modules/service_role" + + role_name = "ecs-task-execution" + role_description = "ECS Task Execution Role" + services = ["ecs-tasks.amazonaws.com"] + + policies = { + pull_ecr_image = aws_iam_policy.pull_ecr_image.arn + } + + policy_documents = { + read_s3_bucket = data.aws_iam_policy_document.read_s3_bucket.json + } + + tags = { + environment = "staging" + } +} + +resource "aws_ecs_task_definition" "task" { + family = "my-ecs-task" + container_definitions = jsonencode([...]) + execution_role_arn = module.service_role.role_arn +} +``` diff --git a/modules/service_role/VERSION.txt b/modules/service_role/VERSION.txt new file mode 100644 index 0000000..d3827e7 --- /dev/null +++ b/modules/service_role/VERSION.txt @@ -0,0 +1 @@ +1.0 diff --git a/modules/service_role/main.tf b/modules/service_role/main.tf new file mode 100644 index 0000000..bd118aa --- /dev/null +++ b/modules/service_role/main.tf @@ -0,0 +1,42 @@ +locals { + // local.policy_attachment_quota will raise error during terraform plan if number of attachments exceeds 10 + total_policy_attachments = length(var.policies) + length(var.policy_documents) + policy_attachment_quota = coalesce(local.total_policy_attachments <= 10 ? "within quota" : null) +} + +resource "aws_iam_role" "main" { + name = var.role_name + description = var.role_description + assume_role_policy = data.aws_iam_policy_document.services_can_assume.json + tags = var.tags +} + +data "aws_iam_policy_document" "services_can_assume" { + statement { + sid = "AssumeRole" + actions = ["sts:AssumeRole"] + + principals { + type = "service" + identifiers = var.services + } + } +} + +resource "aws_iam_role_policy_attachment" "main" { + for_each = merge( + var.policies, + zipmap(var.policy_documents, aws_iam_policy.main[*].arn) + ) + + role = aws_iam_role.main.id + policy_arn = each.value +} + +resource "aws_iam_policy" "main" { + for_each = var.policy_documents + + name = each.key + policy = each.value + tags = var.tags +} diff --git a/modules/service_role/outputs.tf b/modules/service_role/outputs.tf new file mode 100644 index 0000000..846d34e --- /dev/null +++ b/modules/service_role/outputs.tf @@ -0,0 +1,3 @@ +output "role_arn" { + value = aws_iam_role.main.arn +} diff --git a/modules/service_role/variables.tf b/modules/service_role/variables.tf new file mode 100644 index 0000000..2bca90f --- /dev/null +++ b/modules/service_role/variables.tf @@ -0,0 +1,33 @@ +variable "role_name" { + type = string + description = "Name for IAM role" +} + +variable "role_description" { + type = string + description = "Description for IAM role" + default = "" +} + +variable "tags" { + type = map(string) + description = "Tags to be applied to IAM role and any IAM policies created" + default = {} +} + +variable "services" { + type = list(string) + description = "AWS services that can assume IAM role" +} + +variable "policies" { + type = map(string) + description = "IAM policies with an identifier as key and the policy ARN as value" + default = {} +} + +variable "policy_documents" { + type = map(string) + description = "IAM policy documents with an identifier as key and the policy document JSON as value" + default = {} +}