From c63eeb2d290b0efce0916729377eede4c519e54c Mon Sep 17 00:00:00 2001 From: Stretch Date: Tue, 2 Jan 2024 15:36:03 +0000 Subject: [PATCH] Conditionally enable SSM Default Host Management Configuration (#71) * By default, AWS Systems Manager doesn't have permission to perform actions on your instances. * Default Host Management Configuration allows Systems Manager to manage your Amazon EC2 instances automatically. * After you've turned on this setting, all instances using Instance Metadata Service Version 2 (IMDSv2) in the AWS Region and AWS account with SSM Agent version 3.2.582.0 or later installed automatically become managed instances. Benefits of managed instances include the following: * Connect to your instances securely using Session Manager. * Perform automated patch scans using Patch Manager. * View detailed information about your instances using Systems Manager Inventory. * Track and manage instances using Fleet Manager. * Keep the SSM Agent up to date automatically. --- README.md | 5 ++ locals.tf | 2 + .../service-principle-standard.json.tpl | 13 ++++++ policies/ssm-dhmc.json.tpl | 46 +++++++++++++++++++ ssm-dhmc.tf | 30 ++++++++++++ variables.tf | 5 ++ 6 files changed, 101 insertions(+) create mode 100644 policies/assume-roles/service-principle-standard.json.tpl create mode 100644 policies/ssm-dhmc.json.tpl create mode 100644 ssm-dhmc.tf diff --git a/README.md b/README.md index bed9739..4dd6d87 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,16 @@ for dxw's Dalmatian hosting platform. | [aws_iam_policy.cloudwatch_slack_alerts_logs_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.delete_default_resources_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.delete_default_resources_vpc_delete_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.ssm_dhmc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.cloudtrail_cloudwatch_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.cloudwatch_slack_alerts_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.delete_default_resources_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.ssm_dhmc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy_attachment.cloudtrail_cloudwatch_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.cloudwatch_slack_alerts_logs_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.delete_default_resources_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.delete_default_resources_vpc_delete_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.ssm_dhmc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_kms_alias.athena_cloudtrail_output](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | | [aws_kms_alias.cloudtrail_cloudwatch_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | | [aws_kms_alias.cloudwatch_opsgenie_alerts_sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | @@ -99,6 +102,7 @@ for dxw's Dalmatian hosting platform. | [aws_sns_topic_subscription.cloudwatch_opsgenie_alerts_subscription](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | | [aws_sns_topic_subscription.cloudwatch_opsgenie_alerts_subscription_us_east_1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | | [aws_sns_topic_subscription.cloudwatch_slack_alerts_lambda_subscription](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | +| [aws_ssm_service_setting.ssm_dhmc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_service_setting) | resource | | [archive_file.cloudwatch_slack_alerts_lambda](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | | [archive_file.delete_default_resources_lambda](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | @@ -130,6 +134,7 @@ for dxw's Dalmatian hosting platform. | [enable\_delete\_default\_resources](#input\_enable\_delete\_default\_resources) | Creates a Lambda function which deletes all default VPCs and resources within them. This only needs to be ran once, either through the AWS console or via the AWS CLI | `bool` | n/a | yes | | [enable\_route53\_root\_hosted\_zone](#input\_enable\_route53\_root\_hosted\_zone) | Conditionally create Route53 hosted zone, which will contain the DNS records for resources launched within the account. | `bool` | n/a | yes | | [enable\_s3\_tfvars](#input\_enable\_s3\_tfvars) | enable\_s3\_tfvars | `bool` | n/a | yes | +| [enable\_ssm\_dhmc](#input\_enable\_ssm\_dhmc) | Enables SSM Default Host Management Configuration | `bool` | n/a | yes | | [logging\_bucket\_retention](#input\_logging\_bucket\_retention) | Logging bucket retention in days. Set to 0 to keep all logs. | `number` | n/a | yes | | [project\_name](#input\_project\_name) | Project name to be used as a prefix for all resources | `string` | n/a | yes | | [route53\_root\_hosted\_zone\_domain\_name](#input\_route53\_root\_hosted\_zone\_domain\_name) | Route53 root hosted zone domain name | `string` | n/a | yes | diff --git a/locals.tf b/locals.tf index 0175484..d0b3bd8 100644 --- a/locals.tf +++ b/locals.tf @@ -64,6 +64,8 @@ locals { codestar_connections = var.codestar_connections + enable_ssm_dhmc = var.enable_ssm_dhmc + enable_logs_bucket = local.cloudtrail_s3_access_logs || local.cloudtrail_athena_glue_tables logging_bucket_retention = var.logging_bucket_retention logs_bucket_source_arns = concat( diff --git a/policies/assume-roles/service-principle-standard.json.tpl b/policies/assume-roles/service-principle-standard.json.tpl new file mode 100644 index 0000000..0801c45 --- /dev/null +++ b/policies/assume-roles/service-principle-standard.json.tpl @@ -0,0 +1,13 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": ${services} + }, + "Action": "sts:AssumeRole" + } + ] +} diff --git a/policies/ssm-dhmc.json.tpl b/policies/ssm-dhmc.json.tpl new file mode 100644 index 0000000..1195565 --- /dev/null +++ b/policies/ssm-dhmc.json.tpl @@ -0,0 +1,46 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ssm:DescribeAssociation", + "ssm:GetDeployablePatchSnapshotForInstance", + "ssm:GetDocument", + "ssm:DescribeDocument", + "ssm:GetManifest", + "ssm:ListAssociations", + "ssm:ListInstanceAssociations", + "ssm:PutInventory", + "ssm:PutComplianceItems", + "ssm:PutConfigurePackageResult", + "ssm:UpdateAssociationStatus", + "ssm:UpdateInstanceAssociationStatus", + "ssm:UpdateInstanceInformation" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ec2messages:AcknowledgeMessage", + "ec2messages:DeleteMessage", + "ec2messages:FailMessage", + "ec2messages:GetEndpoint", + "ec2messages:GetMessages", + "ec2messages:SendReply" + ], + "Resource": "*" + } + ] +} diff --git a/ssm-dhmc.tf b/ssm-dhmc.tf new file mode 100644 index 0000000..f37623f --- /dev/null +++ b/ssm-dhmc.tf @@ -0,0 +1,30 @@ +resource "aws_iam_role" "ssm_dhmc" { + count = local.enable_ssm_dhmc ? 1 : 0 + + name = "${local.project_name}-ssm-dhmc" + assume_role_policy = templatefile( + "${path.root}/policies/assume-roles/service-principle-standard.json.tpl", + { services = jsonencode(["ssm.amazonaws.com"]) } + ) +} + +resource "aws_iam_policy" "ssm_dhmc" { + count = local.enable_ssm_dhmc ? 1 : 0 + + name = "${local.project_name}-ssm-dhmc" + policy = templatefile("${path.root}/policies/ssm-dhmc.json.tpl", {}) +} + +resource "aws_iam_role_policy_attachment" "ssm_dhmc" { + count = local.enable_ssm_dhmc ? 1 : 0 + + role = aws_iam_role.ssm_dhmc[0].name + policy_arn = aws_iam_policy.ssm_dhmc[0].arn +} + +resource "aws_ssm_service_setting" "ssm_dhmc" { + count = local.enable_ssm_dhmc ? 1 : 0 + + setting_id = "arn:aws:ssm:${local.aws_region}:${local.aws_account_id}:servicesetting/ssm/managed-instance/default-ec2-instance-management-role" + setting_value = aws_iam_role.ssm_dhmc[0].name +} diff --git a/variables.tf b/variables.tf index dde98fc..9f8b7c3 100644 --- a/variables.tf +++ b/variables.tf @@ -157,6 +157,11 @@ variable "codestar_connections" { ) } +variable "enable_ssm_dhmc" { + description = "Enables SSM Default Host Management Configuration" + type = bool +} + variable "logging_bucket_retention" { description = "Logging bucket retention in days. Set to 0 to keep all logs." type = number