Skip to main content
Security Modules 0.71.0Last updated in version 0.70.0

AWS Config Multi Region Module

View SourceRelease Notes

This module wraps the aws-config core module to configure AWS Config in all enabled regions for the AWS Account, and optionally can aggregate AWS Config across multiple accounts.

multi account multi region aws configmulti account multi region aws config

Features

  • Enable AWS Config in all regions

  • Store config items in an encrypted S3 bucket for persistence

  • Configure config items to be automatically archive and delete after a certain time period

  • Designate and configure a global recorder region

  • Create an aggregated view of all regions

  • Consolidate AWS Config from multiple AWS accounts to the S3 bucket and SNS topics in a central account

  • Configure a set of default AWS managed config rules

Learn

Note

This repo is a part of the Gruntwork Infrastructure as Code Library, a collection of reusable, battle-tested, production ready infrastructure code. If you’ve never used the Infrastructure as Code Library before, make sure to read How to use the Gruntwork Infrastructure as Code Library!

Core concepts

Repo organization

  • modules: the main implementation code for this repo, broken down into multiple standalone, orthogonal submodules.

  • codegen: Code generation utilities that help generate modules in this repo.

  • examples: This folder contains working examples of how to use the submodules.

  • test: Automated tests for the modules and examples.

Deploy

Sample Usage

main.tf

# ------------------------------------------------------------------------------------------------------
# DEPLOY GRUNTWORK'S AWS-CONFIG-MULTI-REGION MODULE
# ------------------------------------------------------------------------------------------------------

module "aws_config_multi_region" {

source = "git::git@github.com:gruntwork-io/terraform-aws-security.git//modules/aws-config-multi-region?ref=v0.71.0"

# ----------------------------------------------------------------------------------------------------
# REQUIRED VARIABLES
# ----------------------------------------------------------------------------------------------------

# The AWS Account ID the template should be operated on. This avoids
# misconfiguration errors caused by environment variables.
aws_account_id = <string>

# The name of the S3 Bucket where Config items will be stored. Can be in the
# same account or in another account.
s3_bucket_name = <string>

# ----------------------------------------------------------------------------------------------------
# OPTIONAL VARIABLES
# ----------------------------------------------------------------------------------------------------

# The S3 bucket where access logs for this bucket should be stored. Only used
# if access_logging_enabled is true.
access_logging_bucket = null

# A prefix (i.e., folder path) to use for all access logs stored in
# access_logging_bucket. Only used if access_logging_enabled is true.
access_logging_prefix = null

# Map of additional managed rules to add on top of the defaults. The key is
# the name of the rule (e.g. ´acm-certificate-expiration-check´) and the value
# is an object specifying the rule details
additional_config_rules = {}

# Set to true to send the AWS Config data to another account (e.g., a logs
# account) for aggregation purposes. You must set the ID of that other account
# via the central_account_id variable. This redundant variable has to exist
# because Terraform does not allow computed data in count and for_each
# parameters and var.central_account_id may be computed if its the ID of a
# newly-created AWS account.
aggregate_config_data_in_external_account = false

# The ARN of the policy that is used to set the permissions boundary for the
# IAM role.
aws_config_iam_role_permissions_boundary = null

# For multi-account deployments, set this to the account ID of the central
# account in which the S3 bucket and SNS topic exist. Only used if
# aggregate_config_data_in_external_account is true.
central_account_id = null

# A name for the configuration recorder and delivery channel. If not provided,
# the name is set to 'default'.
config_name = null

# List of AWS account identifiers to exclude from the rules. Only used if
# create_account_rules is false.
config_rule_excluded_accounts = []

# The maximum frequency with which AWS Config runs evaluations for the
# ´PERIODIC´ rules. See
# https://www.terraform.io/docs/providers/aws/r/config_organization_managed_rule.html#maximum_execution_frequency
config_rule_maximum_execution_frequency = "TwentyFour_Hours"

# Set to true to create the config rules at the account level or false to
# create them at the organization level. When you create rules at the
# organization level, you must run this module in the root account, and the
# rules will apply to EVERY account in the organization. This allows you to
# manage the rules centrally, which is convenient, but also has a dependency /
# ordering issue, as org level config rules require every child account to
# have an AWS Config Recorder already set up, which is very inconvenient (when
# adding a new account, you first have to leave the rules disabled for it,
# then create the account, apply a baseline to it that creates a Config
# Recorder, and then go back to the root and enable the rules). When creating
# rules at the account level, you have to create and manage the rules in each
# account separately, which is inconvenient (but only slightly, since it's all
# managed as code), but there are no dependency or ordering issues.
create_account_rules = true

# Set to false to have this module skip creating resources. This weird
# parameter exists solely because Terraform does not support conditional
# modules. Therefore, this is a hack to allow you to conditionally decide if
# the resources should be created or not.
create_resources = true

# Optional KMS key to use for encrypting S3 objects on the AWS Config delivery
# channel for an externally managed S3 bucket. This must belong to the same
# region as the destination S3 bucket. If null, AWS Config will default to
# encrypting the delivered data with AES-256 encryption. Only used if
# var.should_create_s3_bucket is false - otherwise, var.kms_key_arn is used.
delivery_channel_kms_key_arn = null

# The frequency with which AWS Config delivers configuration snapshots. When
# null, defaults to the maximum execution frequency of each rule. Valid
# values: One_Hour | Three_Hours | Six_Hours | Twelve_Hours | TwentyFour_Hours
delivery_frequency = null

# When true, enable the global AWS Config Configuration Aggregator on all
# regions regardless of what is passed into var.opt_in_regions.
enable_all_regions_for_config_aggregator = false

# Set to true to create a set of default config rules in each enabled region.
enable_config_rules = true

# Checks whether the EBS volumes that are in an attached state are encrypted.
enable_encrypted_volumes_rule = true

# Checks whether the account password policy for IAM users meets the specified
# requirements.
enable_iam_password_policy_rule = true

# Checks whether your IAM users have passwords or active access keys that have
# not been used within the specified number of days.
enable_iam_user_unused_credentials_check = true

# Checks whether the security group with 0.0.0.0/0 of any Amazon Virtual
# Private Cloud (Amazon VPC) allows only specific inbound TCP or UDP traffic.
enable_insecure_sg_rules = true

# Checks whether storage encryption is enabled for your RDS DB instances.
enable_rds_storage_encrypted_rule = true

# Checks whether users of your AWS account require a multi-factor
# authentication (MFA) device to sign in with root credentials.
enable_root_account_mfa_rule = true

# Checks that your Amazon S3 buckets do not allow public read access.
enable_s3_bucket_public_read_prohibited_rule = true

# Checks that your Amazon S3 buckets do not allow public write access.
enable_s3_bucket_public_write_prohibited_rule = true

# Enables S3 server access logging which sends detailed records for the
# requests that are made to the bucket. Defaults to false.
enable_s3_server_access_logging = false

# ID or ARN of the KMS key that is used to encrypt the volume. Used for
# configuring the encrypted volumes config rule.
encrypted_volumes_kms_id = null

# If set to true, when you run 'terraform destroy', delete all objects from
# the bucket so that the bucket can be destroyed without error. Warning: these
# objects are not recoverable so only use this if you're absolutely sure you
# want to permanently delete everything!
force_destroy = false

# The AWS Region to use as the global recorder.
global_recorder_region = "us-east-1"

# Number of days before password expiration.
iam_password_policy_rule_max_password_age = 30

# Password minimum length.
iam_password_policy_rule_minimum_password_length = 16

# Number of passwords before allowing reuse.
iam_password_policy_rule_password_reuse_prevention = 5

# Require at least one lowercase character in password.
iam_password_policy_rule_require_lowercase_characters = true

# Require at least one number in password.
iam_password_policy_rule_require_numbers = true

# Require at least one symbol in password.
iam_password_policy_rule_require_symbols = true

# Require at least one uppercase character in password.
iam_password_policy_rule_require_uppercase_characters = true

# The name of an IAM role for Config service to assume. Must be unique within
# the AWS account.
iam_role_name = "AWS_ConfigRole"

# Maximum number of days a credential can be not used.
iam_user_max_credential_usage_age = 90

# Comma-separated list of TCP ports authorized to be open to 0.0.0.0/0. Ranges
# are defined by a dash; for example, '443,1020-1025'.
insecure_sg_rules_authorized_tcp_ports = null

# Comma-separated list of UDP ports authorized to be open to 0.0.0.0/0. Ranges
# are defined by a dash; for example, '500,1020-1025'.
insecure_sg_rules_authorized_udp_ports = null

# Optional KMS key to use for each region for configuring default encryption
# for the S3 bucket and SNS topic (encoded as a map from region - e.g.
# us-east-1 - to ARN of KMS key). This is a backward compatible interface for
# configuring a single KMS key for both S3 objects and the SNS topic. When
# null, falls back to using var.s3_bucket_kms_key_arn and
# var.sns_topic_kms_key_region_map
kms_key_arn = null

# For multi-account deployments, in the central account, provide a list of AWS
# account IDs that should have permissions to write to the S3 bucket and
# publish to the SNS topic. Use this in conjunction with
# should_create_s3_bucket and sns_topic_name. If this is a child account,
# leave this list empty.
linked_accounts = []

# After this number of days, log files should be transitioned from S3 to
# Glacier. Enter 0 to never archive log data.
num_days_after_which_archive_log_data = 365

# After this number of days, log files should be deleted from S3. Enter 0 to
# never delete log data.
num_days_after_which_delete_log_data = 730

# KMS key ID or ARN used to encrypt the storage. Used for configuring the RDS
# storage encryption config rule.
rds_storage_encrypted_kms_id = null

# Set to true to enable replication for this bucket. You can set the role to
# use for replication using the replication_role parameter and the rules for
# replication using the replication_rules parameter.
replication_enabled = false

# The ARN of the IAM role for Amazon S3 to assume when replicating objects.
# Only used if replication_enabled is set to true.
replication_role = null

# The rules for managing replication. Only used if replication_enabled is set
# to true. This should be a map, where the key is a unique ID for each
# replication rule and the value is an object of the form explained in a
# comment above.
replication_rules = {}

# Optional KMS key to use for encrypting S3 objects on the AWS Config bucket,
# when the S3 bucket is created within this module
# (var.should_create_s3_bucket is true). For encrypting S3 objects on delivery
# for an externally managed S3 bucket, refer to the
# var.delivery_channel_kms_key_arn input variable. If null, data in S3 will be
# encrypted using the default aws/s3 key. If provided, the key policy of the
# provided key must permit the IAM role used by AWS Config. See
# https://docs.aws.amazon.com/sns/latest/dg/sns-key-management.html. Note that
# the key should be in the same region as the global recorder region (where
# the S3 bucket will be created).
s3_bucket_kms_key_arn = null

# Enable MFA delete for either 'Change the versioning state of your bucket' or
# 'Permanently delete an object version'. This setting only applies to the
# bucket used to storage AWS Config data. This cannot be used to toggle this
# setting but is available to allow managed buckets to reflect the state in
# AWS. For instructions on how to enable MFA Delete, check out the README from
# the private-s3-bucket module. CIS v1.4 requires this variable to be true. If
# you do not wish to be CIS-compliant, you can set it to false.
s3_mfa_delete = false

# A prefix to use when storing Config objects in S3. This will be the
# beginning of the path in the S3 object. For example: <s3 bucket
# name>:/<prefix>/AWSLogs/<account ID>/Config/*. If this variable is null (the
# default), the path will not include any prefix: e.g., it'll be <s3 bucket
# name>:/AWSLogs/<account ID>/Config/*.
s3_object_prefix = null

# Set this to true to create an S3 bucket in the same region where the global
# recorder is configured. For multi-account deployments, set this to true for
# the central account that should host the S3 bucket and SNS topics, and false
# for all other accounts.
should_create_s3_bucket = true

# If true, create an SNS topic for Config notifications.
should_create_sns_topic = true

# Optional KMS key to use for each region for configuring default encryption
# for the SNS topic (encoded as a map from region - e.g. us-east-1 - to ARN of
# KMS key). If null or the region key is missing, encryption will not be
# configured for the SNS topic in that region.
sns_topic_kms_key_region_map = null

# The name of the SNS topic to use for Config notifications.
sns_topic_name = "ConfigTopic"

# A map of tags to apply to the S3 Bucket. The key is the tag name and the
# value is the tag value.
tags = {}

# When true, all IAM policies will be managed as dedicated policies rather
# than inline policies attached to the IAM roles. Dedicated managed policies
# are friendlier to automated policy checkers, which may scan a single
# resource for findings. As such, it is important to avoid inline policies
# when targeting compliance with various security standards.
use_managed_iam_policies = true

}


Reference

Required

aws_account_idstringrequired

The AWS Account ID the template should be operated on. This avoids misconfiguration errors caused by environment variables.

s3_bucket_namestringrequired

The name of the S3 Bucket where Config items will be stored. Can be in the same account or in another account.

Optional

access_logging_bucketstringoptional

The S3 bucket where access logs for this bucket should be stored. Only used if access_logging_enabled is true.

null
access_logging_prefixstringoptional

A prefix (i.e., folder path) to use for all access logs stored in access_logging_bucket. Only used if access_logging_enabled is true.

null
additional_config_rulesmap(object(…))optional

Map of additional managed rules to add on top of the defaults. The key is the name of the rule (e.g. ´acm-certificate-expiration-check´) and the value is an object specifying the rule details

map(object({
# Description of the rule
description = string
# Identifier of an available AWS Config Managed Rule to call.
identifier = string
# Trigger type of the rule, must be one of ´CONFIG_CHANGE´ or ´PERIODIC´.
trigger_type = string
# A map of input parameters for the rule. If you don't have parameters, pass in an empty map ´{}´.
input_parameters = map(string)
# Whether or not this applies to global (non-regional) resources like IAM roles. When true, these rules are only
# applied in the global config recorder region.
applies_to_global_resources = bool
}))
{}
Example
   additional_config_rules = {
acm-certificate-expiration-check = {
description = "Checks whether ACM Certificates in your account are marked for expiration within the specified number of days.",
identifier = "ACM_CERTIFICATE_EXPIRATION_CHECK",
trigger_type = "PERIODIC",
input_parameters = { "daysToExpiration": "14"},
applies_to_global_resources = false
}
}

Set to true to send the AWS Config data to another account (e.g., a logs account) for aggregation purposes. You must set the ID of that other account via the central_account_id variable. This redundant variable has to exist because Terraform does not allow computed data in count and for_each parameters and central_account_id may be computed if its the ID of a newly-created AWS account.

false

The ARN of the policy that is used to set the permissions boundary for the IAM role.

null
central_account_idstringoptional

For multi-account deployments, set this to the account ID of the central account in which the S3 bucket and SNS topic exist. Only used if aggregate_config_data_in_external_account is true.

null
config_namestringoptional

A name for the configuration recorder and delivery channel. If not provided, the name is set to 'default'.

null
config_rule_excluded_accountslist(string)optional

List of AWS account identifiers to exclude from the rules. Only used if create_account_rules is false.

[]

The maximum frequency with which AWS Config runs evaluations for the ´PERIODIC´ rules. See https://www.terraform.io/docs/providers/aws/r/config_organization_managed_rule.html#maximum_execution_frequency

"TwentyFour_Hours"

Set to true to create the config rules at the account level or false to create them at the organization level. When you create rules at the organization level, you must run this module in the root account, and the rules will apply to EVERY account in the organization. This allows you to manage the rules centrally, which is convenient, but also has a dependency / ordering issue, as org level config rules require every child account to have an AWS Config Recorder already set up, which is very inconvenient (when adding a new account, you first have to leave the rules disabled for it, then create the account, apply a baseline to it that creates a Config Recorder, and then go back to the root and enable the rules). When creating rules at the account level, you have to create and manage the rules in each account separately, which is inconvenient (but only slightly, since it's all managed as code), but there are no dependency or ordering issues.

true
create_resourcesbooloptional

Set to false to have this module skip creating resources. This weird parameter exists solely because Terraform does not support conditional modules. Therefore, this is a hack to allow you to conditionally decide if the resources should be created or not.

true

Optional KMS key to use for encrypting S3 objects on the AWS Config delivery channel for an externally managed S3 bucket. This must belong to the same region as the destination S3 bucket. If null, AWS Config will default to encrypting the delivered data with AES-256 encryption. Only used if should_create_s3_bucket is false - otherwise, kms_key_arn is used.

null
delivery_frequencystringoptional

The frequency with which AWS Config delivers configuration snapshots. When null, defaults to the maximum execution frequency of each rule. Valid values: One_Hour | Three_Hours | Six_Hours | Twelve_Hours | TwentyFour_Hours

null

When true, enable the global AWS Config Configuration Aggregator on all regions regardless of what is passed into opt_in_regions.

false

Set to true to create a set of default config rules in each enabled region.

true

Checks whether the EBS volumes that are in an attached state are encrypted.

true

Checks whether the account password policy for IAM users meets the specified requirements.

true

Checks whether your IAM users have passwords or active access keys that have not been used within the specified number of days.

true

Checks whether the security group with 0.0.0.0/0 of any Amazon Virtual Private Cloud (Amazon VPC) allows only specific inbound TCP or UDP traffic.

true

Checks whether storage encryption is enabled for your RDS DB instances.

true

Checks whether users of your AWS account require a multi-factor authentication (MFA) device to sign in with root credentials.

true

Checks that your Amazon S3 buckets do not allow public read access.

true

Checks that your Amazon S3 buckets do not allow public write access.

true

Enables S3 server access logging which sends detailed records for the requests that are made to the bucket. Defaults to false.

false

ID or ARN of the KMS key that is used to encrypt the volume. Used for configuring the encrypted volumes config rule.

null
force_destroybooloptional

If set to true, when you run 'terraform destroy', delete all objects from the bucket so that the bucket can be destroyed without error. Warning: these objects are not recoverable so only use this if you're absolutely sure you want to permanently delete everything!

false

The AWS Region to use as the global recorder.

"us-east-1"

Number of days before password expiration.

30

Password minimum length.

16

Number of passwords before allowing reuse.

5

Require at least one lowercase character in password.

true

Require at least one number in password.

true

Require at least one symbol in password.

true

Require at least one uppercase character in password.

true
iam_role_namestringoptional

The name of an IAM role for Config service to assume. Must be unique within the AWS account.

"AWS_ConfigRole"

Maximum number of days a credential can be not used.

90

Comma-separated list of TCP ports authorized to be open to 0.0.0.0/0. Ranges are defined by a dash; for example, '443,1020-1025'.

null

Comma-separated list of UDP ports authorized to be open to 0.0.0.0/0. Ranges are defined by a dash; for example, '500,1020-1025'.

null
kms_key_arnmap(string)optional

Optional KMS key to use for each region for configuring default encryption for the S3 bucket and SNS topic (encoded as a map from region - e.g. us-east-1 - to ARN of KMS key). This is a backward compatible interface for configuring a single KMS key for both S3 objects and the SNS topic. When null, falls back to using s3_bucket_kms_key_arn and sns_topic_kms_key_region_map

null
linked_accountslist(string)optional

For multi-account deployments, in the central account, provide a list of AWS account IDs that should have permissions to write to the S3 bucket and publish to the SNS topic. Use this in conjunction with should_create_s3_bucket and sns_topic_name. If this is a child account, leave this list empty.

[]

After this number of days, log files should be transitioned from S3 to Glacier. Enter 0 to never archive log data.

365

After this number of days, log files should be deleted from S3. Enter 0 to never delete log data.

730

KMS key ID or ARN used to encrypt the storage. Used for configuring the RDS storage encryption config rule.

null

Set to true to enable replication for this bucket. You can set the role to use for replication using the replication_role parameter and the rules for replication using the replication_rules parameter.

false
replication_rolestringoptional

The ARN of the IAM role for Amazon S3 to assume when replicating objects. Only used if replication_enabled is set to true.

null

The rules for managing replication. Only used if replication_enabled is set to true. This should be a map, where the key is a unique ID for each replication rule and the value is an object of the form explained in a comment above.

Any types represent complex values of variable type. For details, please consult `variables.tf` in the source repo.
{}
Example
   {
ExampleConfig = {
prefix = "config/"
status = "Enabled"
destination_bucket = "arn:aws:s3:::my-destination-bucket"
destination_storage_class = "STANDARD"
}
}

Details

Ideally, this would be a list(object({...})), but the Terraform object type constraint doesn't support optional
parameters, whereas replication rules have many optional params. And we can't even use list(any), as the Terraform
list type constraint requires all values to have the same type ("shape"), but as each object in the list may specify
different optional params, this won't work either. So, sadly, we are forced to fall back to "any."

s3_bucket_kms_key_arnstringoptional

Optional KMS key to use for encrypting S3 objects on the AWS Config bucket, when the S3 bucket is created within this module (should_create_s3_bucket is true). For encrypting S3 objects on delivery for an externally managed S3 bucket, refer to the delivery_channel_kms_key_arn input variable. If null, data in S3 will be encrypted using the default aws/s3 key. If provided, the key policy of the provided key must permit the IAM role used by AWS Config. See https://docs.aws.amazon.com/sns/latest/dg/sns-key-management.html. Note that the key should be in the same region as the global recorder region (where the S3 bucket will be created).

null
s3_mfa_deletebooloptional

Enable MFA delete for either 'Change the versioning state of your bucket' or 'Permanently delete an object version'. This setting only applies to the bucket used to storage AWS Config data. This cannot be used to toggle this setting but is available to allow managed buckets to reflect the state in AWS. For instructions on how to enable MFA Delete, check out the README from the private-s3-bucket module. CIS v1.4 requires this variable to be true. If you do not wish to be CIS-compliant, you can set it to false.

false
s3_object_prefixstringoptional

A prefix to use when storing Config objects in S3. This will be the beginning of the path in the S3 object. For example: <s3 bucket name>:/<prefix>/AWSLogs/<account ID>/Config/. If this variable is null (the default), the path will not include any prefix: e.g., it'll be <s3 bucket name>:/AWSLogs/<account ID>/Config/.

null

Set this to true to create an S3 bucket in the same region where the global recorder is configured. For multi-account deployments, set this to true for the central account that should host the S3 bucket and SNS topics, and false for all other accounts.

true

If true, create an SNS topic for Config notifications.

true
sns_topic_kms_key_region_mapmap(string)optional

Optional KMS key to use for each region for configuring default encryption for the SNS topic (encoded as a map from region - e.g. us-east-1 - to ARN of KMS key). If null or the region key is missing, encryption will not be configured for the SNS topic in that region.

null
sns_topic_namestringoptional

The name of the SNS topic to use for Config notifications.

"ConfigTopic"
tagsmap(string)optional

A map of tags to apply to the S3 Bucket. The key is the tag name and the value is the tag value.

{}

When true, all IAM policies will be managed as dedicated policies rather than inline policies attached to the IAM roles. Dedicated managed policies are friendlier to automated policy checkers, which may scan a single resource for findings. As such, it is important to avoid inline policies when targeting compliance with various security standards.

true