diff --git a/modules/security_identity_compliance/aws_config/README.md b/modules/security_identity_compliance/aws_config/README.md index 1fea08d..16db163 100644 --- a/modules/security_identity_compliance/aws_config/README.md +++ b/modules/security_identity_compliance/aws_config/README.md @@ -1,8 +1,10 @@ # Overview This module performs the following tasks: -- Enable AWS config -- Create AWS config files for CIS benchmark +- Enable AWS config in all regions +- Deploy CIS1.4 level 1 conformance pack +- Set Config retention period +- Setup Config aggregator, aggregate Config in all regions into primary region - Create s3 bucket for config use ## Inputs: @@ -15,3 +17,5 @@ This module performs the following tasks: | default-tags | tags to be added to resources | list | none | yes | | aws-region-short | short name of aws region (e.g. apne1) | string | none | yes | +# Notes +It takes a while for AWS to process Config changes. \ No newline at end of file diff --git a/modules/security_identity_compliance/aws_config/cis-rules.tf b/modules/security_identity_compliance/aws_config/cis-rules.tf-no similarity index 100% rename from modules/security_identity_compliance/aws_config/cis-rules.tf rename to modules/security_identity_compliance/aws_config/cis-rules.tf-no diff --git a/modules/security_identity_compliance/aws_config/main.tf b/modules/security_identity_compliance/aws_config/main.tf index ff8ca73..e172743 100644 --- a/modules/security_identity_compliance/aws_config/main.tf +++ b/modules/security_identity_compliance/aws_config/main.tf @@ -5,11 +5,53 @@ */ data aws_caller_identity this {} +data aws_regions all-regions {} resource "aws_iam_service_linked_role" "config" { aws_service_name = "config.amazonaws.com" } +resource null_resource cli-resource-awsconfig { + for_each = data.aws_regions.all-regions.names + provisioner "local-exec" { + when = create + command = <<-EOD + wget -q https://raw.githubusercontent.com/awslabs/aws-config-rules/master/aws-config-conformance-packs/Operational-Best-Practices-for-CIS-AWS-v1.4-Level1.yaml -O Cis14Level1.yaml + aws configservice --region ${each.value} put-configuration-recorder --configuration-recorder name=default,roleARN="${aws_iam_service_linked_role.config.arn}" --recording-group allSupported=true,includeGlobalResourceTypes=true + aws configservice --region ${each.value} put-delivery-channel --delivery-channel name=default,s3BucketName=${module.config-bucket.bucket-name},configSnapshotDeliveryProperties={deliveryFrequency=Twelve_Hours} + aws configservice --region ${each.value} put-retention-configuration --retention-period-in-days ${var.config-retention-days} + aws configservice --region ${each.value} put-conformance-pack --conformance-pack-name Cis14Level1 --template-body file://Cis14Level1.yaml + aws configservice --region ${each.value} start-configuration-recorder --configuration-recorder-name default +EOD + } + + // Destroy provisioner does not accept variables. Workaround is to delete recorder in all regions. + provisioner "local-exec" { + when = destroy + on_failure = continue + command = <<-EOD + aws ec2 describe-regions | jq -cr .Regions[].RegionName | while read r; do + aws configservice --region $r describe-configuration-recorders --output text | while read dummy; do + aws configservice --region $r stop-configuration-recorder --configuration-recorder-name default + aws configservice --region $r delete-delivery-channel --delivery-channel-name default + aws configservice --region $r delete-configuration-recorder --configuration-recorder-name default + done + done +EOD + } +} + +resource "aws_config_configuration_aggregator" "config-aggregator" { + depends_on = [null_resource.cli-resource-awsconfig] + name = "ConfigAggregator" + + account_aggregation_source { + account_ids = [data.aws_caller_identity.this.id] + all_regions = true + } +} + +/* resource "aws_config_configuration_recorder" "config-recorder" { name = "${local.resource-prefix}-awsconfig" role_arn = aws_iam_service_linked_role.config.arn @@ -32,6 +74,7 @@ resource "aws_config_configuration_recorder_status" "main" { is_enabled = true depends_on = [aws_config_delivery_channel.config-delivery-channel] } +*/ ######## Config Bucket - Policy ######## diff --git a/modules/security_identity_compliance/aws_config/variables.tf b/modules/security_identity_compliance/aws_config/variables.tf index e1dcf7f..c7324ea 100644 --- a/modules/security_identity_compliance/aws_config/variables.tf +++ b/modules/security_identity_compliance/aws_config/variables.tf @@ -6,7 +6,10 @@ variable "aws-region-short" {} variable "default-tags" {} locals { - ct-bucket-name = "${var.environment}-${var.aws-region-short}-${var.customer-name}-${var.project}-ctbucket-${data.aws_caller_identity.this.account_id}" resource-prefix = "${var.environment}-${var.aws-region-short}-${var.customer-name}-${var.project}" } +variable config-retention-days { + type = number + default = 365 +} \ No newline at end of file diff --git a/modules/storage/infra-s3-bucket/main.tf b/modules/storage/infra-s3-bucket/main.tf index 31b094a..0b6132f 100644 --- a/modules/storage/infra-s3-bucket/main.tf +++ b/modules/storage/infra-s3-bucket/main.tf @@ -4,37 +4,65 @@ module random-suffix { resource "aws_s3_bucket" "s3bucket" { bucket = var.add-random-suffix ? "${var.bucket-name}-${module.random-suffix.number}" : var.bucket-name + tags = var.default-tags +} + +resource "aws_s3_bucket_policy" "bucket-policy" { + bucket = aws_s3_bucket.s3bucket.bucket policy = var.bucket-policy-json - versioning { - enabled = var.enable-bucket-versioning - } +} + resource "aws_s3_bucket_lifecycle_configuration" "bucket-lifecycle-config" { + count = var.bucket-enable-lifecycle ? 1 : 0 - server_side_encryption_configuration { - rule { - apply_server_side_encryption_by_default { - // kms_master_key_id = aws_kms_key.some-key.arn - sse_algorithm = "AES256" + bucket = aws_s3_bucket.s3bucket.bucket + + rule { + id = "default" + status = "Enabled" + + dynamic "noncurrent_version_expiration" { + for_each = var.enable-bucket-versioning ? [1] : [] + content { + noncurrent_days = 90 } } - } - tags = var.default-tags - lifecycle_rule { - id = "${var.bucket-name}-ctbucket-lifecycle-rule" - enabled = true - - transition { - days = 30 - storage_class = "INTELLIGENT_TIERING" + dynamic "expiration" { + for_each = var.bucket-retain-days > 0 ? [1] : [] + content { + days = var.bucket-retain-days + } } - expiration { - days = var.bucket-retain-days + transition { + days = var.transition-ia-days + storage_class = "STANDARD_IA" } } } +resource "aws_s3_bucket_acl" "bucket-acl" { + bucket = aws_s3_bucket.s3bucket.bucket + acl = var.bucket-acl +} + +resource "aws_s3_bucket_versioning" "bucket-versioning" { + count = var.enable-bucket-versioning ? 1 : 0 + bucket = aws_s3_bucket.s3bucket.id + versioning_configuration { + status = "Enabled" + } +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "bucket-encryption" { + bucket = aws_s3_bucket.s3bucket.bucket + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + } +} resource "aws_s3_bucket_public_access_block" "s3-public-access-settings" { bucket = aws_s3_bucket.s3bucket.id diff --git a/modules/storage/infra-s3-bucket/variables.tf b/modules/storage/infra-s3-bucket/variables.tf index f265abb..5590848 100644 --- a/modules/storage/infra-s3-bucket/variables.tf +++ b/modules/storage/infra-s3-bucket/variables.tf @@ -23,3 +23,17 @@ locals { resource-prefix = "${var.environment}-${var.aws-region-short}-${var.customer-name}-${var.project}" } +variable bucket-acl { + type = string + default = "private" +} + +variable bucket-enable-lifecycle { + type = bool + default = true +} + +variable transition-ia-days { + type = number + default = 30 +} \ No newline at end of file