terraform-aws-s3-private-bucket icon indicating copy to clipboard operation
terraform-aws-s3-private-bucket copied to clipboard

Creates a private, encrypted, versioned S3 bucket with good defaults.

Creates a private S3 bucket with good defaults:

  • Private only objects
  • Encryption
  • Versioning
  • Access logging
  • Storage analytics

The following policy rules are set:

  • Deny uploading public objects.
  • Deny updating policy to allow public objects.

The following ACL rules are set:

  • Retroactively remove public access granted through public ACLs
  • Deny updating ACL to public

The following lifecycle rules are set:

  • Incomplete multipart uploads are deleted after 14 days.
  • Expired object delete markers are deleted.
  • Noncurrent object versions transition to the Standard - Infrequent Access storage class after 30 days.
  • Noncurrent object versions expire after 365 days.

Terraform Versions

Terraform 0.13 and newer. Pin module version to ~> 3.X. Submit pull-requests to master branch.

Terraform 0.12. Pin module version to ~> 2.X. Submit pull-requests to terraform012 branch.

Usage

module "aws-s3-bucket" {
  source         = "trussworks/s3-private-bucket/aws"
  bucket         = "my-bucket-name"
  logging_bucket = "my-aws-logs"

  tags = {
    Name        = "My bucket"
    Environment = "Dev"
  }
}

Requirements

Name Version
terraform >= 0.13.0
aws >= 3.75.0

Providers

Name Version
aws >= 3.75.0

Modules

No modules.

Resources

Name Type
aws_s3_bucket.private_bucket resource
aws_s3_bucket_acl.private_bucket resource
aws_s3_bucket_analytics_configuration.private_analytics_config resource
aws_s3_bucket_cors_configuration.private_bucket resource
aws_s3_bucket_inventory.inventory resource
aws_s3_bucket_lifecycle_configuration.private_bucket resource
aws_s3_bucket_logging.private_bucket resource
aws_s3_bucket_policy.private_bucket resource
aws_s3_bucket_public_access_block.public_access_block resource
aws_s3_bucket_server_side_encryption_configuration.private_bucket resource
aws_s3_bucket_versioning.private_bucket resource
aws_caller_identity.current data source
aws_iam_account_alias.current data source
aws_iam_policy_document.supplemental_policy data source
aws_partition.current data source

Inputs

Name Description Type Default Required
abort_incomplete_multipart_upload_days Number of days until aborting incomplete multipart uploads number 14 no
bucket The name of the bucket. string n/a yes
bucket_key_enabled Whether or not to use Amazon S3 Bucket Keys for SSE-KMS. bool false no
cors_rules List of maps containing rules for Cross-Origin Resource Sharing. list(any) [] no
custom_bucket_policy JSON formatted bucket policy to attach to the bucket. string "" no
enable_analytics Enables storage class analytics on the bucket. bool true no
enable_bucket_force_destroy If set to true, Bucket will be emptied and destroyed when terraform destroy is run. bool false no
enable_bucket_inventory If set to true, Bucket Inventory will be enabled. bool false no
enable_s3_public_access_block Bool for toggling whether the s3 public access block resource should be enabled. bool true no
expiration expiration blocks list(any)
[
{
"expired_object_delete_marker": true
}
]
no
inventory_bucket_format The format for the inventory file. Default is ORC. Options are ORC or CSV. string "ORC" no
kms_master_key_id The AWS KMS master key ID used for the SSE-KMS encryption. string "" no
logging_bucket The S3 bucket to send S3 access logs. string "" no
noncurrent_version_expiration Number of days until non-current version of object expires number 365 no
noncurrent_version_transitions Non-current version transition blocks list(any)
[
{
"days": 30,
"storage_class": "STANDARD_IA"
}
]
no
schedule_frequency The S3 bucket inventory frequency. Defaults to Weekly. Options are 'Weekly' or 'Daily'. string "Weekly" no
sse_algorithm The server-side encryption algorithm to use. Valid values are AES256 and aws:kms string "AES256" no
tags A mapping of tags to assign to the bucket. map(string) {} no
transitions Current version transition blocks list(any) [] no
use_account_alias_prefix Whether to prefix the bucket name with the AWS account alias. string true no
use_random_suffix Whether to add a random suffix to the bucket name. bool false no
versioning_status A string that indicates the versioning status for the log bucket. string "Enabled" no

Outputs

Name Description
arn The ARN of the bucket. Will be of format arn:aws:s3:::bucketname.
bucket_domain_name The bucket domain name.
bucket_regional_domain_name The bucket region-specific domain name.
id The name of the bucket.
name The Name of the bucket. Will be of format bucketprefix-bucketname.

Upgrade Paths

Upgrading from 3.x.x to 4.x.x

Version 4.x.x enables the use of version 4 of the AWS provider. Terraform provided an upgrade path for this. To support the upgrade path, this module now includes the following additional resources:

  • aws_s3_bucket_policy.private_bucket
  • aws_s3_bucket_acl.private_bucket
  • aws_s3_bucket_versioning.private_bucket
  • aws_s3_bucket_lifecycle_configuration.private_bucket
  • aws_s3_bucket_logging.private_bucket
  • aws_s3_bucket_server_side_encryption_configuration.private_bucket
  • aws_s3_bucket_cors_configuration.private_bucket

This module version removes the enable_versioning variable (boolean) and replaces it with the versioning_status variable (string). There are three possible values for this variable: Enabled, Disabled, and Suspended. If at one point versioning was enabled on your bucket, but has since been turned off, you will need to set versioning_status to Suspended rather than Disabled.

Additionally, this version of the module requires a minimum AWS provider version of 3.75, so that you can remain on the 3.x AWS provider while still gaining the ability to utilize the new S3 resources introduced in the 4.x AWS provider.

There are two general approaches to performing this upgrade:

  1. Upgrade the module version and run terraform plan followed by terraform apply, which will create the new Terraform resources.
  2. Perform terraform import commands, which accomplishes the same thing without running terraform apply. This is the more cautious route.

If you choose to take the route of running terraform import, you will need to perform the following imports. Replace example with the name you're using when calling this module and replace your-bucket-name-here with the name of your bucket (as opposed to an S3 bucket ARN). Also note the inclusion of ,private when importing the new aws_s3_bucket_acl Terraform resource; if you are setting the s3_bucket_acl input variable, use that value instead of private. If you have not configured a target bucket using the logging_bucket input variable, then you don't need to import the aws_s3_bucket_logging Terraform resource.

terraform import module.example.aws_s3_bucket_policy.private_bucket your-bucket-name-here
terraform import module.example.aws_s3_bucket_acl.private_bucket your-bucket-name-here,private
terraform import module.example.aws_s3_bucket_versioning.private_bucket your-bucket-name-here
terraform import module.example.aws_s3_bucket_lifecycle_configuration.private_bucket your-bucket-name-here
terraform import module.example.aws_s3_bucket_server_side_encryption_configuration.private_bucket your-bucket-name-here
terraform import module.example.aws_s3_bucket_cors_configuration.private_bucket your-bucket-name-here
# Optionally run these two commands if you have configured the logging_bucket input variable.
terraform import module.example.aws_s3_bucket_logging.private_bucket your-bucket-name-here
terraform state mv 'module.example.aws_s3_bucket_logging.private_bucket' 'module.example.aws_s3_bucket_logging.private_bucket[0]'

After this, you will need to run a terraform plan and terraform apply to apply some non-functional changes to lifecycle rule IDs.

Developer Setup

Install dependencies (macOS)

brew install pre-commit go terraform terraform-docs

Testing

Terratest is being used for automated testing with this module. Tests in the test folder can be run locally by running the following command:

make test

Or with aws-vault:

AWS_VAULT_KEYCHAIN_NAME=<NAME> aws-vault exec <PROFILE> -- make test

CHANGELOG

This terraform module is undergoing an experiment where we keep a CHANGELOG for it. We're still trying to figure out how to automate this process and, for now, are manually running the command.

The changelog should be updated every time a new GitHub release is cut.

To do so, you should have a Github token with "repo" scope that can be loaded in as an environment variable. You can find more info here.

export CHANGELOG_GITHUB_TOKEN="«your-40-digit-github-token»"

The command to run on your terminal:

docker run --env CHANGELOG_GITHUB_TOKEN="$CHANGELOG_GITHUB_TOKEN" --rm -v "$(pwd)":/usr/local/src/your-app ferrarimarco/github-changelog-generator -u trussworks -p terraform-aws-s3-private-bucket