From b31cd721d79be8a927d36a5b62b3fcedbf4fbe86 Mon Sep 17 00:00:00 2001 From: Michael Barrientos Date: Tue, 24 Mar 2020 10:46:14 -0700 Subject: [PATCH] [breaking] [feature] aws-iam-instance-profile reuse existing role and remove SSM support (#183) * Allows passing an existing role to aws-iam-instance-profile, and the module will attach whatever permissions are needed. This allows using roles that are created and managed by other modules (e.g. EKS worker role), but provides ability to attach a standard set of permissions to that role. It will still always create the instance profile, even if the profile will be unused. * Removes unused permissions from the aws-iam-instance-profile module for using SSM. --- aws-iam-instance-profile/README.md | 3 +- aws-iam-instance-profile/main.tf | 112 ++---------------------- aws-iam-instance-profile/module_test.go | 16 ---- aws-iam-instance-profile/outputs.tf | 4 +- aws-iam-instance-profile/variables.tf | 18 ++-- 5 files changed, 23 insertions(+), 130 deletions(-) diff --git a/aws-iam-instance-profile/README.md b/aws-iam-instance-profile/README.md index 7e93f1f1..978be86f 100644 --- a/aws-iam-instance-profile/README.md +++ b/aws-iam-instance-profile/README.md @@ -39,7 +39,8 @@ resource "aws_instance" "instance" { | Name | Description | Type | Default | Required | |------|-------------|------|---------|:-----:| -| enable\_ssm | Attach the appropriate policies to allow the instance to integrate with AWS Systems Manager. | `string` | `"true"` | no | +| create\_role | Creates a role for use with the instance profile. | `bool` | `true` | no | +| existing\_role\_name | Use existing role with the given name instead of creating a new role. Attaches all standard policies to given role. Only used if create\_role is false. | `string` | n/a | yes | | iam\_path | The IAM path to the role. | `string` | `"/"` | no | | name\_prefix | Creates a unique name for both the role and instance profile beginning with the specified prefix. Max 32 characters long. | `string` | n/a | yes | | role\_description | The description of the IAM role. | `string` | `""` | no | diff --git a/aws-iam-instance-profile/main.tf b/aws-iam-instance-profile/main.tf index ed8d0061..7d19f562 100755 --- a/aws-iam-instance-profile/main.tf +++ b/aws-iam-instance-profile/main.tf @@ -1,3 +1,7 @@ +locals { + role_name = coalescelist(aws_iam_role.role[*].name, [var.existing_role_name])[0] +} + data "aws_iam_policy_document" "assume-role" { statement { sid = "AssumeRole" @@ -11,6 +15,7 @@ data "aws_iam_policy_document" "assume-role" { } resource "aws_iam_role" "role" { + count = var.create_role ? 1 : 0 name_prefix = var.name_prefix description = var.role_description path = var.iam_path @@ -21,120 +26,17 @@ resource "aws_iam_role" "role" { } } -resource "aws_iam_role_policy" "ssm" { - count = var.enable_ssm ? 1 : 0 - role = aws_iam_role.role.name - policy = data.aws_iam_policy_document.ssm_policy.json -} - resource "aws_iam_role_policy_attachment" "cloudwatch-agent" { - role = aws_iam_role.role.name + role = local.role_name policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy" } resource "aws_iam_instance_profile" "profile" { name_prefix = var.name_prefix path = var.iam_path - role = aws_iam_role.role.name + role = local.role_name lifecycle { ignore_changes = [name, name_prefix, path] } } - -data "aws_iam_policy_document" "ssm_policy" { - statement { - actions = [ - "ssm:DescribeAssociation", - "ssm:GetDeployablePatchSnapshotForInstance", - "ssm:GetDocument", - "ssm:DescribeDocument", - "ssm:GetManifest", - "ssm:GetParameters", - "ssm:ListAssociations", - "ssm:ListInstanceAssociations", - "ssm:PutInventory", - "ssm:PutComplianceItems", - "ssm:PutConfigurePackageResult", - "ssm:UpdateAssociationStatus", - "ssm:UpdateInstanceAssociationStatus", - "ssm:UpdateInstanceInformation", - ] - - resources = ["*"] - } - - statement { - actions = [ - "ssmmessages:CreateControlChannel", - "ssmmessages:CreateDataChannel", - "ssmmessages:OpenControlChannel", - "ssmmessages:OpenDataChannel", - ] - - resources = ["*"] - } - - statement { - actions = [ - "ec2messages:AcknowledgeMessage", - "ec2messages:DeleteMessage", - "ec2messages:FailMessage", - "ec2messages:GetEndpoint", - "ec2messages:GetMessages", - "ec2messages:SendReply", - ] - - resources = ["*"] - } - - statement { - actions = ["cloudwatch:PutMetricData"] - - resources = ["*"] - } - - statement { - actions = ["ec2:DescribeInstanceStatus"] - - resources = ["*"] - } - - statement { - actions = [ - "ds:CreateComputer", - "ds:DescribeDirectories", - ] - - resources = ["*"] - } - - statement { - actions = [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:DescribeLogGroups", - "logs:DescribeLogStreams", - "logs:PutLogEvents", - ] - - resources = ["*"] - } - - statement { - actions = [ - "s3:GetObject", - "s3:ListBucket", - ] - - //https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent-minimum-s3-permissions.html - resources = [ - "arn:aws:s3:::aws-ssm-*/*", - "arn:aws:s3:::aws-windows-downloads-*/*", - "arn:aws:s3:::amazon-ssm-*/*", - "arn:aws:s3:::amazon-ssm-packages-*/*", - "arn:aws:s3:::*-birdwatcher-prod/*", - "arn:aws:s3:::patch-baseline-snapshot-*/*", - ] - } -} diff --git a/aws-iam-instance-profile/module_test.go b/aws-iam-instance-profile/module_test.go index f37f97ca..ed0d9298 100644 --- a/aws-iam-instance-profile/module_test.go +++ b/aws-iam-instance-profile/module_test.go @@ -22,19 +22,3 @@ func TestAWSIAMInstanceProfile(t *testing.T) { testutil.Run(t, terraformOptions) } - -func TestAWSIAMInstanceProfileDisableSSM(t *testing.T) { - terraformOptions := testutil.Options( - testutil.IAMRegion, - map[string]interface{}{ - "name_prefix": random.UniqueId(), - "iam_path": "/foo/", - "role_description": random.UniqueId(), - "enable_ssm": "false", - }, - ) - - defer terraform.Destroy(t, terraformOptions) - - testutil.Run(t, terraformOptions) -} diff --git a/aws-iam-instance-profile/outputs.tf b/aws-iam-instance-profile/outputs.tf index 3f30f413..d63d0162 100755 --- a/aws-iam-instance-profile/outputs.tf +++ b/aws-iam-instance-profile/outputs.tf @@ -1,10 +1,10 @@ output "role_arn" { - value = aws_iam_role.role.arn + value = coalescelist(aws_iam_role.role[*].arn, [""])[0] description = "The Amazon Resource Name (ARN) specifying the role." } output "role_name" { - value = aws_iam_role.role.name + value = local.role_name description = "The name of the role." } diff --git a/aws-iam-instance-profile/variables.tf b/aws-iam-instance-profile/variables.tf index c4bc1f5f..ffeaffc2 100755 --- a/aws-iam-instance-profile/variables.tf +++ b/aws-iam-instance-profile/variables.tf @@ -3,6 +3,18 @@ variable "name_prefix" { description = "Creates a unique name for both the role and instance profile beginning with the specified prefix. Max 32 characters long." } +variable "existing_role_name" { + type = string + description = "Use existing role with the given name instead of creating a new role. Attaches all standard policies to given role. Only used if create_role is false." + default = null +} + +variable "create_role" { + type = bool + description = "Creates a role for use with the instance profile." + default = true +} + variable "iam_path" { type = string default = "/" @@ -14,9 +26,3 @@ variable "role_description" { description = "The description of the IAM role." default = "" } - -variable "enable_ssm" { - type = string - description = "Attach the appropriate policies to allow the instance to integrate with AWS Systems Manager." - default = "true" -}