From bec34b8bf2c7e58cca9965b09f25082e2a00cc37 Mon Sep 17 00:00:00 2001 From: tknguyen Date: Wed, 5 Jun 2024 09:03:21 -0500 Subject: [PATCH 1/3] initial config_org --- .../aggregator_org_configuration/data.tf | 9 + .../aggregator_org_configuration/main.tf | 36 ++ .../aggregator_org_configuration/providers.tf | 17 + .../aggregator_org_configuration/variables.tf | 27 + .../config_org/configuration/data.tf | 9 + .../config_org/configuration/invoke.tf | 30 ++ .../config_org/configuration/main.tf | 496 ++++++++++++++++++ .../config_org/configuration/providers.tf | 17 + .../config_org/configuration/variables.tf | 180 +++++++ .../config_org/configuration_role/data.tf | 9 + .../config_org/configuration_role/main.tf | 145 +++++ .../configuration_role/providers.tf | 17 + .../configuration_role/variables.tf | 54 ++ .../terraform/solutions/config_org/data.tf | 14 + .../config_org/delivery_kms_key/data.tf | 9 + .../config_org/delivery_kms_key/main.tf | 133 +++++ .../config_org/delivery_kms_key/providers.tf | 17 + .../config_org/delivery_kms_key/variables.tf | 36 ++ .../config_org/delivery_s3_bucket/data.tf | 9 + .../config_org/delivery_s3_bucket/main.tf | 116 ++++ .../delivery_s3_bucket/providers.tf | 17 + .../delivery_s3_bucket/variables.tf | 31 ++ .../config_org/global_events/data.tf | 9 + .../config_org/global_events/main.tf | 30 ++ .../config_org/global_events/providers.tf | 17 + .../config_org/global_events/variables.tf | 21 + .../terraform/solutions/config_org/main.tf | 62 +++ .../config_org/org_sns-kms-key/data.tf | 9 + .../config_org/org_sns-kms-key/main.tf | 60 +++ .../config_org/org_sns-kms-key/providers.tf | 17 + .../config_org/org_sns-kms-key/variables.tf | 21 + .../solutions/config_org/providers.tf | 14 + .../solutions/config_org/sns/data.tf | 9 + .../solutions/config_org/sns/main.tf | 36 ++ .../solutions/config_org/sns/providers.tf | 17 + .../solutions/config_org/sns/variables.tf | 32 ++ .../solutions/config_org/variables.tf | 231 ++++++++ 37 files changed, 2013 insertions(+) create mode 100644 aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/data.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/main.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/providers.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/variables.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/configuration/data.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/configuration/invoke.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/configuration/main.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/configuration/providers.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/configuration/variables.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/configuration_role/data.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/configuration_role/main.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/configuration_role/providers.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/configuration_role/variables.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/data.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/data.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/main.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/providers.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/variables.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/data.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/main.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/providers.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/variables.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/global_events/data.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/global_events/main.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/global_events/providers.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/global_events/variables.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/main.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/org_sns-kms-key/data.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/org_sns-kms-key/main.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/org_sns-kms-key/providers.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/org_sns-kms-key/variables.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/providers.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/sns/data.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/sns/main.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/sns/providers.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/sns/variables.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/variables.tf diff --git a/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/data.tf b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/data.tf new file mode 100644 index 00000000..97f34e1e --- /dev/null +++ b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/data.tf @@ -0,0 +1,9 @@ +######################################################################## +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +######################################################################## + +data "aws_partition" "current" {} +data "aws_caller_identity" "current" {} +data "aws_region" "current" {} +data "aws_organizations_organization" "current" {} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/main.tf b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/main.tf new file mode 100644 index 00000000..178036dc --- /dev/null +++ b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/main.tf @@ -0,0 +1,36 @@ +######################################################################## +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +######################################################################## +resource "aws_iam_role" "r_config_aggregator_role" { + name = var.p_aggregator_role_name + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = "sts:AssumeRole" + Principal = { + Service = "config.amazonaws.com" + } + } + ] + }) + + managed_policy_arns = [ + "arn:aws:iam::aws:policy/service-role/AWSConfigRoleForOrganizations" + ] + + tags = { + "${var.p_sra_solution_name_key}" = var.p_sra_solution_name + } +} + +resource "aws_config_configuration_aggregator" "r_organization_config_aggregator" { + name = var.p_aggregator_name + + account_aggregation_source { + account_ids = [data.aws_caller_identity.current.account_id] + regions = ["all"] + } +} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/providers.tf b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/providers.tf new file mode 100644 index 00000000..35e5eb9e --- /dev/null +++ b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/providers.tf @@ -0,0 +1,17 @@ +######################################################################## +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +######################################################################## + +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.1.0" + + tags = { + "sra-solution" = var.p_sra_solution_name + } + } + } +} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/variables.tf b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/variables.tf new file mode 100644 index 00000000..d8bb029b --- /dev/null +++ b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/variables.tf @@ -0,0 +1,27 @@ +######################################################################## +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +######################################################################## +variable "p_aggregator_name" { + type = string + description = "Config Aggregator Name" + default = "sra-config-aggregator-org" +} + +variable "p_aggregator_role_name" { + type = string + description = "Config Aggregator Role Name" + default = "sra-config-aggregator-org" +} + +variable "p_sra_solution_name" { + type = string + description = "The SRA solution name. The default value is the folder name of the solution" + default = "sra-config-aggregator-org" +} + +variable "p_sra_solution_name_key" { + type = string + description = "The key used for tagging resources with the SRA solution name." + default = "sra-solution" +} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration/data.tf b/aws_sra_examples/terraform/solutions/config_org/configuration/data.tf new file mode 100644 index 00000000..97f34e1e --- /dev/null +++ b/aws_sra_examples/terraform/solutions/config_org/configuration/data.tf @@ -0,0 +1,9 @@ +######################################################################## +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +######################################################################## + +data "aws_partition" "current" {} +data "aws_caller_identity" "current" {} +data "aws_region" "current" {} +data "aws_organizations_organization" "current" {} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration/invoke.tf b/aws_sra_examples/terraform/solutions/config_org/configuration/invoke.tf new file mode 100644 index 00000000..28331ead --- /dev/null +++ b/aws_sra_examples/terraform/solutions/config_org/configuration/invoke.tf @@ -0,0 +1,30 @@ +######################################################################## +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +######################################################################## + +resource "aws_lambda_invocation" "new_lambda_invoke" { + function_name = aws_lambda_function.r_config_org_lambda_function.function_name + + input = jsonencode({ + "RequestType" : "Create", + "ResourceType" : "Custom::LambdaCustomResource", + "ResourceProperties" : { + "ServiceToken" : "${aws_lambda_function.r_config_org_lambda_function.arn}", + "AUDIT_ACCOUNT" : "${var.p_audit_account_id}", + "CONFIGURATION_ROLE_NAME" : "${var.p_config_configuration_role_name}", + "CONTROL_TOWER_REGIONS_ONLY" : "${var.p_control_tower_regions_only}", + "ENABLED_REGIONS" : "${var.p_enabled_regions}", + "ALL_SUPPORTED" : "${var.p_all_supported}", + "INCLUDE_GLOBAL_RESOURCE_TYPES" : "${var.p_include_global_resource_types}", + "DELIVERY_CHANNEL_NAME" : "${var.p_delivery_channel_name}", + "FREQUENCY" : "${var.p_frequency}", + "RESOURCE_TYPES" : "${var.p_resource_types}", + "RECORDER_NAME" : "${var.p_recorder_name}", + "KMS_KEY_SECRET_NAME" : "${var.p_kms_key_arn_secret_name}", + "HOME_REGION" : "${var.p_home_region}", + "SNS_TOPIC_ARN_FANOUT" : "${aws_sns_topic.r_config_org_topic.arn}", + "PUBLISHING_DESTINATION_BUCKET_ARN" : "arn:aws:s3:::${var.p_publishing_destination_bucket_name}" + } + }) +} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration/main.tf b/aws_sra_examples/terraform/solutions/config_org/configuration/main.tf new file mode 100644 index 00000000..40c19ede --- /dev/null +++ b/aws_sra_examples/terraform/solutions/config_org/configuration/main.tf @@ -0,0 +1,496 @@ +######################################################################## +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +######################################################################## +locals { + graviton_regions = [ + "ap-northeast-1", + "ap-south-1", + "ap-southeast-1", + "ap-southeast-2", + "eu-central-1", + "eu-west-1", + "eu-west-2", + "us-east-1", + "us-east-2", + "us-west-2", + ] + account_id = data.aws_caller_identity.current.account_id + region = data.aws_region.current.name + src_path = "${path.root}/../../solutions/config/config_org/lambda/src/" + + compliance_frequency_single_day = var.p_compliance_frequency == 1 + create_dlq_alarm = var.p_sra_alarm_email != "" + create_lambda_log_group = var.p_create_lambda_log_group == "true" + is_all_supported = var.p_all_supported == "true" + use_graviton = contains(local.graviton_regions, data.aws_region.current.name) + use_kms_key = var.p_lambda_log_group_kms_key != "" + not_global_region_us_east_1 = data.aws_region.current.name != "us-east-1" +} + +resource "aws_cloudwatch_log_group" "r_config_org_lambda_log_group" { + count = local.create_lambda_log_group ? 1 : 0 + name = "/aws/lambda/${var.p_config_org_lambda_function_name}" + retention_in_days = var.p_lambda_log_group_retention + kms_key_id = local.use_kms_key != "" ? var.p_lambda_log_group_kms_key : null + lifecycle { + prevent_destroy = true + } +} + +######################################################################## +# Lambda Policies Documents +######################################################################## +resource "aws_iam_role" "r_config_org_lambda_role" { + name = var.p_config_org_lambda_role_name + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Action = "sts:AssumeRole", + Effect = "Allow", + Principal = { + Service = ["lambda.amazonaws.com"] + } + } + ] + }) +} + +resource "aws_iam_role" "r_config_org_lambda_role" { + name = var.p_config_org_lambda_role_name + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Action = "sts:AssumeRole", + Effect = "Allow", + Principal = { + Service = ["lambda.amazonaws.com"] + } + } + ] + }) + path = "/" +} + +resource "aws_iam_policy" "sra_config_org_policy_organizations" { + name = "sra-config-org-policy-organizations" + description = "IAM policy for Macie Org Lambda Organizations" + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "OrganizationsReadAccess" + Effect = "Allow" + Action = [ + "organizations:DescribeAccount", + "organizations:ListAccounts" + ] + Resource = "*" + } + ] + }) +} + +resource "aws_iam_policy" "ssm_access" { + name = "ssm-access" + description = "IAM policy for SSM access" + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = [ + "ssm:GetParameter", + "ssm:GetParameters" + ], + Resource = [ + "arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter/sra*" + ] + } + ] + }) +} + +resource "aws_iam_policy" "sra_config_org_policy_sns" { + name = "sra-config-org-policy-sns" + description = "IAM policy for SNS access" + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "SNSPublish" + Effect = "Allow" + Action = [ + "sns:Publish", + "sns:PublishBatch" + ], + Resource = aws_sns_topic.r_config_org_topic.arn + } + ] + }) +} + +resource "aws_iam_policy" "sra_config_org_policy_iam" { + name = "sra-config-org-policy-iam" + description = "IAM policy for IAM access" + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "AssumeRole" + Effect = "Allow" + Action = ["sts:AssumeRole"] + Condition = { + StringEquals = { + "aws:PrincipalOrgId" = var.p_organization_id + } + }, + Resource = [ + "arn:aws:iam::*:role/${var.p_config_configuration_role_name}" + ] + }, + { + Sid = "AllowReadIamActions" + Effect = "Allow" + Action = ["iam:GetRole"] + Resource = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/*" + }, + { + Sid = "AllowCreateServiceLinkedRole" + Effect = "Allow" + Action = ["iam:CreateServiceLinkedRole"] + Condition = { + StringLike = { + "iam:AWSServiceName" = "config.amazonaws.com" + } + }, + Resource = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig" + }, + { + Sid = "AllowPolicyActions" + Effect = "Allow" + Action = ["iam:PutRolePolicy"] + Resource = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig" + } + ] + }) +} + +resource "aws_iam_policy" "sra_config_org_policy_logs" { + name = "sra-config-org-policy-logs" + description = "IAM policy for logs access" + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "CreateLogGroupAndEvents" + Effect = "Allow" + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + Resource = "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:/aws/lambda/${var.p_config_org_lambda_function_name}:log-stream:*" + } + ] + }) +} + +resource "aws_iam_policy" "sra_config_org_policy_sqs" { + name = "sra-config-org-policy-sqs" + description = "IAM policy for SQS access" + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "SQSSendMessage" + Effect = "Allow" + Action = ["sqs:SendMessage"], + Resource = aws_sqs_queue.r_config_org_dlq.arn + } + ] + }) +} + +######################################################################## +# Policy Attachment +######################################################################## +resource "aws_iam_role_policy_attachment" "r_config_org_lambda_role_organizations" { + role = aws_iam_role.r_config_org_lambda_role.name + policy_arn = aws_iam_policy.sra_config_org_policy_organizations.arn +} + +resource "aws_iam_role_policy_attachment" "r_config_org_lambda_role_ssm_access" { + role = aws_iam_role.r_config_org_lambda_role.name + policy_arn = aws_iam_policy.ssm_access.arn +} + +resource "aws_iam_role_policy_attachment" "r_config_org_lambda_role_sns" { + role = aws_iam_role.r_config_org_lambda_role.name + policy_arn = aws_iam_policy.sra_config_org_policy_sns.arn +} + +resource "aws_iam_role_policy_attachment" "r_config_org_lambda_role_iam" { + role = aws_iam_role.r_config_org_lambda_role.name + policy_arn = aws_iam_policy.sra_config_org_policy_iam.arn +} + +resource "aws_iam_role_policy_attachment" "r_config_org_lambda_role_logs" { + role = aws_iam_role.r_config_org_lambda_role.name + policy_arn = aws_iam_policy.sra_config_org_policy_logs.arn +} + +resource "aws_iam_role_policy_attachment" "r_config_org_lambda_role_sqs" { + role = aws_iam_role.r_config_org_lambda_role.name + policy_arn = aws_iam_policy.sra_config_org_policy_sqs.arn +} + +######################################################################## +# Lambda Function +######################################################################## +data "archive_file" "hash_check" { + type = "zip" + source_dir = local.src_path + output_path = "${path.module}/lambda/lambda_function.zip" + excludes = ["lambda_function.zip, data.zip"] +} + +resource "null_resource" "package_lambda" { + triggers = { + src_hash = "${data.archive_file.hash_check.output_sha}" + } + + provisioner "local-exec" { + command = < Date: Fri, 19 Jul 2024 16:01:22 -0500 Subject: [PATCH 2/3] Config Org Solution for testing --- .../config/config_org/lambda/src/app.py | 5 +- aws_sra_examples/terraform/common/main.tf | 3 +- .../terraform/common/variables.tf | 14 +- .../solutions/cloudtrail_org/org/main.tf | 2 +- .../solutions/cloudtrail_org/s3/main.tf | 2 +- .../aggregator_org_configuration/main.tf | 8 +- .../aggregator_org_configuration/providers.tf | 4 - .../config_org/configuration/invoke.tf | 1 + .../config_org/configuration/main.tf | 167 ++++++++---------- .../config_org/configuration/providers.tf | 3 - .../config_org/configuration/variables.tf | 11 +- .../config_org/configuration_role/main.tf | 30 ++-- .../configuration_role/providers.tf | 3 - .../configuration_role/variables.tf | 6 - .../config_org/delivery_kms_key/main.tf | 25 +-- .../config_org/delivery_kms_key/output.tf | 4 + .../config_org/delivery_kms_key/providers.tf | 4 - .../config_org/delivery_kms_key/variables.tf | 1 + .../config_org/delivery_s3_bucket/main.tf | 18 +- .../config_org/delivery_s3_bucket/output.tf | 7 + .../delivery_s3_bucket/providers.tf | 4 - .../config_org/global_events/main.tf | 2 +- .../config_org/global_events/providers.tf | 4 - .../terraform/solutions/config_org/main.tf | 125 +++++++++---- .../config_org/org_sns-kms-key/variables.tf | 2 +- .../solutions/config_org/providers.tf | 2 +- .../solutions/config_org/sns/main.tf | 4 +- .../solutions/config_org/sns/providers.tf | 3 - .../solutions/config_org/sns/variables.tf | 1 + .../solutions/config_org/variables.tf | 12 -- .../solutions/guard_duty/kms_key/main.tf | 2 +- .../solutions/macie/delivery_kms_key/main.tf | 2 +- aws_sra_examples/terraform/solutions/main.tf | 19 ++ .../terraform/solutions/providers.tf | 49 +++++ .../terraform/solutions/variables.tf | 8 + 35 files changed, 330 insertions(+), 227 deletions(-) create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/output.tf create mode 100644 aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/output.tf diff --git a/aws_sra_examples/solutions/config/config_org/lambda/src/app.py b/aws_sra_examples/solutions/config/config_org/lambda/src/app.py index 65fef0a0..f71af843 100644 --- a/aws_sra_examples/solutions/config/config_org/lambda/src/app.py +++ b/aws_sra_examples/solutions/config/config_org/lambda/src/app.py @@ -509,7 +509,10 @@ def orchestrator(event: Dict[str, Any], context: Any) -> None: event: event data context: runtime information """ - if event.get("RequestType"): + if event.get("Terraform"): + LOGGER.info("...calling terraform handler...") + process_event_cloudformation(event, context) + elif event.get("RequestType"): LOGGER.info("...calling helper...") helper(event, context) elif event.get("Records") and event["Records"][0]["EventSource"] == "aws:sns": diff --git a/aws_sra_examples/terraform/common/main.tf b/aws_sra_examples/terraform/common/main.tf index f6988e0f..ad4dff5b 100644 --- a/aws_sra_examples/terraform/common/main.tf +++ b/aws_sra_examples/terraform/common/main.tf @@ -123,7 +123,8 @@ resource "local_file" "config_file_creation" { enable_cloudtrail_org = false enable_iam_password_policy = false enable_inspector = false - + enable_config_org = false + ######################################################################## # Guard Duty Settings ######################################################################## diff --git a/aws_sra_examples/terraform/common/variables.tf b/aws_sra_examples/terraform/common/variables.tf index 2c23b10b..764c14af 100644 --- a/aws_sra_examples/terraform/common/variables.tf +++ b/aws_sra_examples/terraform/common/variables.tf @@ -2,26 +2,32 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 ######################################################################## +variable "account_region" { + type = string + description = "Default Account Region to deploy in" + default = "us-east-1" +} + variable "control_tower" { description = "AWS Control Tower landing zone deployed/in-use" - default = "true" + default = "false" } variable "governed_regions" { description = "AWS regions (comma separated) if not using AWS Control Tower (leave set to ct-regions for AWS Control Tower environments)" - default = "ct-regions" + default = "us-east-1,us-west-2" } variable "security_account_id" { description = "Security Tooling Account ID" type = string - default = "111111111111" + default = "654654614633" } variable "log_archive_account_id" { description = "Log Archive Account ID" type = string - default = "222222222222" + default = "533267136266" } variable "aws_partition" { diff --git a/aws_sra_examples/terraform/solutions/cloudtrail_org/org/main.tf b/aws_sra_examples/terraform/solutions/cloudtrail_org/org/main.tf index 50e76c05..5386c375 100644 --- a/aws_sra_examples/terraform/solutions/cloudtrail_org/org/main.tf +++ b/aws_sra_examples/terraform/solutions/cloudtrail_org/org/main.tf @@ -289,7 +289,7 @@ resource "aws_lambda_function" "cloudtrail_org_lambda_function" { #checkov:skip=CKV_AWS_115: Ensure that AWS Lambda function is configured for function-level concurrent execution limit #checkov:skip=CKV_AWS_117: Ensure that AWS Lambda function is configured inside a VPC #checkov:skip=CKV_AWS_50: X-Ray tracing is enabled for Lambda - + description = "Creates an Organization CloudTrail" function_name = var.cloudtrail_lambda_function_name role = aws_iam_role.cloudtrail_lambda_role.arn diff --git a/aws_sra_examples/terraform/solutions/cloudtrail_org/s3/main.tf b/aws_sra_examples/terraform/solutions/cloudtrail_org/s3/main.tf index d0153a96..20ca17c8 100644 --- a/aws_sra_examples/terraform/solutions/cloudtrail_org/s3/main.tf +++ b/aws_sra_examples/terraform/solutions/cloudtrail_org/s3/main.tf @@ -144,7 +144,7 @@ resource "aws_s3_bucket_policy" "org_trail_bucket_policy" { resource "aws_secretsmanager_secret" "org_trail_s3_bucket_secret" { #checkov:skip=CKV_AWS_149: Ensure that Secrets Manager secret is encrypted using KMS CMK #checkov:skip=CKV2_AWS_57: Ensure Secrets Manager secrets should have automatic rotation enabled - + count = var.sra_secrets_key_alias_arn != "" ? 1 : 0 name = "sra/cloudtrail_org_s3_bucket" diff --git a/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/main.tf b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/main.tf index 178036dc..1f2b81c1 100644 --- a/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/main.tf +++ b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/main.tf @@ -3,13 +3,13 @@ # SPDX-License-Identifier: MIT-0 ######################################################################## resource "aws_iam_role" "r_config_aggregator_role" { - name = var.p_aggregator_role_name + name = var.p_aggregator_role_name assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { - Effect = "Allow" - Action = "sts:AssumeRole" + Effect = "Allow" + Action = "sts:AssumeRole" Principal = { Service = "config.amazonaws.com" } @@ -31,6 +31,6 @@ resource "aws_config_configuration_aggregator" "r_organization_config_aggregator account_aggregation_source { account_ids = [data.aws_caller_identity.current.account_id] - regions = ["all"] + all_regions = true } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/providers.tf b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/providers.tf index 35e5eb9e..226f1ca4 100644 --- a/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/providers.tf +++ b/aws_sra_examples/terraform/solutions/config_org/aggregator_org_configuration/providers.tf @@ -8,10 +8,6 @@ terraform { aws = { source = "hashicorp/aws" version = ">= 5.1.0" - - tags = { - "sra-solution" = var.p_sra_solution_name - } } } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration/invoke.tf b/aws_sra_examples/terraform/solutions/config_org/configuration/invoke.tf index 28331ead..d82ae53a 100644 --- a/aws_sra_examples/terraform/solutions/config_org/configuration/invoke.tf +++ b/aws_sra_examples/terraform/solutions/config_org/configuration/invoke.tf @@ -7,6 +7,7 @@ resource "aws_lambda_invocation" "new_lambda_invoke" { function_name = aws_lambda_function.r_config_org_lambda_function.function_name input = jsonencode({ + "Terraform" : "true", "RequestType" : "Create", "ResourceType" : "Custom::LambdaCustomResource", "ResourceProperties" : { diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration/main.tf b/aws_sra_examples/terraform/solutions/config_org/configuration/main.tf index 40c19ede..ee2978ee 100644 --- a/aws_sra_examples/terraform/solutions/config_org/configuration/main.tf +++ b/aws_sra_examples/terraform/solutions/config_org/configuration/main.tf @@ -3,7 +3,7 @@ # SPDX-License-Identifier: MIT-0 ######################################################################## locals { - graviton_regions = [ + graviton_regions = [ "ap-northeast-1", "ap-south-1", "ap-southeast-1", @@ -17,15 +17,15 @@ locals { ] account_id = data.aws_caller_identity.current.account_id region = data.aws_region.current.name - src_path = "${path.root}/../../solutions/config/config_org/lambda/src/" + src_path = "${path.root}/../../solutions/config/config_org/lambda/src/" compliance_frequency_single_day = var.p_compliance_frequency == 1 - create_dlq_alarm = var.p_sra_alarm_email != "" - create_lambda_log_group = var.p_create_lambda_log_group == "true" - is_all_supported = var.p_all_supported == "true" - use_graviton = contains(local.graviton_regions, data.aws_region.current.name) - use_kms_key = var.p_lambda_log_group_kms_key != "" - not_global_region_us_east_1 = data.aws_region.current.name != "us-east-1" + create_dlq_alarm = var.p_sra_alarm_email != "" + create_lambda_log_group = var.p_create_lambda_log_group == "true" + is_all_supported = var.p_all_supported == "true" + use_graviton = contains(local.graviton_regions, data.aws_region.current.name) + use_kms_key = var.p_lambda_log_group_kms_key != "" + not_global_region_us_east_1 = var.p_current_region != "us-east-1" } resource "aws_cloudwatch_log_group" "r_config_org_lambda_log_group" { @@ -42,13 +42,13 @@ resource "aws_cloudwatch_log_group" "r_config_org_lambda_log_group" { # Lambda Policies Documents ######################################################################## resource "aws_iam_role" "r_config_org_lambda_role" { - name = var.p_config_org_lambda_role_name + name = var.p_config_org_lambda_role_name assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [ { - Action = "sts:AssumeRole", - Effect = "Allow", + Action = "sts:AssumeRole", + Effect = "Allow", Principal = { Service = ["lambda.amazonaws.com"] } @@ -57,33 +57,16 @@ resource "aws_iam_role" "r_config_org_lambda_role" { }) } -resource "aws_iam_role" "r_config_org_lambda_role" { - name = var.p_config_org_lambda_role_name - assume_role_policy = jsonencode({ - Version = "2012-10-17", - Statement = [ - { - Action = "sts:AssumeRole", - Effect = "Allow", - Principal = { - Service = ["lambda.amazonaws.com"] - } - } - ] - }) - path = "/" -} - resource "aws_iam_policy" "sra_config_org_policy_organizations" { name = "sra-config-org-policy-organizations" description = "IAM policy for Macie Org Lambda Organizations" - policy = jsonencode({ - Version = "2012-10-17", + policy = jsonencode({ + Version = "2012-10-17", Statement = [ { - Sid = "OrganizationsReadAccess" - Effect = "Allow" - Action = [ + Sid = "OrganizationsReadAccess" + Effect = "Allow" + Action = [ "organizations:DescribeAccount", "organizations:ListAccounts" ] @@ -96,12 +79,12 @@ resource "aws_iam_policy" "sra_config_org_policy_organizations" { resource "aws_iam_policy" "ssm_access" { name = "ssm-access" description = "IAM policy for SSM access" - policy = jsonencode({ - Version = "2012-10-17", + policy = jsonencode({ + Version = "2012-10-17", Statement = [ { - Effect = "Allow", - Action = [ + Effect = "Allow", + Action = [ "ssm:GetParameter", "ssm:GetParameters" ], @@ -116,13 +99,13 @@ resource "aws_iam_policy" "ssm_access" { resource "aws_iam_policy" "sra_config_org_policy_sns" { name = "sra-config-org-policy-sns" description = "IAM policy for SNS access" - policy = jsonencode({ - Version = "2012-10-17", + policy = jsonencode({ + Version = "2012-10-17", Statement = [ { - Sid = "SNSPublish" - Effect = "Allow" - Action = [ + Sid = "SNSPublish" + Effect = "Allow" + Action = [ "sns:Publish", "sns:PublishBatch" ], @@ -133,15 +116,15 @@ resource "aws_iam_policy" "sra_config_org_policy_sns" { } resource "aws_iam_policy" "sra_config_org_policy_iam" { - name = "sra-config-org-policy-iam" + name = "sra-config-org-policy-iam-lambda" description = "IAM policy for IAM access" - policy = jsonencode({ - Version = "2012-10-17", + policy = jsonencode({ + Version = "2012-10-17", Statement = [ { - Sid = "AssumeRole" - Effect = "Allow" - Action = ["sts:AssumeRole"] + Sid = "AssumeRole" + Effect = "Allow" + Action = ["sts:AssumeRole"] Condition = { StringEquals = { "aws:PrincipalOrgId" = var.p_organization_id @@ -158,9 +141,9 @@ resource "aws_iam_policy" "sra_config_org_policy_iam" { Resource = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/*" }, { - Sid = "AllowCreateServiceLinkedRole" - Effect = "Allow" - Action = ["iam:CreateServiceLinkedRole"] + Sid = "AllowCreateServiceLinkedRole" + Effect = "Allow" + Action = ["iam:CreateServiceLinkedRole"] Condition = { StringLike = { "iam:AWSServiceName" = "config.amazonaws.com" @@ -181,13 +164,13 @@ resource "aws_iam_policy" "sra_config_org_policy_iam" { resource "aws_iam_policy" "sra_config_org_policy_logs" { name = "sra-config-org-policy-logs" description = "IAM policy for logs access" - policy = jsonencode({ - Version = "2012-10-17", + policy = jsonencode({ + Version = "2012-10-17", Statement = [ { - Sid = "CreateLogGroupAndEvents" - Effect = "Allow" - Action = [ + Sid = "CreateLogGroupAndEvents" + Effect = "Allow" + Action = [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" @@ -201,8 +184,8 @@ resource "aws_iam_policy" "sra_config_org_policy_logs" { resource "aws_iam_policy" "sra_config_org_policy_sqs" { name = "sra-config-org-policy-sqs" description = "IAM policy for SQS access" - policy = jsonencode({ - Version = "2012-10-17", + policy = jsonencode({ + Version = "2012-10-17", Statement = [ { Sid = "SQSSendMessage" @@ -301,29 +284,29 @@ resource "aws_lambda_function" "r_config_org_lambda_function" { filename = data.archive_file.zipped_lambda.output_path dead_letter_config { - target_arn = aws_sqs_queue.config_org_dlq.arn + target_arn = aws_sqs_queue.r_config_org_dlq.arn } environment { variables = { - AUDIT_ACCOUNT = var.p_audit_account_id - LOG_LEVEL = var.p_lambda_log_level - AWS_PARTITION = data.aws_partition.current.partition - CONFIGURATION_ROLE_NAME = var.p_config_configuration_role_name - CONTROL_TOWER_REGIONS_ONLY = var.p_control_tower_regions_only - ENABLED_REGIONS = var.p_enabled_regions - ALL_SUPPORTED = var.p_all_supported - INCLUDE_GLOBAL_RESOURCE_TYPES = var.p_include_global_resource_types - FREQUENCY = var.p_frequency - RESOURCE_TYPES = var.p_resource_types - DELIVERY_S3_KEY_PREFIX = var.p_delivery_s3_key_prefix - S3_BUCKET_NAME = "${var.p_config_org_delivery_bucket_prefix}-${var.p_log_archive_account_id}-${var.p_home_region}" - DELIVERY_CHANNEL_NAME = var.p_delivery_channel_name - CONFIG_TOPIC_NAME = var.p_config_topic_name - RECORDER_NAME = var.p_recorder_name - KMS_KEY_SECRET_NAME = var.p_kms_key_arn_secret_name - HOME_REGION = var.p_home_region - SNS_TOPIC_ARN_FANOUT = aws_sns_topic.config_org_topic.arn + AUDIT_ACCOUNT = var.p_audit_account_id + LOG_LEVEL = var.p_lambda_log_level + AWS_PARTITION = data.aws_partition.current.partition + CONFIGURATION_ROLE_NAME = var.p_config_configuration_role_name + CONTROL_TOWER_REGIONS_ONLY = var.p_control_tower_regions_only + ENABLED_REGIONS = var.p_enabled_regions + ALL_SUPPORTED = var.p_all_supported + INCLUDE_GLOBAL_RESOURCE_TYPES = var.p_include_global_resource_types + FREQUENCY = var.p_frequency + RESOURCE_TYPES = var.p_resource_types == "" ? null : var.p_resource_types + DELIVERY_S3_KEY_PREFIX = var.p_delivery_s3_key_prefix + S3_BUCKET_NAME = "${var.p_config_org_delivery_bucket_prefix}-${var.p_log_archive_account_id}-${var.p_home_region}" + DELIVERY_CHANNEL_NAME = var.p_delivery_channel_name + CONFIG_TOPIC_NAME = var.p_config_topic_name + RECORDER_NAME = var.p_recorder_name + KMS_KEY_SECRET_NAME = var.p_kms_key_arn_secret_name + HOME_REGION = var.p_home_region + SNS_TOPIC_ARN_FANOUT = aws_sns_topic.r_config_org_topic.arn PUBLISHING_DESTINATION_BUCKET_ARN = "arn:${data.aws_partition.current.partition}:s3:::${var.p_publishing_destination_bucket_name}" } } @@ -356,7 +339,7 @@ resource "aws_sqs_queue" "r_config_org_dlq" { message_retention_seconds = 345600 lifecycle { - prevent_destroy = false + prevent_destroy = false create_before_destroy = true } } @@ -389,10 +372,10 @@ resource "aws_sns_topic" "r_config_org_dlq_alarm_topic" { } resource "aws_sns_topic_subscription" "r_config_org_dlq_alarm_topic_subscription" { - count = var.p_sra_alarm_email != "" ? 1 : 0 - endpoint = var.p_sra_alarm_email - protocol = "email" - topic_arn = aws_sns_topic.r_config_org_dlq_alarm_topic[0].arn + count = var.p_sra_alarm_email != "" ? 1 : 0 + endpoint = var.p_sra_alarm_email + protocol = "email" + topic_arn = aws_sns_topic.r_config_org_dlq_alarm_topic[0].arn } resource "aws_cloudwatch_metric_alarm" "r_config_org_dlq_alarm" { @@ -415,10 +398,10 @@ resource "aws_cloudwatch_metric_alarm" "r_config_org_dlq_alarm" { } resource "aws_cloudwatch_event_rule" "r_scheduled_compliance_rule" { - name = "${var.p_control_tower_life_cycle_rule_name}-organization-compliance" - description = "SRA Config Trigger for scheduled organization compliance" + name = "${var.p_control_tower_life_cycle_rule_name}-organization-compliance" + description = "SRA Config Trigger for scheduled organization compliance" schedule_expression = local.compliance_frequency_single_day ? "rate(${var.p_compliance_frequency} day)" : "rate(${var.p_compliance_frequency} days)" - state = "ENABLED" + state = "ENABLED" } resource "aws_cloudwatch_event_target" "r_scheduled_compliance_rule_target" { @@ -438,13 +421,13 @@ resource "aws_lambda_permission" "r_permission_for_scheduled_compliance_rule_to_ resource "aws_iam_role" "r_cross_region_event_rule_role" { count = local.not_global_region_us_east_1 ? 1 : 0 - name = var.p_event_rule_role_name + name = var.p_event_rule_role_name assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [ { - Effect = "Allow", - Action = "sts:AssumeRole", + Effect = "Allow", + Action = "sts:AssumeRole", Principal = { Service = "events.amazonaws.com" } @@ -453,9 +436,9 @@ resource "aws_iam_role" "r_cross_region_event_rule_role" { }) inline_policy { - name = "sra-account-org-config-policy-events" + name = "sra-account-org-config-policy-events" policy = jsonencode({ - Version = "2012-10-17", + Version = "2012-10-17", Statement = [ { Effect = "Allow", @@ -471,11 +454,11 @@ resource "aws_cloudwatch_event_rule" "r_organizations_rule" { name = "${var.p_control_tower_life_cycle_rule_name}-org-update" description = "SRA Config Trigger on Organizations update" event_pattern = jsonencode({ - source = ["aws.organizations"], + source = ["aws.organizations"], "detail-type" = ["AWS Service Event via CloudTrail", "AWS API Call via CloudTrail"], detail = { eventSource = ["organizations.amazonaws.com"], - eventName = ["AcceptHandshake", "CreateAccountResult"] + eventName = ["AcceptHandshake", "CreateAccountResult"] } }) state = "ENABLED" diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration/providers.tf b/aws_sra_examples/terraform/solutions/config_org/configuration/providers.tf index c5ab4eeb..30cfbfd1 100644 --- a/aws_sra_examples/terraform/solutions/config_org/configuration/providers.tf +++ b/aws_sra_examples/terraform/solutions/config_org/configuration/providers.tf @@ -9,9 +9,6 @@ terraform { source = "hashicorp/aws" version = ">= 5.1.0" #configuration_aliases = [aws.main, aws.management, aws.log_archive] - tags = { - "sra-solution" = var.p_sra_solution_name - } } } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration/variables.tf b/aws_sra_examples/terraform/solutions/config_org/configuration/variables.tf index 3aeb0826..faed7eea 100644 --- a/aws_sra_examples/terraform/solutions/config_org/configuration/variables.tf +++ b/aws_sra_examples/terraform/solutions/config_org/configuration/variables.tf @@ -28,15 +28,15 @@ variable "p_home_region" { type = string } -variable "p_sra_alarm_email" { - description = "(Optional) Email address for receiving DLQ alarms" +variable "p_current_region" { + description = "Current Region" type = string - default = "" } -variable "p_sra_staging_s3_bucket_name" { - description = "SRA Staging S3 bucket name for the artifacts relevant to solution. (e.g., lambda zips, CloudFormation templates) S3 bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-)." +variable "p_sra_alarm_email" { + description = "(Optional) Email address for receiving DLQ alarms" type = string + default = "" } variable "p_kms_key_arn" { @@ -47,6 +47,7 @@ variable "p_kms_key_arn" { variable "p_recorder_name" { description = "Config delivery s3 bucket name" type = string + default = "sra-ConfigRecorder" } variable "p_all_supported" { diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration_role/main.tf b/aws_sra_examples/terraform/solutions/config_org/configuration_role/main.tf index 8d618a92..6e3448ad 100644 --- a/aws_sra_examples/terraform/solutions/config_org/configuration_role/main.tf +++ b/aws_sra_examples/terraform/solutions/config_org/configuration_role/main.tf @@ -49,14 +49,16 @@ resource "aws_iam_role_policy_attachment" "r_config_org_attach_kms" { data "aws_iam_policy_document" "r_config_recorder_assume_role_policy" { statement { - effect = "Allow" - actions = ["sts:AssumeRole"] - resources = ["arn:aws:iam::${var.p_management_account_id}:role/${var.p_config_org_lambda_role_name}"] - + effect = "Allow" + actions = ["sts:AssumeRole"] + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${var.p_management_account_id}:root"] + } condition { test = "StringEquals" variable = "aws:PrincipalArn" - values = ["arn:aws:iam::${var.p_management_account_id}:root"] + values = ["arn:aws:iam::${var.p_management_account_id}:role/${var.p_config_org_lambda_role_name}"] } } } @@ -77,9 +79,9 @@ data "aws_iam_policy_document" "r_config_org_policy_iam" { } statement { - sid = "AllowCreateServiceLinkedRole" - effect = "Allow" - actions = ["iam:CreateServiceLinkedRole"] + sid = "AllowCreateServiceLinkedRole" + effect = "Allow" + actions = ["iam:CreateServiceLinkedRole"] condition { test = "StringLike" variable = "iam:AWSServiceName" @@ -98,8 +100,8 @@ data "aws_iam_policy_document" "r_config_org_policy_iam" { data "aws_iam_policy_document" "r_config_org_policy_config" { statement { - effect = "Allow" - actions = [ + effect = "Allow" + actions = [ "config:DeleteDeliveryChannel", "config:DescribeConfigurationRecorders", "config:DescribeDeliveryChannels", @@ -115,8 +117,8 @@ data "aws_iam_policy_document" "r_config_org_policy_config" { data "aws_iam_policy_document" "r_config_org_policy_secrets_manager" { statement { - effect = "Allow" - actions = ["secretsmanager:GetSecretValue"] + effect = "Allow" + actions = ["secretsmanager:GetSecretValue"] condition { test = "StringLike" variable = "aws:PrincipalAccount" @@ -128,8 +130,8 @@ data "aws_iam_policy_document" "r_config_org_policy_secrets_manager" { data "aws_iam_policy_document" "r_config_org_policy_kms" { statement { - effect = "Allow" - actions = ["kms:Decrypt"] + effect = "Allow" + actions = ["kms:Decrypt"] condition { test = "StringLike" variable = "aws:PrincipalAccount" diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration_role/providers.tf b/aws_sra_examples/terraform/solutions/config_org/configuration_role/providers.tf index c5ab4eeb..30cfbfd1 100644 --- a/aws_sra_examples/terraform/solutions/config_org/configuration_role/providers.tf +++ b/aws_sra_examples/terraform/solutions/config_org/configuration_role/providers.tf @@ -9,9 +9,6 @@ terraform { source = "hashicorp/aws" version = ">= 5.1.0" #configuration_aliases = [aws.main, aws.management, aws.log_archive] - tags = { - "sra-solution" = var.p_sra_solution_name - } } } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/configuration_role/variables.tf b/aws_sra_examples/terraform/solutions/config_org/configuration_role/variables.tf index fae60cbf..0d0eec07 100644 --- a/aws_sra_examples/terraform/solutions/config_org/configuration_role/variables.tf +++ b/aws_sra_examples/terraform/solutions/config_org/configuration_role/variables.tf @@ -31,12 +31,6 @@ variable "p_sra_solution_tag_key" { default = "sra-solution" } -variable "p_sra_solution_name" { - type = string - description = "The SRA solution name. The default value is the folder name of the solution" - default = "sra-config-org" -} - variable "p_audit_account_id" { type = string description = "AWS Account ID of the Audit account." diff --git a/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/main.tf b/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/main.tf index ccc3d351..24af28fd 100644 --- a/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/main.tf +++ b/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/main.tf @@ -21,11 +21,9 @@ resource "aws_kms_alias" "r_config_delivery_key_alias" { resource "aws_secretsmanager_secret" "r_config_delivery_key_secret" { #checkov:skip=CKV_AWS_149: Ensure that Secrets Manager secret is encrypted using KMS CMK #checkov:skip=CKV2_AWS_57: Ensure Secrets Manager secrets should have automatic rotation enabled - - count = var.p_sras_secrets_key_alias_arn != "" ? 1 : 0 + name = "sra/config_org_delivery_key_arn" description = "Config Delivery KMS Key ARN" - kms_key_id = var.p_sras_secrets_key_alias_arn tags = { "sra-solution" = var.p_sra_solution_name @@ -33,8 +31,7 @@ resource "aws_secretsmanager_secret" "r_config_delivery_key_secret" { } resource "aws_secretsmanager_secret_version" "r_config_delivery_key_secret_version" { - count = var.p_sras_secrets_key_alias_arn != "" ? 1 : 0 - secret_id = aws_secretsmanager_secret.r_config_delivery_key_secret[0].id + secret_id = aws_secretsmanager_secret.r_config_delivery_key_secret.id secret_string = jsonencode({ ConfigDeliveryKeyArn = aws_kms_key.r_config_delivery_key.arn @@ -70,9 +67,13 @@ data "aws_iam_policy_document" "r_config_delivery_key_policy" { } statement { - sid = "AllowAliasCreationDuringSetup" - effect = "Allow" - actions = ["kms:CreateAlias"] + sid = "AllowAliasCreationDuringSetup" + effect = "Allow" + actions = ["kms:CreateAlias"] + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } resources = ["*"] condition { test = "StringEquals" @@ -92,7 +93,7 @@ data "aws_iam_policy_document" "r_config_delivery_key_policy" { actions = ["kms:Decrypt"] resources = ["*"] principals { - type = "AWS" + type = "AWS" identifiers = [ "arn:aws:iam::${var.p_log_archive_account_id}:root", "arn:aws:iam::${var.p_management_account_id}:root" @@ -101,9 +102,9 @@ data "aws_iam_policy_document" "r_config_delivery_key_policy" { } statement { - sid = "AllowAccountAccess" - effect = "Allow" - actions = [ + sid = "AllowAccountAccess" + effect = "Allow" + actions = [ "kms:DescribeKey", "kms:Decrypt" ] diff --git a/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/output.tf b/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/output.tf new file mode 100644 index 00000000..f42edb6f --- /dev/null +++ b/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/output.tf @@ -0,0 +1,4 @@ +output "config_delivery_kms_key_arn" { + description = "ARN of the KMS Key used for Config delivery encryption" + value = aws_kms_key.r_config_delivery_key.arn +} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/providers.tf b/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/providers.tf index 35e5eb9e..226f1ca4 100644 --- a/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/providers.tf +++ b/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/providers.tf @@ -8,10 +8,6 @@ terraform { aws = { source = "hashicorp/aws" version = ">= 5.1.0" - - tags = { - "sra-solution" = var.p_sra_solution_name - } } } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/variables.tf b/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/variables.tf index cc27ab53..8c0529b4 100644 --- a/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/variables.tf +++ b/aws_sra_examples/terraform/solutions/config_org/delivery_kms_key/variables.tf @@ -21,6 +21,7 @@ variable "p_management_account_id" { variable "p_sras_secrets_key_alias_arn" { type = string description = "(Optional) SRA Secrets Manager KMS Key Alias ARN" + default = "" } variable "p_sra_solution_name" { diff --git a/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/main.tf b/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/main.tf index bea90217..c34b2b93 100644 --- a/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/main.tf +++ b/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/main.tf @@ -63,13 +63,13 @@ resource "aws_s3_bucket_policy" "r_config_s3_bucket_policy" { data "aws_iam_policy_document" "r_config_s3_bucket_policy" { statement { - sid = "AllowSSLRequestsOnly" - effect = "Deny" + sid = "AllowSSLRequestsOnly" + effect = "Deny" principals { type = "AWS" identifiers = ["*"] } - actions = ["s3:*"] + actions = ["s3:*"] resources = [ "${aws_s3_bucket.r_config_delivery_s3_bucket.arn}", "${aws_s3_bucket.r_config_delivery_s3_bucket.arn}/*" @@ -82,8 +82,8 @@ data "aws_iam_policy_document" "r_config_s3_bucket_policy" { } statement { - sid = "AWSBucketPermissionsCheck" - effect = "Allow" + sid = "AWSBucketPermissionsCheck" + effect = "Allow" principals { type = "Service" identifiers = ["config.amazonaws.com"] @@ -93,8 +93,8 @@ data "aws_iam_policy_document" "r_config_s3_bucket_policy" { } statement { - sid = "AWSConfigBucketExistenceCheck" - effect = "Allow" + sid = "AWSConfigBucketExistenceCheck" + effect = "Allow" principals { type = "Service" identifiers = ["config.amazonaws.com"] @@ -104,8 +104,8 @@ data "aws_iam_policy_document" "r_config_s3_bucket_policy" { } statement { - sid = "AWSBucketDeliveryForConfig" - effect = "Allow" + sid = "AWSBucketDeliveryForConfig" + effect = "Allow" principals { type = "Service" identifiers = ["config.amazonaws.com"] diff --git a/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/output.tf b/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/output.tf new file mode 100644 index 00000000..2016a2e9 --- /dev/null +++ b/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/output.tf @@ -0,0 +1,7 @@ +######################################################################## +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +######################################################################## +output "config_delivery_bucket_name" { + value = aws_s3_bucket.r_config_delivery_s3_bucket.id +} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/providers.tf b/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/providers.tf index 35e5eb9e..226f1ca4 100644 --- a/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/providers.tf +++ b/aws_sra_examples/terraform/solutions/config_org/delivery_s3_bucket/providers.tf @@ -8,10 +8,6 @@ terraform { aws = { source = "hashicorp/aws" version = ">= 5.1.0" - - tags = { - "sra-solution" = var.p_sra_solution_name - } } } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/global_events/main.tf b/aws_sra_examples/terraform/solutions/config_org/global_events/main.tf index 12e7e9f8..475f76a8 100644 --- a/aws_sra_examples/terraform/solutions/config_org/global_events/main.tf +++ b/aws_sra_examples/terraform/solutions/config_org/global_events/main.tf @@ -7,7 +7,7 @@ resource "aws_cloudwatch_event_rule" "r_organizations_rule" { description = "SRA Config Forward Organizations events to home region." event_pattern = jsonencode({ - source = ["aws.organizations"], + source = ["aws.organizations"], "detail-type" = ["AWS Service Event via CloudTrail"], detail = { eventSource = ["organizations.amazonaws.com"], diff --git a/aws_sra_examples/terraform/solutions/config_org/global_events/providers.tf b/aws_sra_examples/terraform/solutions/config_org/global_events/providers.tf index 35e5eb9e..226f1ca4 100644 --- a/aws_sra_examples/terraform/solutions/config_org/global_events/providers.tf +++ b/aws_sra_examples/terraform/solutions/config_org/global_events/providers.tf @@ -8,10 +8,6 @@ terraform { aws = { source = "hashicorp/aws" version = ">= 5.1.0" - - tags = { - "sra-solution" = var.p_sra_solution_name - } } } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/main.tf b/aws_sra_examples/terraform/solutions/config_org/main.tf index 7a3fcaa5..e38efd26 100644 --- a/aws_sra_examples/terraform/solutions/config_org/main.tf +++ b/aws_sra_examples/terraform/solutions/config_org/main.tf @@ -1,62 +1,121 @@ locals { - aws_partition = data.aws_partition.current.partition - aws_account_id = data.aws_caller_identity.current.account_id - aws_region = data.aws_region.current.name + aws_partition = data.aws_partition.current.partition + aws_account_id = data.aws_caller_identity.current.account_id + aws_region = data.aws_region.current.name c_not_global_region_us_east_1 = local.aws_region != "us-east-1" - c_register_delegated_admin = var.p_register_delegated_admin_account == true - c_control_tower_regions = var.p_control_tower_regions_only == true + c_register_delegated_admin = var.p_register_delegated_admin_account == true + c_control_tower_regions = var.p_control_tower_regions_only == true + + is_audit_account = data.aws_caller_identity.current.account_id == var.p_audit_account_id + is_log_account = data.aws_caller_identity.current.account_id == var.p_audit_account_id + is_home_region = data.aws_region.current.name == var.p_home_region } module "m_config_sns_topic" { - source = "./sns" - - providers = { - aws = aws.audit - } + depends_on = [module.m_configuration_role] + count = local.is_audit_account ? 1 : 0 + source = "./sns" - p_configuration_email = var.p_configuration_email - p_config_org_sns_key_alias = var.p_config_org_sns_key_alias - p_config_topic_name = var.p_config_topic_name + p_configuration_email = var.p_configuration_email + p_config_org_sns_key_alias = var.p_config_org_sns_key_alias + p_config_topic_name = var.p_config_topic_name p_subscribe_to_configuration_topic = var.p_subscribe_to_configuration_topic } -module "m_management_configuration_role"{ - source = "./configuration_role" +module "m_configuration_role" { + count = local.is_home_region ? 1 : 0 - providers = { - aws = aws.management - } + source = "./configuration_role" - p_audit_account_id = var.p_audit_account_id - p_management_account_id = var.p_management_account_id - p_home_region = var.p_home_region -} + providers = { + aws = aws.main + } -module "m_configuration_role"{ - count = local.aws_account_id != var.p_management_account_id ? 1 : 0 + p_audit_account_id = var.p_audit_account_id + p_management_account_id = var.p_management_account_id + p_home_region = var.p_home_region +} - source = "./configuration_role" +// delivery kms +module "m_delivery_kms" { + count = local.is_audit_account ? 1 : 0 + source = "./delivery_kms_key" - providers = { - aws = aws.main - } + providers = { + aws = aws.main + } - p_audit_account_id = var.p_audit_account_id - p_management_account_id = var.p_management_account_id - p_home_region = var.p_home_region + p_log_archive_account_id = var.p_log_archive_account_id + p_management_account_id = var.p_management_account_id } // delivery bucket +module "m_delivery_bucket" { + depends_on = [module.m_configuration_role, module.m_delivery_kms] + count = local.is_audit_account && local.is_home_region ? 1 : 0 + source = "./delivery_s3_bucket" + + providers = { + aws = aws.log_archive + } + + p_organization_id = var.p_organization_id + p_config_org_delivery_bucket_prefix = var.p_config_org_delivery_bucket_prefix + p_config_org_delivery_kms_key_arn = module.m_delivery_kms[0].config_delivery_kms_key_arn +} // configuration +module "m_configuration" { + depends_on = [module.m_configuration_role, module.m_delivery_bucket] + count = local.is_audit_account && local.is_home_region ? 1 : 0 + source = "./configuration" + + providers = { + aws = aws.management + } + + p_publishing_destination_bucket_name = module.m_delivery_bucket[0].config_delivery_bucket_name + p_home_region = var.p_home_region + p_delivery_s3_key_prefix = var.p_organization_id + p_kms_key_arn = module.m_delivery_kms[0].config_delivery_kms_key_arn + p_audit_account_id = var.p_audit_account_id + p_organization_id = var.p_organization_id + p_log_archive_account_id = var.p_log_archive_account_id + p_current_region = data.aws_region.current.name +} // global events +module "m_global_events" { + count = local.is_audit_account && local.is_home_region && local.c_not_global_region_us_east_1 ? 1 : 0 + source = "./global_events" -// delivery kms + providers = { + aws = aws.management + } + + p_home_region = var.p_home_region + p_sra_solution_name = var.p_sra_solution_name +} // org-sns +module "m_org_sns_kms_key" { + count = local.is_audit_account ? 1 : 0 -// register delegated admin..? + source = "./sns" + + providers = { + aws = aws.main + } +} // config aggregator +module "m_config_aggregator" { + count = local.is_audit_account && local.is_home_region ? 1 : 0 + + source = "./aggregator_org_configuration" + + providers = { + aws = aws.main + } +} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/org_sns-kms-key/variables.tf b/aws_sra_examples/terraform/solutions/config_org/org_sns-kms-key/variables.tf index b5c6ab9d..efac8627 100644 --- a/aws_sra_examples/terraform/solutions/config_org/org_sns-kms-key/variables.tf +++ b/aws_sra_examples/terraform/solutions/config_org/org_sns-kms-key/variables.tf @@ -10,7 +10,7 @@ variable "p_sra_solution_name" { variable "p_config_org_sns_key_alias" { default = "sra-config-org-sns-key" - description = "Config SNS KMS Key Alias" + description = "(Optional) SRA Secrets Manager KMS Key Alias ARN" type = string } diff --git a/aws_sra_examples/terraform/solutions/config_org/providers.tf b/aws_sra_examples/terraform/solutions/config_org/providers.tf index df85fa5f..f698760b 100644 --- a/aws_sra_examples/terraform/solutions/config_org/providers.tf +++ b/aws_sra_examples/terraform/solutions/config_org/providers.tf @@ -8,7 +8,7 @@ terraform { aws = { source = "hashicorp/aws" version = ">= 5.1.0" - configuration_aliases = [aws.main, aws.management, aws.log_archive, aws.audit] + configuration_aliases = [aws.main, aws.management, aws.log_archive] } } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/sns/main.tf b/aws_sra_examples/terraform/solutions/config_org/sns/main.tf index 4aeb29fb..d84e2e3f 100644 --- a/aws_sra_examples/terraform/solutions/config_org/sns/main.tf +++ b/aws_sra_examples/terraform/solutions/config_org/sns/main.tf @@ -3,8 +3,8 @@ # SPDX-License-Identifier: MIT-0 ######################################################################## resource "aws_sns_topic" "config_org_topic" { - name = var.p_config_topic_name - display_name = var.p_config_topic_name + name = var.p_config_topic_name + display_name = var.p_config_topic_name kms_master_key_id = "arn:${data.aws_partition.current.partition}:kms:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:alias/${var.p_config_org_sns_key_alias}" tags = { "sra-solution" = var.p_sra_solution_name diff --git a/aws_sra_examples/terraform/solutions/config_org/sns/providers.tf b/aws_sra_examples/terraform/solutions/config_org/sns/providers.tf index c5ab4eeb..30cfbfd1 100644 --- a/aws_sra_examples/terraform/solutions/config_org/sns/providers.tf +++ b/aws_sra_examples/terraform/solutions/config_org/sns/providers.tf @@ -9,9 +9,6 @@ terraform { source = "hashicorp/aws" version = ">= 5.1.0" #configuration_aliases = [aws.main, aws.management, aws.log_archive] - tags = { - "sra-solution" = var.p_sra_solution_name - } } } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/config_org/sns/variables.tf b/aws_sra_examples/terraform/solutions/config_org/sns/variables.tf index cea75859..e81ed2a9 100644 --- a/aws_sra_examples/terraform/solutions/config_org/sns/variables.tf +++ b/aws_sra_examples/terraform/solutions/config_org/sns/variables.tf @@ -5,6 +5,7 @@ variable "p_configuration_email" { type = string description = "Email for receiving all AWS configuration events" + default = "" } variable "p_config_org_sns_key_alias" { diff --git a/aws_sra_examples/terraform/solutions/config_org/variables.tf b/aws_sra_examples/terraform/solutions/config_org/variables.tf index 226bf7bc..62539f46 100644 --- a/aws_sra_examples/terraform/solutions/config_org/variables.tf +++ b/aws_sra_examples/terraform/solutions/config_org/variables.tf @@ -20,24 +20,12 @@ variable "p_sra_alarm_email" { default = "" } -variable "p_sra_solution_name" { - description = "SRA Solution Name" - type = string - default = "sra-config-org" -} - variable "p_sra_solution_version" { description = "SRA Solution Version" type = string default = "v1.0" } -variable "p_sra_staging_s3_bucket_name" { - description = "SRA Staging S3 Bucket Name" - type = string - default = "/sra/staging-s3-bucket-name" -} - variable "p_management_account_id" { description = "Management Account ID" type = string diff --git a/aws_sra_examples/terraform/solutions/guard_duty/kms_key/main.tf b/aws_sra_examples/terraform/solutions/guard_duty/kms_key/main.tf index 092a31f4..41298020 100644 --- a/aws_sra_examples/terraform/solutions/guard_duty/kms_key/main.tf +++ b/aws_sra_examples/terraform/solutions/guard_duty/kms_key/main.tf @@ -93,7 +93,7 @@ resource "aws_kms_alias" "guardduty_delivery_key_alias" { resource "aws_secretsmanager_secret" "guardduty_delivery_key_secret" { #checkov:skip=CKV2_AWS_57: Ensure Secrets Manager secrets should have automatic rotation enabled - + count = var.create_secret ? 1 : 0 name = "sra/guardduty_org_delivery_key_arn" description = "GuardDuty Delivery KMS Key ARN" diff --git a/aws_sra_examples/terraform/solutions/macie/delivery_kms_key/main.tf b/aws_sra_examples/terraform/solutions/macie/delivery_kms_key/main.tf index ac610b2d..2bc61f8c 100644 --- a/aws_sra_examples/terraform/solutions/macie/delivery_kms_key/main.tf +++ b/aws_sra_examples/terraform/solutions/macie/delivery_kms_key/main.tf @@ -93,7 +93,7 @@ resource "aws_kms_alias" "macie_delivery_key_alias" { resource "aws_secretsmanager_secret" "macie_delivery_key_secret" { #checkov:skip=CKV_AWS_149: Ensure that Secrets Manager secret is encrypted using KMS CMK #checkov:skip=CKV2_AWS_57: Ensure Secrets Manager secrets should have automatic rotation enabled - + count = var.secrets_key_alias_arn != "" ? 1 : 0 name = "sra/macie_org_delivery_key_arn" description = "Macie Delivery KMS Key ARN" diff --git a/aws_sra_examples/terraform/solutions/main.tf b/aws_sra_examples/terraform/solutions/main.tf index 91624bce..7aaafdd7 100644 --- a/aws_sra_examples/terraform/solutions/main.tf +++ b/aws_sra_examples/terraform/solutions/main.tf @@ -195,3 +195,22 @@ module "iam_password_policy" { require_symbols = var.iam_password_policy_require_symbols require_uppercase_characters = var.iam_password_policy_require_uppercase_characters } + +module "config" { + count = var.enable_config_org ? 1 : 0 + + providers = { + aws.main = aws.target_config + aws.management = aws.management_config + aws.log_archive = aws.log_archive_config + } + + source = "./config_org" + + p_organization_id = var.organization_id + p_log_archive_account_id = local.log_archive_account_id + p_root_organizational_unit_id = var.root_organizational_unit_id + p_audit_account_id = local.audit_account_id + p_home_region = var.home_region + p_management_account_id = local.management_account_id +} \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/providers.tf b/aws_sra_examples/terraform/solutions/providers.tf index deacd7c9..456cbae2 100644 --- a/aws_sra_examples/terraform/solutions/providers.tf +++ b/aws_sra_examples/terraform/solutions/providers.tf @@ -55,4 +55,53 @@ provider "aws" { Owner = "Security" } } +} + +provider "aws" { + alias = "management_config" + region = var.account_region + + assume_role { + role_arn = "arn:aws:iam::${var.management_account_id}:role/sra-execution" + session_name = "Pipeline_Run" + } + + default_tags { + tags = { + Owner = "Security" + sra-solution = "sra-config-org" + } + } +} + +provider "aws" { + alias = "target_config" + region = var.account_region + + assume_role { + role_arn = "arn:aws:iam::${var.account_id}:role/sra-execution" + session_name = "Pipeline_Run" + } + default_tags { + tags = { + Owner = "Security" + sra-solution = "sra-config-org" + } + } +} + +provider "aws" { + alias = "log_archive_config" + region = var.account_region + + assume_role { + role_arn = "arn:aws:iam::${var.log_archive_account_id}:role/sra-execution" + session_name = "Pipeline_Run" + } + default_tags { + tags = { + Owner = "Security" + sra-solution = "sra-config-org" + } + } } \ No newline at end of file diff --git a/aws_sra_examples/terraform/solutions/variables.tf b/aws_sra_examples/terraform/solutions/variables.tf index c52aa830..91070814 100644 --- a/aws_sra_examples/terraform/solutions/variables.tf +++ b/aws_sra_examples/terraform/solutions/variables.tf @@ -349,3 +349,11 @@ variable "disable_cloudtrail" { type = bool default = false } + +######################################################################## +# AWS Config Organization +######################################################################## +variable "enable_config_org" { + description = "Enables the AWS Config Organization" + type = bool +} \ No newline at end of file From 066a436d3f10b46cf8edceffad8ebc722cb8282b Mon Sep 17 00:00:00 2001 From: nguyentk Date: Fri, 19 Jul 2024 16:09:18 -0500 Subject: [PATCH 3/3] reset to default values --- aws_sra_examples/terraform/common/variables.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aws_sra_examples/terraform/common/variables.tf b/aws_sra_examples/terraform/common/variables.tf index 764c14af..65706f3f 100644 --- a/aws_sra_examples/terraform/common/variables.tf +++ b/aws_sra_examples/terraform/common/variables.tf @@ -15,19 +15,19 @@ variable "control_tower" { variable "governed_regions" { description = "AWS regions (comma separated) if not using AWS Control Tower (leave set to ct-regions for AWS Control Tower environments)" - default = "us-east-1,us-west-2" + default = "ct-regions" } variable "security_account_id" { description = "Security Tooling Account ID" type = string - default = "654654614633" + default = "111111111111" } variable "log_archive_account_id" { description = "Log Archive Account ID" type = string - default = "533267136266" + default = "222222222222" } variable "aws_partition" {