/terraform-aws-s3

Standard S3 module that enforces KMS encryption. Use principal based policies to access this bucket if possible.

Primary LanguageHCLApache License 2.0Apache-2.0

Terraform AWS [S3]

Standard S3 module that enforces KMS encryption. Use principal based policies to access this bucket if possible.

Basically there are two workflows:

  • Bucket is non-public: var.name and var.kms_key_arn are provided.
  • Bucket is public: var.name and var.kms_key_arn are provided and var.use_sse-s3_encryption_instead_of_sse-kms is true along with var.public_read_access is also true.

Use var.additional_tags for any tagging purposes like backups.

You can externally attach resources such as aws_s3_bucket_cors_configuration & aws_s3_bucket_lifecycle_configuration as wrapping them only duplicates work and they cannot be generally applied.

Setting any other parameter other than the flows above is generally against best practices. Best practices involve:

  • Always enable versioning.
  • Always enable KMS encryption. We use CMK when possible or SSE-S3 if not.
  • Disable ACLs completely.
  • Enable full bucket protection (public access block).

This module also creates an SSM parameter called "/s3/${var.name}/id" to allow e.g. CICD systems to fetch the bucket name since bucket names are globally unique and we use the Terraform autogenerated prefix to do this. This makes the bucket name non-predictable but the SSM parameter solves this.

How does it work

Basic flows are explained above. More complex flows are wrapped in our other modules that stem from AWS requirements and limitations. They involve more complex scenarios that are not explained here but are required from other module purposes.

See [./example] for examples on the replication setups.

Providers

Name Version
aws >=4.8.0

Modules

Name Source Version
replication_source ./replication_source n/a
replication_target ./replication_target n/a

Resources

Name Type
aws_s3_bucket.this resource
aws_s3_bucket_lifecycle_configuration.this resource
aws_s3_bucket_ownership_controls.this resource
aws_s3_bucket_policy.this resource
aws_s3_bucket_public_access_block.this resource
aws_s3_bucket_server_side_encryption_configuration.this resource
aws_s3_bucket_versioning.this resource
aws_ssm_parameter.this resource
aws_caller_identity.current data source
aws_iam_policy_document.deny_obsolete_tls data source
aws_iam_policy_document.deny_unencrypted_kms data source
aws_iam_policy_document.deny_unencrypted_objectaccess data source
aws_iam_policy_document.deny_unencrypted_sse data source
aws_iam_policy_document.dummy_policy data source
aws_iam_policy_document.public_read_access data source
aws_iam_policy_document.this data source
aws_partition.current data source

Inputs

Name Description Type Default Required
additional_tags Additional tags to be added to resources. map(string) {} no
bucket_policy_addition Optional TF Object that converts to policy JSON with jsonencode() to append to current bucket policy which forbids non-encrypted uploads by default. Set an <bucket> resource attribute to have it replaced by this module for you. any null no
disable_encryption_enforcement Internal use only. Buckets get a standard policy that prevents un-encrypted uploads or encryption schemes that are not the default encryption. Some services cannot work (Athena CUR) with this policy enabled. bool false no
enable_acl Internal use only. Enable ACL which is disabled by default. This is required in order to use the bucket for CloudFront S3 logging. bool false no
enable_public_read_access Enable public read access. bool false no
kms_key_arn KMS key to use for encrypting S3 bucket. string n/a yes
lifecycle_configuration Object Lifecycle rules configuration.
map(object({
status = string
bucket_prefix = string
transition = object({
storage_class = string
transition_days = number
})
expiration_days = number
noncurrent_version_expiration = object({
newer_noncurrent_versions = number
noncurrent_days = number
})
noncurrent_version_transition = object({
newer_noncurrent_versions = number
noncurrent_days = number
storage_class = string
})
}))
{} no
name Prefix name for S3 bucket. string n/a yes
source_replication_configuration Replication configuration using this bucket as source. The key of the map is used for naming. Use output.replication_target_bucket_arguments from any source buckets you want to replicate to in order to fill this argument if available.
map(object({
destination_bucket_arn = string
destination_aws_account = string
destination_kms_key_arn = string
}))
{} no
target_replication_configuration Replication configuration using this bucket as target. The key of the map is used for naming. Use output.replication_source_bucket_arguments from any source buckets you want to replicate to in order to fill this argument if available.
map(object({
source_role_arn = string
}))
{} no
use_fixed_name Dont generate suffix after var.name to support already created S3 buckets. Not recommended to use this as this makes the S3 module non-portable. bool false no
use_sse-s3_encryption_instead_of_sse-kms Internal use only unless var.enable_public_read_access is true. Enforce SSE-S3 encryption instead of SSE-KMS. This is required if external services only support SSE-S3. This is also a requirement for public buckets. bool false no

Outputs

Name Description
kms_key_arn n/a
replication_source_bucket_arguments n/a
replication_target_bucket_arguments n/a
s3_arn n/a
s3_bucket_name n/a
s3_name_parameter_arn n/a
website_regional_domain regional is better than global since global has redirects and is being deprecated