Skip to main content
Security Modules 0.74.5Last updated in version 0.74.2

AWS Config

View Source Release Notes

This Terraform Module configures AWS Config, a service that allows you to assess, audit, and evaluate the configurations of your AWS resources. You can use AWS Config to ensure that AWS resources are configured in a manner that is in compliance with your company policies or regulatory requirements.

AWS Config ArchitectureAWS Config Architecture

Features

  • Record snapshots of how your AWS resources are configured.

  • Create an S3 bucket to store AWS Config logs from multiple AWS accounts and regions.

  • Create a delivery channel to send notifications to an existing SNS topic, which can be used to alert you when configurations change.

  • Aggregate the output of AWS Config in multiple accounts to a single pane of glass.

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.

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

  • test: Automated tests for the modules and examples.

Deploy

Non-production deployment (quick start for learning)

If you just want to try this repo out for experimenting and learning, check out the following resources:

  • examples/aws-config: The examples/aws-config folder contains sample code optimized for learning, experimenting, and testing (but not production usage).

Production deployment

If you want to deploy this repo in production, check out the following resources:

Manage

Day-to-day operations

Sample Usage

main.tf

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

module "aws_config" {

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

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

# 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

# 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

# Set to true to create config aggregator, typically in the global recorder
# region of the security/central account. The variable is needed due to
# Terraform limitations, creating the aggregator conditionally based on AWS
# region might fail as 'aws_region' datasource might be deferred if the module
# has 'depend_on' on other resources.
create_config_aggregator = false

# 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 in this module should be created or not.
create_resources = true

# The ID of the current AWS account. Normally, we can fetch this automatically
# using the aws_caller_identity data source, but due to Terraform limitations,
# in some rare situations, this data source returns the wrong ID, so this
# parameter needs to be passed manually. Most users can leave this value
# unset. See
# https://github.com/gruntwork-io/terraform-aws-security/pull/308#issuecomment-676561441
# for context.
current_account_id = null

# 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 AWS Config Configuration Aggregator on all regions
# regardless of what is passed into var.opt_in_regions.
enable_all_regions_for_config_aggregator = false

# 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

# 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 region in which to create the global recorder for configuration of
# global resources such as IAM users, groups, roles, and policies.
global_recorder_region = "us-east-1"

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

# Optional KMS key to use for encrypting S3 objects AND the SNS topic. 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 S3 buckets and var.sns_topic_kms_key_arn for SNS
# topics.
kms_key_arn = null

# For multi-account deployments, 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 var.should_create_s3_bucket and var.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. If null,
# never delete.
num_days_after_which_delete_log_data = 730

# Enables config aggregation in only the provided regions. If this list is
# empty, config aggregation will be enabled in all regions.
opt_in_regions = []

# Map of recording group configurations.
#
# See the official AWS provider documentation for futher context
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/config_configuration_recorder#recording_group-configuration-block
#
# Each configuration can have the following parameters:
#
# all_supported bool (required):
# Whether to records configuration changes for every supported type of regional resource.
#
# include_global_resource_types bool (required):
# Whether to records configuration changes for every supported type of global resource.
#
# resource_types list(string) (required):
# List of resource types to record configuration changes for.
# Requires that all_supported is false and a recording_strategy of "INCLUSION_BY_RESOURCE_TYPES"
#
# recording_strategy object({}) (required):
# use_only list(string):
# The recording stratgy to use which can be one of:
# - "ALL_SUPPORTED_RESOURCE_TYPES"
# - "EXCLUSION_BY_RESOURCE_TYPES"
# - "INCLUSION_BY_RESOURCE_TYPES"
#
# exclusion_by_resource_types object({}) (optional):
# resource_types list(string):
# A list of resource types to exclude from recording.
# Requires that all_supported is false and a recording_strategy of "EXCLUSION_BY_RESOURCE_TYPES"
#
recording_groups = {"default_group":{"all_supported":true,"include_global_resource_types":true,"recording_strategy":{"use_only":"ALL_SUPPORTED_RESOURCE_TYPES"},"resource_types":[]}}

# The mode for AWS Config to record configuration changes.
#
# recording_frequency:
# The frequency with which AWS Config records configuration changes (service defaults to CONTINUOUS).
# - CONTINUOUS
# - DAILY
#
# You can also override the recording frequency for specific resource types.
# recording_mode_override:
# description:
# A description for the override.
# recording_frequency:
# The frequency with which AWS Config records configuration changes for the specified resource types.
# - CONTINUOUS
# - DAILY
# resource_types:
# A list of resource types for which AWS Config records configuration changes. For example, AWS::EC2::Instance.
#
# See the following for more information:
# https://docs.aws.amazon.com/config/latest/developerguide/stop-start-recorder.html
#
# /*
# recording_mode = {
# recording_frequency = "DAILY"
# recording_mode_override = {
# description = "Override for specific resource types"
# recording_frequency = "CONTINUOUS"
# resource_types = ["AWS::EC2::Instance"]
# }
# }
# */
#
recording_mode = 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.
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

# If set to true, attach an IAM policy, to the AWS Config IAM role that allows
# the role to publish messages to the SNS topic defined by either
# `sns_topic_name` or `sns_topic_arn`. Set to false if an SNS topic is not
# used.
should_attach_sns_policy = true

# If set to true, create an IAM role for AWS Config. Customize the name of the
# role by setting iam_role_name. If set to false, the name passed in
# iam_role_name must already exist.
should_create_iam_role = true

# If set to true, create an S3 bucket for delivering Config objectts. Defaults
# to true.
should_create_s3_bucket = true

# The ARN of an existing SNS topic. Can be in the same account or another
# account. To create a new topic, set sns_topic_name. One of var.sns_topic_arn
# or var.sns_topic_name are required. This module does not support creating
# AWS Config without an SNS topic.
sns_topic_arn = null

# The ID of an AWS-managed(default) or customer-managed customer master key
# (CMK) to use for encrypting the Amazon SNS topic (var.sns_topic_name is
# non-null). Specify null explicitly to disable encryption of SNS topic.
sns_topic_kms_key_arn = "alias/aws/sns"

# If set, creates an SNS topic to which Config notifications will be
# delivered. To provide an existing topic, set sns_topic_arn. One of
# var.sns_topic_arn or var.sns_topic_name are required. One of
# var.sns_topic_arn or var.sns_topic_name are required. This module does not
# support creating AWS Config without an SNS topic.
sns_topic_name = null

# 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

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

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

Set to true to create config aggregator, typically in the global recorder region of the security/central account. The variable is needed due to Terraform limitations, creating the aggregator conditionally based on AWS region might fail as 'aws_region' datasource might be deferred if the module has 'depend_on' on other resources.

false
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 in this module should be created or not.

true
current_account_idstringoptional

The ID of the current AWS account. Normally, we can fetch this automatically using the aws_caller_identity data source, but due to Terraform limitations, in some rare situations, this data source returns the wrong ID, so this parameter needs to be passed manually. Most users can leave this value unset. See https://github.com/gruntwork-io/terraform-aws-security/pull/308#issuecomment-676561441 for context.

null

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 AWS Config Configuration Aggregator on all regions regardless of what is passed into opt_in_regions.

false

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

false
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 region in which to create the global recorder for configuration of global resources such as IAM users, groups, roles, and policies.

"us-east-1"
iam_role_namestringoptional

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

"AWS_ConfigRole"
kms_key_arnstringoptional

Optional KMS key to use for encrypting S3 objects AND the SNS topic. 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 S3 buckets and sns_topic_kms_key_arn for SNS topics.

null
linked_accountslist(string)optional

For multi-account deployments, 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. If null, never delete.

730
opt_in_regionslist(string)optional

Enables config aggregation in only the provided regions. If this list is empty, config aggregation will be enabled in all regions.

[]
recording_groupsmap(object(…))optional

Map of recording group configurations.

See the official AWS provider documentation for futher context https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/config_configuration_recorder#recording_group-configuration-block

Each configuration can have the following parameters:

all_supported bool (required): Whether to records configuration changes for every supported type of regional resource.

include_global_resource_types bool (required): Whether to records configuration changes for every supported type of global resource.

resource_types list(string) (required): List of resource types to record configuration changes for. Requires that all_supported is false and a recording_strategy of 'INCLUSION_BY_RESOURCE_TYPES'

recording_strategy object({}) (required): use_only list(string): The recording stratgy to use which can be one of:

  • 'ALL_SUPPORTED_RESOURCE_TYPES'
  • 'EXCLUSION_BY_RESOURCE_TYPES'
  • 'INCLUSION_BY_RESOURCE_TYPES'

exclusion_by_resource_types object({}) (optional): resource_types list(string): A list of resource types to exclude from recording. Requires that all_supported is false and a recording_strategy of 'EXCLUSION_BY_RESOURCE_TYPES'

map(object({
all_supported = bool
include_global_resource_types = bool
resource_types = list(string)
recording_strategy = object({
use_only = string
})
exclusion_by_resource_types = optional(object({
resource_types = list(string)
}))
}))
{
default_group = {
all_supported = true,
include_global_resource_types = true,
recording_strategy = {
use_only = "ALL_SUPPORTED_RESOURCE_TYPES"
},
resource_types = []
}
}
recording_modeobject(…)optional

The mode for AWS Config to record configuration changes.

recording_frequency: The frequency with which AWS Config records configuration changes (service defaults to CONTINUOUS).

  • CONTINUOUS
  • DAILY

You can also override the recording frequency for specific resource types. recording_mode_override: description: A description for the override. recording_frequency: The frequency with which AWS Config records configuration changes for the specified resource types.

  • CONTINUOUS
  • DAILY resource_types: A list of resource types for which AWS Config records configuration changes. For example, AWS::EC2::Instance.

See the following for more information: https://docs.aws.amazon.com/config/latest/developerguide/stop-start-recorder.html

recording_mode = &#123;
recording_frequency = 'DAILY'
recording_mode_override = &#123;
description = 'Override for specific resource types'
recording_frequency = 'CONTINUOUS'
resource_types = ['AWS::EC2::Instance']
&#125;
&#125;
object({
recording_frequency = string
recording_mode_override = optional(object({
description = string
recording_frequency = string
resource_types = list(string)
}))
})
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.

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

If set to true, attach an IAM policy, to the AWS Config IAM role that allows the role to publish messages to the SNS topic defined by either sns_topic_name or sns_topic_arn. Set to false if an SNS topic is not used.

true

If set to true, create an IAM role for AWS Config. Customize the name of the role by setting iam_role_name. If set to false, the name passed in iam_role_name must already exist.

true

If set to true, create an S3 bucket for delivering Config objectts. Defaults to true.

true
sns_topic_arnstringoptional

The ARN of an existing SNS topic. Can be in the same account or another account. To create a new topic, set sns_topic_name. One of sns_topic_arn or sns_topic_name are required. This module does not support creating AWS Config without an SNS topic.

null
sns_topic_kms_key_arnstringoptional

The ID of an AWS-managed(default) or customer-managed customer master key (CMK) to use for encrypting the Amazon SNS topic (sns_topic_name is non-null). Specify null explicitly to disable encryption of SNS topic.

"alias/aws/sns"
sns_topic_namestringoptional

If set, creates an SNS topic to which Config notifications will be delivered. To provide an existing topic, set sns_topic_arn. One of sns_topic_arn or sns_topic_name are required. One of sns_topic_arn or sns_topic_name are required. This module does not support creating AWS Config without an SNS topic.

null
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