From d169819beb375867bb557291061485ea4355f746 Mon Sep 17 00:00:00 2001 From: Leo Cao Date: Fri, 22 Sep 2023 15:20:45 +1000 Subject: [PATCH] feat: bind existing aws policy to role --- README.md | 14 ++++-- examples/deployer_roles/README.md | 33 +++++++++++++ examples/deployer_roles/ecs_deployer.tf | 49 +++++++++++++++++++ examples/human_roles/README.md | 29 +++++++++++ examples/human_roles/amplify_admin.tf | 9 ++++ examples/service_roles/README.md | 33 +++++++++++++ .../service_roles/lambda_service_roles.tf | 20 ++++++++ main.tf | 18 ++++++- variables.tf | 26 ++++++---- 9 files changed, 216 insertions(+), 15 deletions(-) create mode 100644 examples/deployer_roles/README.md create mode 100644 examples/deployer_roles/ecs_deployer.tf create mode 100644 examples/human_roles/README.md create mode 100644 examples/human_roles/amplify_admin.tf create mode 100644 examples/service_roles/README.md create mode 100644 examples/service_roles/lambda_service_roles.tf diff --git a/README.md b/README.md index cd1a974..cda0a25 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Terraform Module: IAM Role -This is a Terraform module for creating custom AWS IAM roles. +This is DAQ's Terraform Module for AWS IAM role management. + +This repo provides a template for other Terraform repos to create IAM roles. ## Install @@ -11,7 +13,11 @@ This is a Terraform module for creating custom AWS IAM roles. ## Usage This module creates an IAM Role and its policy document. -You need to pass your custom policy document to the module. +You need to pass your custom policy document or a list of AWS pre-defined policies to the module. + +## Example + +See [examples](./examples/). ## Requirements @@ -35,8 +41,9 @@ No modules. | Name | Type | |------|------| | [aws_iam_policy.custom_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy_attachment.custom_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | +| [aws_iam_policy_attachment.custom_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | | [aws_iam_role.custom_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.existing_policy_attachment](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 | @@ -45,6 +52,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [arns\_assume\_role](#input\_arns\_assume\_role) | List of ARNs of IAM entities that can assume the role | `list(string)` | `[]` | no | +| [existing\_iam\_policy\_arns](#input\_existing\_iam\_policy\_arns) | List of ARNs of existing IAM policies | `list(string)` | `[]` | no | | [iam\_policy\_document](#input\_iam\_policy\_document) | Custom IAM policy document | `string` | `""` | no | | [name\_prefix](#input\_name\_prefix) | Name prefix for IAM role name | `string` | `""` | no | | [role\_description](#input\_role\_description) | An optional IAM role description | `string` | `""` | no | diff --git a/examples/deployer_roles/README.md b/examples/deployer_roles/README.md new file mode 100644 index 0000000..096aa26 --- /dev/null +++ b/examples/deployer_roles/README.md @@ -0,0 +1,33 @@ +# deployer_roles + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [devops\_infra\_deploy](#module\_devops\_infra\_deploy) | ../.. | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_policy_document.ecs_infra_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +No inputs. + +## Outputs + +No outputs. + diff --git a/examples/deployer_roles/ecs_deployer.tf b/examples/deployer_roles/ecs_deployer.tf new file mode 100644 index 0000000..e2897af --- /dev/null +++ b/examples/deployer_roles/ecs_deployer.tf @@ -0,0 +1,49 @@ +data "aws_iam_policy_document" "ecs_infra_role_policy" { + statement { + resources = ["arn:aws:s3:::ecs-infrastructre"] + actions = [ + "s3:ListBucket", + ] + } + + statement { + resources = ["arn:aws:s3:::ecs-infrastructre/*"] + actions = [ + "s3:Get*", + "s3:Put*", + "s3:Delete*", + ] + } + + statement { + resources = ["arn:aws:iam::000000000000:role/service_roles/*"] + actions = ["iam:PassRole"] + } + + // enable VPCs, subnets, route tables and internet gateways creation + statement { + resources = ["*"] + actions = [ + "ec2:Describe*", + "ec2:Create*", + "ec2:Delete*", + "ec2:AttachInternetGateway", + "ec2:AssociateRouteTable", + "ec2:ModifyVpcAttribute", + "ec2:DisableVpcClassicLink", + "ec2:DisableVpcClassicLinkDnsSupport", + "ec2:EnableVpcClassicLink", + "ec2:EnableVpcClassicLinkDnsSupport", + ] + } +} + +module "devops_infra_deploy" { + source = "../.." + + name_prefix = "ecsInfraDeploy" + role_path = "/ecs/" + role_description = "Role for deploying ECS infrastructure" + iam_policy_document = data.aws_iam_policy_document.ecs_infra_role_policy.json + arns_assume_role = ["arn:aws:iam::000000000000:root"] +} diff --git a/examples/human_roles/README.md b/examples/human_roles/README.md new file mode 100644 index 0000000..25dc6b0 --- /dev/null +++ b/examples/human_roles/README.md @@ -0,0 +1,29 @@ +# human_roles + + +## Requirements + +No requirements. + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [amplify\_and\_cognito\_admin](#module\_amplify\_and\_cognito\_admin) | ../.. | n/a | + +## Resources + +No resources. + +## Inputs + +No inputs. + +## Outputs + +No outputs. + diff --git a/examples/human_roles/amplify_admin.tf b/examples/human_roles/amplify_admin.tf new file mode 100644 index 0000000..6803512 --- /dev/null +++ b/examples/human_roles/amplify_admin.tf @@ -0,0 +1,9 @@ +module "amplify_and_cognito_admin" { + source = "../.." + + name_prefix = "amplifyAdmin" + role_path = "/human/" + role_description = "Role for granting admin access on Amplify" + existing_iam_policy_arns = ["arn:aws:iam::aws:policy/AdministratorAccess-Amplify"] + arns_assume_role = ["arn:aws:iam::000000000000:root"] +} diff --git a/examples/service_roles/README.md b/examples/service_roles/README.md new file mode 100644 index 0000000..dc01258 --- /dev/null +++ b/examples/service_roles/README.md @@ -0,0 +1,33 @@ +# service_roles + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [lambda\_auto\_link\_data\_iam\_role](#module\_lambda\_auto\_link\_data\_iam\_role) | ../.. | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_policy_document.lambda_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +No inputs. + +## Outputs + +No outputs. + diff --git a/examples/service_roles/lambda_service_roles.tf b/examples/service_roles/lambda_service_roles.tf new file mode 100644 index 0000000..937e941 --- /dev/null +++ b/examples/service_roles/lambda_service_roles.tf @@ -0,0 +1,20 @@ +data "aws_iam_policy_document" "lambda_policy" { + statement { + actions = [ + "logs:CreateLogStream", + "logs:PutLogEvents", + ] + + resources = ["*"] + } +} + +module "lambda_auto_link_data_iam_role" { + source = "../.." + + name_prefix = "myLambda" + role_path = "/service_roles/" + role_description = "Allows resources to log to log groups" + iam_policy_document = data.aws_iam_policy_document.lambda_policy.json + services_assume_role = ["lambda.amazonaws.com"] +} diff --git a/main.tf b/main.tf index fa69389..6c99771 100644 --- a/main.tf +++ b/main.tf @@ -8,14 +8,28 @@ resource "aws_iam_role" "custom_role" { } resource "aws_iam_policy" "custom_policy" { + for_each = var.iam_policy_document == "" ? {} : { "policy" : true } + name = "${var.name_prefix}Policy" path = "/" policy = var.iam_policy_document } -resource "aws_iam_policy_attachment" "custom_attachment" { +resource "aws_iam_policy_attachment" "custom_policy_attachment" { + for_each = var.iam_policy_document == "" ? {} : { "attachment" : true } + name = "${var.name_prefix}Attachment" roles = [aws_iam_role.custom_role.name] - policy_arn = aws_iam_policy.custom_policy.arn + policy_arn = aws_iam_policy.custom_policy["policy"].arn + depends_on = [aws_iam_role.custom_role, aws_iam_policy.custom_policy] } + +resource "aws_iam_role_policy_attachment" "existing_policy_attachment" { + for_each = var.existing_iam_policy_arns == [] ? toset([]) : toset(var.existing_iam_policy_arns) + + role = aws_iam_role.custom_role.name + policy_arn = each.key + + depends_on = [aws_iam_role.custom_role] +} diff --git a/variables.tf b/variables.tf index b5c006f..a262762 100644 --- a/variables.tf +++ b/variables.tf @@ -1,35 +1,41 @@ variable "name_prefix" { - default = "" - description = "Name prefix for IAM role name" type = string + description = "Name prefix for IAM role name" + default = "" } variable "role_path" { - default = "" - description = "An optional IAM role path" type = string + description = "An optional IAM role path" + default = "" } variable "role_description" { - default = "" - description = "An optional IAM role description" type = string + description = "An optional IAM role description" + default = "" } variable "iam_policy_document" { - default = "" - description = "Custom IAM policy document" type = string + description = "Custom IAM policy document" + default = "" } -variable "arns_assume_role" { +variable "existing_iam_policy_arns" { + type = list(string) + description = "List of ARNs of existing IAM policies" default = [] +} + +variable "arns_assume_role" { type = list(string) description = "List of ARNs of IAM entities that can assume the role" + default = [] } variable "services_assume_role" { - default = [] type = list(string) description = "List of services that can assume the role" + default = [] }