From a0be28ca8f34d66ec90faa9bcfbacdd2a2dd8464 Mon Sep 17 00:00:00 2001 From: Rohith Jayawardene Date: Mon, 29 Apr 2024 08:35:54 +0100 Subject: [PATCH] feat: moving the cloudformation bucket the management account --- README.md | 1 + data.tf | 6 ++++ locals.tf | 6 ++-- main.tf | 89 +++++++++++++++++++++++++++----------------------- quicksights.tf | 13 ++++---- 5 files changed, 64 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 73c92aa..19dbf53 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | [aws_quicksight_user.users](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/quicksight_user) | resource | | [aws_s3_object.cloudformation_templates](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_object) | resource | | [aws_caller_identity.cost_analysis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_caller_identity.management](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.cudos_sso](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cudos_sso_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.dashboards_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | diff --git a/data.tf b/data.tf index c092504..1475c2a 100644 --- a/data.tf +++ b/data.tf @@ -3,6 +3,12 @@ data "aws_caller_identity" "cost_analysis" { provider = aws.cost_analysis } + +## Find the account id for the management account +data "aws_caller_identity" "management" { + provider = aws.management +} + ## Find the current organization data "aws_organizations_organization" "current" { provider = aws.management diff --git a/locals.tf b/locals.tf index 955ee26..cf48183 100644 --- a/locals.tf +++ b/locals.tf @@ -1,17 +1,15 @@ locals { - ## The current account id - account_id = data.aws_caller_identity.cost_analysis.account_id ## The region where the stack is being deployed region = data.aws_region.cost_analysis.name ## Is the account id for the cost analysis account cost_analysis_account_id = data.aws_caller_identity.cost_analysis.account_id ## Is the management account id - management_account_id = data.aws_organizations_organization.current.master_account_id + management_account_id = data.aws_caller_identity.management.account_id ## Is the organization root id organization_root_id = data.aws_organizations_organization.current.roots[0].id ## The s3 bucket name for the cloudformation scripts - template_base_url = format("https://%s.s3.%s.amazonaws.com", var.stacks_bucket_name, local.region) + stacks_base_url = format("https://%s.s3.%s.amazonaws.com", var.stacks_bucket_name, local.region) ## Is the user mappings for the quicksight groups user_group_mappings = merge([ for n, g in var.quicksight_groups : { diff --git a/main.tf b/main.tf index 4563ba7..b3cb6bc 100644 --- a/main.tf +++ b/main.tf @@ -74,7 +74,23 @@ data "aws_iam_policy_document" "stack_bucket_policy" { ] principals { type = "AWS" - identifiers = [local.account_id] + identifiers = [local.management_account_id] + } + resources = [ + format("arn:aws:s3:::%s", var.stacks_bucket_name), + format("arn:aws:s3:::%s/*", var.stacks_bucket_name), + ] + } + + statement { + effect = "Allow" + actions = [ + "s3:GetObject", + "s3:ListBucket", + ] + principals { + type = "AWS" + identifiers = [local.cost_analysis_account_id] } resources = [ format("arn:aws:s3:::%s", var.stacks_bucket_name), @@ -95,7 +111,7 @@ data "aws_iam_policy_document" "dashboards_bucket_policy" { ] principals { type = "AWS" - identifiers = [local.account_id] + identifiers = [local.cost_analysis_account_id] } resources = [ format("arn:aws:s3:::%s", var.dashboards_bucket_name), @@ -111,21 +127,17 @@ module "cloudformation_bucket" { source = "terraform-aws-modules/s3-bucket/aws" version = "4.1.2" - attach_deny_incorrect_encryption_headers = true - attach_deny_insecure_transport_policy = true - attach_deny_unencrypted_object_uploads = true - attach_require_latest_tls_policy = true - acl = "private" - block_public_acls = true - block_public_policy = true - bucket = var.stacks_bucket_name - expected_bucket_owner = local.account_id - force_destroy = true - ignore_public_acls = true - object_ownership = "BucketOwnerPreferred" - policy = data.aws_iam_policy_document.stack_bucket_policy.json - restrict_public_buckets = true - tags = var.tags + attach_policy = true + block_public_acls = true + block_public_policy = true + bucket = var.stacks_bucket_name + expected_bucket_owner = local.management_account_id + force_destroy = true + ignore_public_acls = true + object_ownership = "BucketOwnerPreferred" + policy = data.aws_iam_policy_document.stack_bucket_policy.json + restrict_public_buckets = true + tags = var.tags server_side_encryption_configuration = { rule = { @@ -140,7 +152,7 @@ module "cloudformation_bucket" { } providers = { - aws = aws.cost_analysis + aws = aws.management } } @@ -148,12 +160,13 @@ module "cloudformation_bucket" { resource "aws_s3_object" "cloudformation_templates" { for_each = fileset("${path.module}/assets/cloudformation/", "**/*.yaml") - bucket = module.cloudformation_bucket.s3_bucket_id - key = each.value - source = "${path.module}/assets/cloudformation/${each.value}" - etag = filemd5("${path.module}/assets/cloudformation/cudos/${each.value}") + bucket = module.cloudformation_bucket.s3_bucket_id + etag = filemd5("${path.module}/assets/cloudformation/cudos/${each.value}") + key = each.value + server_side_encryption = "AES256" + source = "${path.module}/assets/cloudformation/${each.value}" - provider = aws.cost_analysis + provider = aws.management } ## Provision a bucket used to contain the cudos dashboards - note this @@ -164,21 +177,17 @@ module "dashboard_bucket" { source = "terraform-aws-modules/s3-bucket/aws" version = "4.1.2" - attach_deny_incorrect_encryption_headers = true - attach_deny_insecure_transport_policy = true - attach_deny_unencrypted_object_uploads = true - attach_require_latest_tls_policy = true - acl = "private" - block_public_acls = true - block_public_policy = true - bucket = var.dashboards_bucket_name - expected_bucket_owner = local.account_id - force_destroy = true - ignore_public_acls = true - object_ownership = "BucketOwnerPreferred" - policy = data.aws_iam_policy_document.dashboards_bucket_policy.json - restrict_public_buckets = true - tags = var.tags + attach_policy = true + block_public_acls = true + block_public_policy = true + bucket = var.dashboards_bucket_name + expected_bucket_owner = local.cost_analysis_account_id + force_destroy = true + ignore_public_acls = true + object_ownership = "BucketOwnerPreferred" + policy = data.aws_iam_policy_document.dashboards_bucket_policy.json + restrict_public_buckets = true + tags = var.tags server_side_encryption_configuration = { rule = { @@ -262,7 +271,7 @@ module "dashboards" { resource "aws_cloudformation_stack" "cudos_read_permissions" { name = var.stack_name_read_permissions capabilities = ["CAPABILITY_NAMED_IAM", "CAPABILITY_AUTO_EXPAND"] - template_url = format("%s/%s", local.template_base_url, "deploy-data-read-permissions.yaml") + template_url = format("%s/%s", local.stacks_base_url, "deploy-data-read-permissions.yaml") parameters = { "AllowModuleReadInMgmt" = "yes", @@ -295,7 +304,7 @@ resource "aws_cloudformation_stack" "cudos_read_permissions" { resource "aws_cloudformation_stack" "cudos_data_collection" { name = var.stack_name_collectors capabilities = ["CAPABILITY_NAMED_IAM", "CAPABILITY_AUTO_EXPAND"] - template_url = format("%s/%s", local.template_base_url, "deploy-data-collection.yaml") + template_url = format("%s/%s", local.stacks_base_url, "deploy-data-collection.yaml") parameters = { "IncludeBackupModule" = var.enable_backup_module ? "yes" : "no", diff --git a/quicksights.tf b/quicksights.tf index 7aa4537..2166613 100644 --- a/quicksights.tf +++ b/quicksights.tf @@ -3,9 +3,9 @@ resource "aws_quicksight_group" "groups" { for_each = var.quicksight_groups + description = each.value.description group_name = each.key namespace = each.value.namespace - description = each.value.description provider = aws.cost_analysis } @@ -15,10 +15,11 @@ resource "aws_quicksight_user" "users" { for_each = var.quicksight_users email = each.key - identity_type = "IAM" - user_role = each.value.role iam_arn = aws_iam_role.cudos_sso[0].arn + identity_type = "IAM" session_name = each.key + user_name = format("%s/%s", aws_iam_role.cudos_sso[0].name, each.key) + user_role = each.value.role provider = aws.cost_analysis } @@ -30,9 +31,7 @@ resource "aws_quicksight_group_membership" "members" { group_name = aws_quicksight_group.groups[each.value.group].group_name member_name = format("%s/%s", aws_iam_role.cudos_sso[0].name, each.value.user) - provider = aws.cost_analysis + depends_on = [aws_quicksight_user.users] - depends_on = [ - aws_quicksight_user.users, - ] + provider = aws.cost_analysis }