From 3d17f05e20a7b4392cd3e109421d8ab44003512e Mon Sep 17 00:00:00 2001 From: Daniel Palmer Date: Wed, 13 Mar 2024 15:37:58 +0000 Subject: [PATCH] LZA-163: Updates from testing --- modules/aws/group_user_memberships/main.tf | 221 ++++++++++++++++-- .../aws/group_user_memberships/variables.tf | 162 ++++++++++++- 2 files changed, 350 insertions(+), 33 deletions(-) diff --git a/modules/aws/group_user_memberships/main.tf b/modules/aws/group_user_memberships/main.tf index 0094898..edd904f 100644 --- a/modules/aws/group_user_memberships/main.tf +++ b/modules/aws/group_user_memberships/main.tf @@ -2,39 +2,216 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0.0, < 6.0.0" + version = "> 5.0.0, < 6.0.0" } } } -data "aws_identitystore_group" "identity_store_groups" { - identity_store_id = var.identity_store_id - - alternate_identifier { - unique_attribute { - attribute_path = "DisplayName" - attribute_value = var.group_name - } +provider "aws" { + region = "eu-west-2" +} + +provider "aws" { + region = "us-east-1" + alias = "us-east-1" +} + +#COST AND USAGE REPORT +resource "aws_cur_report_definition" "cur_report_definitions" { + depends_on = [aws_iam_role.cur_role, aws_s3_bucket_policy.cur_S3_bucket_policy] + provider = aws.us-east-1 + report_name = var.report_name + time_unit = var.time_unit + format = var.format + compression = var.compression + additional_schema_elements = var.additional_schema_elements + s3_bucket = aws_s3_bucket.s3_buckets.id + s3_region = var.bucket_region + additional_artifacts = var.additional_artifacts + s3_prefix = "cur/${var.billing_account}" + refresh_closed_reports = var.refresh_closed_reports + report_versioning = var.report_versioning +} + +#S3 BUCKET +resource "aws_s3_bucket" "s3_buckets" { + bucket = var.bucket_name +} + +#S3 SETTINGS +resource "aws_s3_bucket_ownership_controls" "bucket_ownership_controls" { + bucket = aws_s3_bucket.s3_buckets.id + rule { + object_ownership = "BucketOwnerEnforced" } } -data "aws_identitystore_user" "identity_store_users" { - for_each = toset(var.users) +resource "aws_s3_bucket_versioning" "versioning_rules" { + bucket = aws_s3_bucket.s3_buckets.id + versioning_configuration { + status = "Enabled" + } +} - identity_store_id = var.identity_store_id +resource "aws_s3_bucket_server_side_encryption_configuration" "encryption_rules" { + bucket = aws_s3_bucket.s3_buckets.id - alternate_identifier { - unique_attribute { - attribute_path = "UserName" - attribute_value = each.key + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" } } } -resource "aws_identitystore_group_membership" "group_membership" { - for_each = toset(var.users) - - identity_store_id = var.identity_store_id - group_id = data.aws_identitystore_group.identity_store_groups.id - member_id = data.aws_identitystore_user.identity_store_users[each.key].id +resource "aws_s3_bucket_public_access_block" "cur_public_access_block" { + bucket = aws_s3_bucket.s3_buckets.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +#IAM ROLE +resource "aws_iam_role" "cur_role" { + name = var.iam_role + assume_role_policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + "Action" : "sts:AssumeRole", + "Principal" : { + "Service" : "s3.amazonaws.com" + }, + "Effect" : "Allow", + "Sid" : "" + } + ] + }) + + inline_policy { + name = var.inline_policy_name + + policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + "Action" : [ + "s3:GetReplicationConfiguration", + "s3:ListBucket" + ], + "Resource" : "arn:aws:s3:::cid-${var.billing_account}-central-finops-local", + "Effect" : "Allow" + }, + { + "Action" : [ + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionAcl" + ], + "Resource" : "arn:aws:s3:::cid-${var.billing_account}-central-finops-local/*", + "Effect" : "Allow" + }, + { + "Action" : [ + "s3:ReplicateObject", + "s3:ReplicateDelete", + "s3:ReplicateTags", + "s3:GetObjectVersionTagging" + ], + "Resource" : "arn:aws:s3:::cid-873134405383-shared/cur/${var.billing_account}/*", + "Effect" : "Allow" + } + ] + }) + } +} + +#S3 BUCKET POLICY +resource "aws_s3_bucket_policy" "cur_S3_bucket_policy" { + bucket = aws_s3_bucket.s3_buckets.id + policy = jsonencode({ + "Version" : "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "billingreports.amazonaws.com" + }, + "Action": [ + "s3:GetBucketAcl", + "s3:GetBucketPolicy" + ], + "Resource": aws_s3_bucket.s3_buckets.arn, + "Condition": { + "StringEquals": { + "aws:SourceAccount": var.billing_account, + "aws:SourceArn": "arn:aws:cur:us-east-1:${var.billing_account}:definition/*" + } + } + }, + { + "Effect": "Allow", + "Principal": { + "Service": "billingreports.amazonaws.com" + }, + "Action": "s3:PutObject", + "Resource": "${aws_s3_bucket.s3_buckets.arn}/*", + "Condition": { + "StringEquals": { + "aws:SourceAccount": var.billing_account, + "aws:SourceArn": "arn:aws:cur:us-east-1:${var.billing_account}:definition/*" + } + } + } + ] + }) } + + +#S3 LIFECYCLE RULE +resource "aws_s3_bucket_lifecycle_configuration" "cur_bucket_lifecycle_rule" { + depends_on = [aws_s3_bucket_versioning.versioning_rules] + bucket = aws_s3_bucket.s3_buckets.id + rule { + id = var.lifecycle_rule + + filter {} + + noncurrent_version_expiration { + noncurrent_days = var.noncurrent_version_expiration_days + } + + expiration { + days = var.expiration_days + } + status = "Enabled" + } +} + +/* # REPLICATION RULE +resource "aws_s3_bucket_replication_configuration" "cur_bucket_replication_rule" { + depends_on = [aws_s3_bucket_versioning.versioning_rules] + bucket = aws_s3_bucket.s3_buckets.id + role = aws_iam_role.cur_role.arn + rule { + id = var.replication_rule + + filter {} + + destination { + bucket = var.destination_bucket + storage_class = "STANDARD" + } + + delete_marker_replication { + status = "Enabled" + } + + source_selection_criteria { + sse_kms_encrypted_objects { + status = "Disabled" + } + } + status = "Enabled" + } +} */ diff --git a/modules/aws/group_user_memberships/variables.tf b/modules/aws/group_user_memberships/variables.tf index d1df783..119b072 100644 --- a/modules/aws/group_user_memberships/variables.tf +++ b/modules/aws/group_user_memberships/variables.tf @@ -1,24 +1,164 @@ -variable "identity_store_id" { - description = "The AWS SSO instance to create the group in." +variable "report_name" { type = string + description = "The name of the cost and usage report to create." validation { - condition = can(regex("d-[a-z0-9]{10}", var.identity_store_id)) - error_message = "The identity store id must be in the format `d-` followed by 10 alphanumeric characters." + condition = length(var.report_name) >= 1 && length(var.report_name) <= 256 + error_message = "The report_name name must be less than 256 characters." } } -variable "users" { - description = "The AWS accounts to assign the group to." - type = list(string) +variable "time_unit" { + type = string + description = "The frequency on which report data are measured and displayed." + + validation { + condition = contains(["DAILY", "HOURLY", "MONTHLY"], var.time_unit) + error_message = "Valid values for time_unit are (DAILY, HOURLY, MONTHLY)" + } +} + +variable "format" { + type = string + description = "The format for the report." + + validation { + condition = contains(["textORcsv", "Parquet"], var.format) + error_message = "Valid values for format are (textORcsv, Parquet)" + } +} + +variable "compression" { + type = string + description = "Compression format for report." + + validation { + condition = contains(["GZIP", "ZIP", "Parquet"], var.compression) + error_message = "Valid values for time_unit are (GZIP, ZIP, Parquet)" + } +} + +variable "additional_schema_elements" { + type = list(string) + description = "A list of schema elements." + + validation { + condition = contains(var.additional_schema_elements, "RESOURCES") || contains(var.additional_schema_elements, "SPLIT_COST_ALLOCATION_DATA" ) + error_message = "Valid values for additional_schema_elements are (RESOURCES, SPLIT_COST_ALLOCATION_DATA)" + } +} + +variable "bucket_name" { + type = string + description = "The name of the existing s3 bucket store generated reports" + + validation { + condition = length(var.bucket_name) >= 1 && length(var.bucket_name) <= 64 + error_message = "The bucket_name name must be less than 64 characters." + } +} + +variable "bucket_region" { + type = string + description = "Region of the existing S3 bucket to hold generated reports." + + validation { + condition = can(regex("[a-z][a-z]-[a-z]+-[1-9]", var.bucket_region)) + error_message = "Must be valid AWS Region names." + } +} + +variable "additional_artifacts" { + type = list(string) + description = "A list of additional artifacts." + + validation { + condition = contains(var.additional_artifacts, "REDSHIFT") || contains(var.additional_artifacts, "QUICKSHIFT") || contains(var.additional_artifacts, "ATHENA") + error_message = "Valid values for time_unit are (REDSHIFT, QUICKSHIFT, ATHENA)" + } +} + +variable "refresh_closed_reports" { + type = string + description = "Set to true to update your reports after they have been finalized if AWS detects charges related to previous months." +} + +variable "report_versioning" { + type = string + description = "Overwrite the previous version of each report or to deliver the report in addition to the previous versions. Valid values are (CREATE_NEW_REPORT and OVERWRITE_REPORT)" +} + +variable "iam_role" { + type = string + description = "Friendly name of the role. If omitted, Terraform will assign a random, unique name" +} + +variable "lifecycle_rule" { + type = string + description = "The name of the lifecycle rule applied to S3" + + validation { + condition = length(var.lifecycle_rule) >= 1 && length(var.lifecycle_rule) <= 256 + error_message = "The lifecycle_rule name must be less than 256 characters." + } +} + +variable "noncurrent_version_expiration_days" { + type = number + description = "The Number of days an object is noncurrent before Amazon S3 can perform the associated action." + + validation { + condition = var.noncurrent_version_expiration_days > 0 + error_message = "The noncurrent_version_expiration_days variable must be a positive integer." + } +} + +variable "expiration_days" { + type = number + description = "The lifetime, in days, of the objects that are subject to the rule.." + + validation { + condition = var.expiration_days > 0 + error_message = "The expiration_days variable must be a positive integer." + } +} + +variable "inline_policy_name" { + type = string + description = "Name of the role policy." + + validation { + condition = length(var.inline_policy_name) >= 1 && length(var.inline_policy_name) <= 256 + error_message = "The inline_policy_name must be less than 256 characters." + } +} + +variable "billing_account" { + type = string + description = "AccountID for the billing account" + + validation { + condition = length(var.billing_account) == 12 + error_message = "The billing_account id must be 12 characters." + } } -variable "group_name" { - description = "The ID of the group to assign the user to." +/* variable "replication_rule" { type = string + description = "The name of the replication rule applied to S3" validation { - condition = length(var.group_name) >= 1 && length(var.group_name) <= 64 - error_message = "The group name must be less than 64 characters." + condition = length(var.replication_rule) >= 1 && length(var.replication_rule) <= 256 + error_message = "The replication_rule name must be less than 256 characters." } } + +#variable "destination_bucket" { + type = string + description = "The ARN of the existing s3 bucket to replicate generated reports to." + + validation { + condition = length(var.destination_bucket) >= 1 && length(var.destination_bucket) <= 256 + error_message = "The destination_bucket ARN must be less than 256 characters." + } +} */