From 33a0bc127a0c5ba2ebdec82078b44c3fb343d0dd Mon Sep 17 00:00:00 2001 From: Michael Kania Date: Mon, 2 Mar 2020 10:42:15 -0800 Subject: [PATCH 1/7] add cloudwatch log encyption rule --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++---- config-rules.tf | 14 ++++++++++++++ variables.tf | 5 +++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8eb5d97..879d26b 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,61 @@ +# AWS Config Terraform module + Enables AWS Config and adds managed config rules with good defaults. The following AWS Config Rules are supported: +## ACM + * acm-certificate-expiration-check: Ensure ACM Certificates in your account are marked for expiration within the specified number of days. + +## AMI + * approved-amis-by-tag: Checks whether running instances are using specified AMIs. + +## CloudTrail + * cloudtrail-enabled: Ensure CloudTrail is enabled. * cloud-trail-encryption-enabled: Ensure CloudTrail is configured to use server side encryption (SSE) with AWS KMS or CMK encryption. * cloud-trail-log-file-validation-enabled: Checks whether AWS CloudTrail creates a signed digest file with logs. * multi-region-cloud-trail-enabled: Ensure that there is at least one multi-region AWS CloudTrail enabled. + +## CloudWatch Logs + +* cloudwatch-log-group-encryption: Ensure that CloudWatch Logs are encrypted. + +## EC2 + * ec2-encrypted-volumes: Evaluates whether EBS volumes that are in an attached state are encrypted. * ec2-volume-inuse-check: Checks whether EBS volumes are attached to EC2 instances + +## VPC + * eip_attached: Checks whether all EIP addresses that are allocated to a VPC are attached to EC2 or in-use ENIs. +* instances-in-vpc: Ensure all EC2 instances run in a VPC. + +## GuardDuty + * guardduty-enabled-centralized: Checks whether Amazon GuardDuty is enabled in your AWS account and region. + +## IAM + * iam-password-policy: Ensure the account password policy for IAM users meets the specified requirements. * iam-user-no-policies-check: Ensure that none of your IAM users have policies attached; IAM users must inherit permissions from IAM groups or roles. * iam-group-has-users-check: Checks whether IAM groups have at least one IAM user. -* instances-in-vpc: Ensure all EC2 instances run in a VPC. -* required-tags: Checks if resources are deployed with configured tags. * root-account-mfa-enabled: Ensure root AWS account has MFA enabled. + +## Tagging + +* required-tags: Checks if resources are deployed with configured tags. + +## RDS + * rds-instance-public-access-check: Checks whether the Amazon Relational Database Service (RDS) instances are not publicly accessible. * rds-snapshots-public-prohibited: Checks if Amazon Relational Database Service (Amazon RDS) snapshots are public. * rds-storage-encrypted: Checks whether storage encryption is enabled for your RDS DB instances. + +## S3 + * s3-bucket-public-write-prohibited: Checks that your S3 buckets do not allow public write access. ## Terraform Versions @@ -62,6 +97,7 @@ module "aws_config" { | check\_cloud\_trail\_encryption | Enable cloud-trail-encryption-enabled rule | `bool` | `false` | no | | check\_cloud\_trail\_log\_file\_validation | Enable cloud-trail-log-file-validation-enabled rule | `bool` | `false` | no | | check\_cloudtrail\_enabled | Enable cloudtrail-enabled rule | `bool` | `true` | no | +| check\_cloudwatch\_log\_group\_encrypted | Enable cloudwatch-log-group-encryption rule | `bool` | `true` | no | | check\_ec2\_encrypted\_volumes | Enable ec2-encrypted-volumes rule | `bool` | `true` | no | | check\_ec2\_volume\_inuse\_check | Enable ec2-volume-inuse-check rule | `bool` | `true` | no | | check\_eip\_attached | Enable eip-attached rule | `bool` | `false` | no | @@ -115,12 +151,12 @@ brew install pre-commit go terraform terraform-docs automated testing with this module. Tests in the `test` folder can be run locally by running the following command: -```text +```shell make test ``` Or with aws-vault: -```text +```shell AWS_VAULT_KEYCHAIN_NAME= aws-vault exec -- make test ``` diff --git a/config-rules.tf b/config-rules.tf index 498fa33..707d9f4 100644 --- a/config-rules.tf +++ b/config-rules.tf @@ -340,3 +340,17 @@ resource "aws_config_config_rule" "ec2-encrypted-volumes" { depends_on = [aws_config_configuration_recorder.main] } + +resource "aws_config_config_rule" "cloudwatch_log_group_encrypted" { + count = var.check_cloudwatch_log_group_encrypted ? 1 : 0 + + name = "cloudwatch_log_group-encrypted" + description = "Checks whether a log group in Amazon CloudWatch Logs is encrypted. The rule is NON_COMPLIANT if CloudWatch Logs has a log group without encryption enabled" + + source { + owner = "AWS" + source_identifier = "CLOUDWATCH_LOG_GROUP_ENCRYPTED" + } + + depends_on = [aws_config_configuration_recorder.main] +} diff --git a/variables.tf b/variables.tf index 266640e..072353e 100644 --- a/variables.tf +++ b/variables.tf @@ -196,3 +196,8 @@ variable "check_s3_bucket_public_write_prohibited" { description = "Enable s3-bucket-public-write-prohibited rule" default = true } + +variable "check_cloudwatch_log_group_encrypted" { + description = "Enable cloudwatch-log-group-encryption rule" + default = true +} From 5d5d9c7c814a684638637932a2eb4279571b7e98 Mon Sep 17 00:00:00 2001 From: Michael Kania Date: Mon, 2 Mar 2020 10:44:18 -0800 Subject: [PATCH 2/7] cleanup titles --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 879d26b..071ebf3 100644 --- a/README.md +++ b/README.md @@ -2,59 +2,59 @@ Enables AWS Config and adds managed config rules with good defaults. -The following AWS Config Rules are supported: +## Supported AWS Config Rules -## ACM +### ACM * acm-certificate-expiration-check: Ensure ACM Certificates in your account are marked for expiration within the specified number of days. -## AMI +### AMI * approved-amis-by-tag: Checks whether running instances are using specified AMIs. -## CloudTrail +### CloudTrail * cloudtrail-enabled: Ensure CloudTrail is enabled. * cloud-trail-encryption-enabled: Ensure CloudTrail is configured to use server side encryption (SSE) with AWS KMS or CMK encryption. * cloud-trail-log-file-validation-enabled: Checks whether AWS CloudTrail creates a signed digest file with logs. * multi-region-cloud-trail-enabled: Ensure that there is at least one multi-region AWS CloudTrail enabled. -## CloudWatch Logs +### CloudWatch Logs * cloudwatch-log-group-encryption: Ensure that CloudWatch Logs are encrypted. -## EC2 +### EC2 * ec2-encrypted-volumes: Evaluates whether EBS volumes that are in an attached state are encrypted. * ec2-volume-inuse-check: Checks whether EBS volumes are attached to EC2 instances -## VPC +### VPC * eip_attached: Checks whether all EIP addresses that are allocated to a VPC are attached to EC2 or in-use ENIs. * instances-in-vpc: Ensure all EC2 instances run in a VPC. -## GuardDuty +### GuardDuty * guardduty-enabled-centralized: Checks whether Amazon GuardDuty is enabled in your AWS account and region. -## IAM +### IAM * iam-password-policy: Ensure the account password policy for IAM users meets the specified requirements. * iam-user-no-policies-check: Ensure that none of your IAM users have policies attached; IAM users must inherit permissions from IAM groups or roles. * iam-group-has-users-check: Checks whether IAM groups have at least one IAM user. * root-account-mfa-enabled: Ensure root AWS account has MFA enabled. -## Tagging +### Tagging * required-tags: Checks if resources are deployed with configured tags. -## RDS +### RDS * rds-instance-public-access-check: Checks whether the Amazon Relational Database Service (RDS) instances are not publicly accessible. * rds-snapshots-public-prohibited: Checks if Amazon Relational Database Service (Amazon RDS) snapshots are public. * rds-storage-encrypted: Checks whether storage encryption is enabled for your RDS DB instances. -## S3 +### S3 * s3-bucket-public-write-prohibited: Checks that your S3 buckets do not allow public write access. From 70d91de4c0900cb7bebb9953a4c7a17d5494a2a6 Mon Sep 17 00:00:00 2001 From: Michael Kania Date: Mon, 2 Mar 2020 11:04:49 -0800 Subject: [PATCH 3/7] updates dependencies --- .circleci/config.yml | 2 +- .pre-commit-config.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 50d2808..d43e5b0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: validate: docker: - - image: trussworks/circleci-docker-primary:40076395a6e6a349f92caa92c4de614e105fe672 + - image: trussworks/circleci-docker-primary:abca33ce0067fe58a4e33139ae470b65f1cab1f9 steps: - checkout - restore_cache: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index eaa9ebb..060a53e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: git://github.com/pre-commit/pre-commit-hooks - rev: v2.4.0 + rev: v2.5.0 hooks: - id: check-json - id: check-merge-conflict @@ -12,17 +12,17 @@ repos: - id: trailing-whitespace - repo: git://github.com/igorshubovych/markdownlint-cli - rev: v0.21.0 + rev: v0.22.0 hooks: - id: markdownlint - repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.24.0 + rev: v1.27.0 hooks: - id: terraform_docs - id: terraform_fmt - repo: git://github.com/golangci/golangci-lint - rev: v1.23.1 + rev: v1.23.7 hooks: - id: golangci-lint From 83ee0788cf01b00abb3eaafae730884e1a761c31 Mon Sep 17 00:00:00 2001 From: Michael Kania Date: Mon, 2 Mar 2020 11:05:42 -0800 Subject: [PATCH 4/7] updates example versions --- examples/required-tags/main.tf | 2 +- examples/simple/main.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/required-tags/main.tf b/examples/required-tags/main.tf index 05c12e5..a0fb040 100644 --- a/examples/required-tags/main.tf +++ b/examples/required-tags/main.tf @@ -4,7 +4,7 @@ module "config_logs" { source = "trussworks/logs/aws" - version = "~> 3" + version = "~> 5" s3_bucket_name = "${var.config_logs_bucket}" region = "${var.region}" diff --git a/examples/simple/main.tf b/examples/simple/main.tf index 5e3497e..339f28a 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -4,7 +4,7 @@ module "config_logs" { source = "trussworks/logs/aws" - version = "~> 3" + version = "~> 5" s3_bucket_name = "${var.config_logs_bucket}" region = "${var.region}" From c6adf4c6135f546cde325891b35955497c87eb1b Mon Sep 17 00:00:00 2001 From: Michael Kania Date: Mon, 2 Mar 2020 11:15:48 -0800 Subject: [PATCH 5/7] add types to variables --- variables.tf | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/variables.tf b/variables.tf index 072353e..9565fbf 100644 --- a/variables.tf +++ b/variables.tf @@ -41,86 +41,103 @@ variable "config_delivery_frequency" { variable "acm_days_to_expiration" { description = "Specify the number of days before the rule flags the ACM Certificate as noncompliant." + type = number default = 14 } variable "password_require_uppercase" { description = "Require at least one uppercase character in password." + type = bool default = true } variable "password_require_lowercase" { description = "Require at least one lowercase character in password." + type = bool default = true } variable "password_require_symbols" { description = "Require at least one symbol in password." + type = bool default = true } variable "password_require_numbers" { description = "Require at least one number in password." + type = bool default = true } variable "password_min_length" { description = "Password minimum length." + type = number default = 14 } variable "password_reuse_prevention" { description = "Number of passwords before allowing reuse." + type = number default = 24 } variable "password_max_age" { description = "Number of days before password expiration." + type = number default = 90 } variable "check_root_account_mfa_enabled" { description = "Enable root-account-mfa-enabled rule" + type = bool default = false } variable "check_guard_duty" { description = "Enable guardduty-enabled-centralized rule" + type = bool default = false } variable "check_rds_public_access" { description = "Enable rds-instance-public-access-check rule" + type = bool default = false } variable "check_multi_region_cloud_trail" { description = "Enable multi-region-cloud-trail-enabled rule" + type = bool default = false } variable "check_cloudtrail_enabled" { description = "Enable cloudtrail-enabled rule" + type = bool default = true } variable "check_cloud_trail_encryption" { description = "Enable cloud-trail-encryption-enabled rule" + type = bool default = false } variable "check_cloud_trail_log_file_validation" { description = "Enable cloud-trail-log-file-validation-enabled rule" + type = bool default = false } variable "check_eip_attached" { description = "Enable eip-attached rule" + type = bool default = false } variable "check_required_tags" { description = "Enable required-tags rule" + type = bool default = false } @@ -138,36 +155,43 @@ variable "required_tags" { variable "check_instances_in_vpc" { description = "Enable instances-in-vpc rule" + type = bool default = true } variable "check_acm_certificate_expiration_check" { description = "Enable acm-certificate-expiration-check rule" + type = bool default = true } variable "check_iam_password_policy" { description = "Enable iam-password-policy rule" + type = bool default = true } variable "check_iam_group_has_users_check" { description = "Enable iam-group-has-users-check rule" + type = bool default = true } variable "check_iam_user_no_policies_check" { description = "Enable iam-user-no-policies-check rule" + type = bool default = true } variable "check_ec2_volume_inuse_check" { description = "Enable ec2-volume-inuse-check rule" + type = bool default = true } variable "check_approved_amis_by_tag" { description = "Enable approved-amis-by-tag rule" + type = bool default = false } @@ -179,25 +203,30 @@ variable "ami_required_tag_key_value" { variable "check_ec2_encrypted_volumes" { description = "Enable ec2-encrypted-volumes rule" + type = bool default = true } variable "check_rds_storage_encrypted" { description = "Enable rds-storage-encrypted rule" + type = bool default = true } variable "check_rds_snapshots_public_prohibited" { description = "Enable rds-snapshots-public-prohibited rule" + type = bool default = true } variable "check_s3_bucket_public_write_prohibited" { description = "Enable s3-bucket-public-write-prohibited rule" + type = bool default = true } variable "check_cloudwatch_log_group_encrypted" { description = "Enable cloudwatch-log-group-encryption rule" + type = bool default = true } From 0beb1ec81e8ebba47f482bd8d38d31b8e8d46954 Mon Sep 17 00:00:00 2001 From: Michael Kania Date: Mon, 2 Mar 2020 11:23:03 -0800 Subject: [PATCH 6/7] Cleanup 0.11 syntax in tests --- examples/required-tags/main.tf | 9 +++++---- examples/simple/main.tf | 9 +++++---- go.sum | 2 -- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/required-tags/main.tf b/examples/required-tags/main.tf index a0fb040..b147a18 100644 --- a/examples/required-tags/main.tf +++ b/examples/required-tags/main.tf @@ -6,17 +6,18 @@ module "config_logs" { source = "trussworks/logs/aws" version = "~> 5" - s3_bucket_name = "${var.config_logs_bucket}" - region = "${var.region}" - allow_config = "true" + s3_bucket_name = var.config_logs_bucket + region = var.region + allow_config = true config_logs_prefix = "config" + force_destroy = true } module "config" { source = "../../" config_name = var.config_name - config_logs_bucket = "${module.config_logs.aws_logs_bucket}" + config_logs_bucket = module.config_logs.aws_logs_bucket config_logs_prefix = "config" check_required_tags = true diff --git a/examples/simple/main.tf b/examples/simple/main.tf index 339f28a..e3518d6 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -6,16 +6,17 @@ module "config_logs" { source = "trussworks/logs/aws" version = "~> 5" - s3_bucket_name = "${var.config_logs_bucket}" - region = "${var.region}" - allow_config = "true" + s3_bucket_name = var.config_logs_bucket + region = var.region + allow_config = true config_logs_prefix = "config" + force_destroy = true } module "config" { source = "../../" config_name = var.config_name - config_logs_bucket = "${module.config_logs.aws_logs_bucket}" + config_logs_bucket = module.config_logs.aws_logs_bucket config_logs_prefix = "config" } diff --git a/go.sum b/go.sum index 24ae4d1..dbf4d26 100644 --- a/go.sum +++ b/go.sum @@ -193,8 +193,6 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/gruntwork-io/gruntwork-cli v0.5.1 h1:mVmVsFubUSLSCO8bGigI63HXzvzkC0uWXzm4dd9pXRg= github.com/gruntwork-io/gruntwork-cli v0.5.1/go.mod h1:IBX21bESC1/LGoV7jhXKUnTQTZgQ6dYRsoj/VqxUSZQ= -github.com/gruntwork-io/terratest v0.23.4 h1:3H8/gS4XJvy3AwPyvil3yMMeiBB6FrGP9IvJI6e2uis= -github.com/gruntwork-io/terratest v0.23.4/go.mod h1:ds4v1EDndcBq3zNUPs1uot0YGWDbk++I5KPSOSJ6df4= github.com/gruntwork-io/terratest v0.24.2 h1:ZL7s7ZaVPRds+HqtPFh8gXjFVpKRNAAbwyVPYx3lH50= github.com/gruntwork-io/terratest v0.24.2/go.mod h1:0MCPUGIgQaAXOmw0qRLqyIXs8q6yoNPB3aZt4SkdH0M= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= From 76946fe2b94a308b892357e101179f3c0d39d509 Mon Sep 17 00:00:00 2001 From: Michael Kania Date: Mon, 2 Mar 2020 11:28:39 -0800 Subject: [PATCH 7/7] don't empty buckets in terratest now that we have a force_destroy flag --- test/terraform_aws_config_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/terraform_aws_config_test.go b/test/terraform_aws_config_test.go index c9d2041..d3fd227 100644 --- a/test/terraform_aws_config_test.go +++ b/test/terraform_aws_config_test.go @@ -5,7 +5,6 @@ import ( "strings" "testing" - "github.com/gruntwork-io/terratest/modules/aws" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" test_structure "github.com/gruntwork-io/terratest/modules/test-structure" @@ -40,9 +39,6 @@ func TestTerraformAwsConfig(t *testing.T) { defer terraform.Destroy(t, terraformOptions) - // Empty config_logs_bucket before terraform destroy - defer aws.EmptyS3Bucket(t, awsRegion, expectedConfigLogsBucket) - terraform.InitAndApply(t, terraformOptions) requiredTagsRuleARN := terraform.Output(t, terraformOptions, "required_tags_rule_arn") @@ -77,7 +73,6 @@ func TestRequiredTags(t *testing.T) { } defer terraform.Destroy(t, terraformOptions) - defer aws.EmptyS3Bucket(t, awsRegion, expectedConfigLogsBucket) terraform.InitAndApply(t, terraformOptions)