The terraform-aws-s3-bucket module from Cloud Posse represents a consolidated Terraform building block for Amazon S3 bucket creation that bundles versioning, lifecycle management, object locks, replication, encryption, ACL handling, bucket policies, and static website hosting into a single reusable interface. The module is positioned as an enterprise grade provisioning component with explicit attention to security defaults, drift prevention, and compatibility across provider versions. The documentation and release history show continuous adaptation to AWS API changes, including the introduction of regional namespaces and encryption configuration drift fixes. The module interacts with a defined set of child modules such as cloudposse/iam-s3-user/aws and cloudposse/label/null, and it declares a broad resource surface covering bucket core configuration, ownership controls, public access blocking, server side encryption, intelligent tiering, CORS, logging, notifications, replication, website configuration, and directory bucket support. The module also surfaces a predictable set of outputs for bucket ARN, domain name, ID, region, and regional domain name, and it documents requirements for Terraform, AWS provider, and utility providers. The design reflects a deliberate trade off between backward compatibility, where ACL private and ObjectWriter ownership are defaults, and forward guidance toward BucketOwnerEnforced ownership which automatically disables ACLs. Public access is blocked by default with configurable overrides via blockpublicacls, blockpublicpolicy, ignorepublicacls, and restrictpublicbuckets. Optional IAM user creation is supported with an explicit security warning about unencrypted Terraform state storage of access keys and the recommendation to use SSM Parameter Store for secret handling.
Module Identity and Release Chronology
The module is identified as terraform-aws-s3-bucket and is distributed under the Cloud Posse GitHub organization.
The release list documented in the reference material includes v4.14.0 and v4.13.0 and v4.12.0.
v4.14.0 introduced the bucketnamespace argument. The change was authored by Quentin BERTRAND and tracked as #291. The rationale provided is that AWS added regional namespaces for bucket. References cited include the HashiCorp AWS provider documentation for s3bucket with bucketnamespace and the AWS blog introducing account regional namespaces for Amazon S3 general purpose buckets. The impact of this addition is that operators can now explicitly set a regional namespace for bucket names, which affects bucket naming constraints and availability in regions where AWS enforces regional namespaces. The contextual connection is that the module must pass this argument through to the awss3_bucket resource, preserving compatibility with provider versions that support the field.
v4.12.0 is documented as a bug fix release. The change adds blockedencryptiontypes variable to fix perpetual SSE config drift. The work was performed by Chris Hilton and tracked as #289. The what section states that a new blockedencryptiontypes variable of type list(string) with default null is added to the module, wired into the rule block of awss3bucketserversideencryptionconfiguration, and documented in variables.tf and the inputs table in README.md. The why section explains that on hashicorp/aws provider >= 6.22.0, GetBucketEncryption returns blockedencryptiontypes = ["NONE"] by default. The module's encryption rule omits the field, which the provider treats as an empty list, causing perpetual diff. The real world consequence is that without this variable, Terraform plans will perpetually show changes for encryption configuration, leading to noisy CI pipelines and failed drift detection. The fix aligns module state with provider behavior and prevents unnecessary updates.
Provider and Terraform Requirements
The module declares requirements for Terraform and providers.
Terraform version requirement is >= 1.8.0.
AWS provider version requirement is documented in two contexts. One context shows aws version >= 4.0, < 6.0.0. Another context shows aws version >= 6.37.0. The utils provider version is >= 2.0.0, < 3.0.0.
The time provider is referenced with version >= 0.7.
The module composition includes child modules with pinned versions.
Modules table from the library documentation shows:
- s3_user version 1.2.0 source cloudposse/iam-s3-user/aws description n/a
- this version 0.25.0 source cloudposse/label/null description n/a
The component library documentation shows a different module graph:
- account_map version 2.0.0 source cloudposse/stack-config/yaml//modules/remote-state description n/a
- bucket_policy version 2.0.2 source cloudposse/iam-policy/aws description n/a
- iam_roles version latest source ../account-map/modules/iam-roles description n/a
- s3_bucket version 4.11.0 source cloudposse/s3-bucket/aws description n/a
- this version 0.25.0 source cloudposse/label/null description n/a
The impact of these version constraints is that consumers must align their Terraform and provider versions with the module's expectations, otherwise the module may fail to plan or may produce errors due to missing arguments. The contextual layer is that the module evolves in parallel with AWS provider changes, as seen with bucketnamespace and blockedencryption_types, requiring coordinated upgrades of the module and provider.
Resource Inventory and Configuration Surface
The module manages a comprehensive set of AWS resources.
Resources used by this module include:
- awsiampolicy.replication
- awsiamrole.replication
- awsiamrolepolicyattachment.replication
- awss3bucket.default
- awss3bucketaccelerateconfiguration.default
- awss3bucket_acl.default
- awss3bucketcorsconfiguration.default
- awss3bucketintelligenttiering_configuration.default
- awss3bucketlifecycleconfiguration.default
- awss3bucket_logging.default
- awss3bucketnotification.bucketnotification
- awss3bucketobjectlock_configuration.default
- awss3bucketownershipcontrols.default
- awss3bucket_policy.default
- awss3bucketpublicaccess_block.default
- awss3bucketreplicationconfiguration.default
- awss3bucketrequestpayment_configuration.default
- awss3bucketserversideencryptionconfiguration.default
- awss3bucket_versioning.default
- awss3bucketwebsiteconfiguration.default
- awss3bucketwebsiteconfiguration.redirect
- awss3directory_bucket.default
- timesleep.waitforawss3bucketsettings
The presence of awsiampolicy.replication, awsiamrole.replication, and awsiamrolepolicyattachment.replication indicates that cross account or cross region replication is supported with dedicated IAM principals. The real world consequence is that replication can be enabled without manual IAM creation, reducing configuration errors.
The inclusion of awss3bucketownershipcontrols.default and awss3bucket_acl.default reflects the module's handling of object ownership transitions. The module defaults to ObjectWriter for backward compatibility and recommends BucketOwnerEnforced moving forward. The impact is that teams migrating to BucketOwnerEnforced will need to remove ACL dependencies and may need a migration window.
The resource awss3bucketpublicaccessblock.default enforces default deny of public access. The configuration surface allows overrides via blockpublicacls, blockpublicpolicy, ignorepublicacls, and restrictpublic_buckets.
The resource timesleep.waitforawss3bucketsettings is used to introduce a delay to allow AWS eventual consistency to settle after bucket creation before applying dependent settings. The impact is reduced race conditions during initial provisioning.
Outputs and Data Sources
The module exposes outputs that surface key identifiers for downstream consumption.
Outputs documented include:
- bucket_arn
- Bucket ARN
- bucketdomainname
- Bucket domain name
- bucket_id
- Bucket ID
- bucket_region
- Bucket region
- bucketregionaldomain_name
- Bucket region-specific domain name
These outputs enable referencing the bucket in other modules without hardcoding names. The impact is improved composability.
The module also references data sources. The documentation states the following data sources are used by this module, though the specific list is truncated in the reference material. The component documentation lists dependencies and data sources are used, reinforcing the pattern of remote state lookups via account_map.
Security Posture and Public Access Controls
The module blocks public access to the bucket by default. The settings blockpublicacls, blockpublicpolicy, ignorepublicacls, and restrictpublicbuckets can be changed to alter the defaults. See AWS documentation for more details.
The impact of default blocking is that accidental public exposure is prevented for new buckets. The contextual connection is that the module also supports website hosting via awss3bucketwebsiteconfiguration, which inherently requires careful public access configuration. Operators must explicitly relax public access blocks to serve static websites.
The module can optionally create an IAM User with access to the S3 bucket. This is inherently insecure in that to enable anyone to become the User, access keys must be generated, and anything generated by Terraform is stored unencrypted in the Terraform state.
The reference material recommends using SSM Parameter Store is recommended because that will keep the secret from being easily accessible via Terraform remote state lookup, but the key will still be stored unencrypted in the Terraform state in any case.
The real world consequence is that IAM user creation via Terraform introduces secret material in state. Teams must evaluate state encryption and access controls, or avoid user creation in favor of IAM roles.
Object Ownership and ACL Transition
For backward compatibility, it sets the S3 bucket ACL to private and the s3objectownership to ObjectWriter. Moving forward, setting s3objectownership to BucketOwnerEnforced is recommended, and doing so automatically disables the ACL.
The usage example demonstrates this:
```
module "s3_bucket" {
source = "cloudposse/s3-bucket/aws"
Cloud Posse recommends pinning every module to a specific version
version = "x.x.x"
name = "app"
stage = "test"
namespace = "eg"
s3objectownership = "BucketOwnerEnforced"
enabled = true
userenabled = false
versioningenabled = false
privilegedprincipalactions = ["s3:GetObject", "s3:ListBucket", "s3:GetBucketLocation"]
privilegedprincipalarns = [
{
(local.deploymentiamrolearn) = [""]
},
{
(local.additionaldeploymentiamrole_arn) = ["prefix1/", "prefix2/"]
}
]
}
```
The impact of BucketOwnerEnforced is simplified permission management and avoidance of ACL related issues. The transition from ObjectWriter requires removal of ACL configurations and may require data migration considerations.
Lifecycle Configuration Patterns
The module supports S3 storage lifecycle configuration.
An example locals block is provided:
locals {
lifecycle_configuration_rules = [{
enabled = true # bool
id = "v2rule"
abort_incomplete_multipart_upload_days = 1 # number
filter_and = null
expiration = {
days = 120 # integer > 0
}
noncurrent_version_expiration = {
newer_noncurrent_versions = 3 # integer > 0
noncurrent_days = 60 # integer >= 0
}
transition = [{
days = 30 # integer >= 0
storage_class = "STANDARD_IA" # string/enum, one of GLACIER, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, DEEP_ARCHIVE, GLACIER_IR.
},
{
days = 60 # integer >= 0
storage_class = "ONEZONE_IA" # string/enum, one of GLACIER, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, DEEP_ARCHIVE,
The impact of lifecycle rules is cost optimization through automatic transition to cheaper storage classes and expiration of old versions. The abortincompletemultipartuploaddays setting prevents orphaned multipart uploads from accumulating storage charges. The noncurrentversionexpiration configuration manages versioned object retention.
The contextual connection is that lifecycle configuration interacts with versioning_enabled and object lock settings. Disabling versioning while having noncurrent version expiration rules would be ineffective.
Encryption and Drift Mitigation
The module creates awss3bucketserversideencryptionconfiguration.default. The v4.12.0 fix for blockedencryptiontypes variable ensures the rule block matches provider defaults and prevents perpetual diff.
The module also supports object lock configuration via awss3bucketobjectlock_configuration.default, which enables compliance mode or governance mode retention.
The real world consequence is that encryption is enforced at bucket creation, reducing compliance risk. Drift mitigation ensures stable Terraform plans.
Replication and Cross Region Features
Replication is supported via awss3bucketreplicationconfiguration.default along with IAM policy and role resources. The module can configure replication for versioned buckets with appropriate IAM permissions.
The impact is that data durability and low latency access across regions can be achieved declaratively. The contextual layer is that replication requires versioning enabled and proper KMS permissions when SSE-KMS is used.
Website Hosting and Static Site Support
The module includes awss3bucketwebsiteconfiguration.default and awss3bucketwebsiteconfiguration.redirect resources. This allows static website hosting with index and error documents, and redirects.
The impact is that the same module can provision both data buckets and static web buckets, reducing module sprawl. The trade off is that website hosting requires public access considerations which conflict with default public access blocks.
Integration Patterns
The component documentation shows the module is used as a dependency within larger stacks. The s3_bucket module version 4.11.0 is referenced as a dependency with cloudposse/s3-bucket/aws.
The module this version 0.25.0 from cloudposse/label/null provides naming conventions via name, stage, namespace parameters.
The bucket_policy module version 2.0.2 from cloudposse/iam-policy/aws is used to generate bucket policies.
The account_map module version 2.0.0 from cloudposse/stack-config/yaml//modules/remote-state provides remote state data.
The impact is that the s3 bucket module fits into a larger ecosystem of Cloud Posse components for IAM, labeling, and stack configuration.
Requirements and Compatibility Notes
Requirements documented:
- terraform version >= 1.8.0
- aws version >= 4.0, < 6.0.0
- utils version >= 2.0.0, < 3.0.0
Providers documented:
- aws version >= 4.0, < 6.0.0
The earlier library documentation shows aws version >= 6.37.0 and time version >= 0.7.
The discrepancy reflects different documentation snapshots and the module's evolution with provider versions. Operators must verify which provider range applies to the specific module version they pin.
Conclusion
The cloudposse terraform-aws-s3-bucket module delivers a dense, enterprise ready interface for Amazon S3 provisioning that balances backward compatibility with progressive security defaults. The resource surface covers bucket core attributes, acceleration, ACLs, CORS, intelligent tiering, lifecycle, logging, notifications, object lock, ownership controls, policies, public access blocking, replication, request payment, server side encryption, versioning, website configuration, directory buckets, and timing safeguards. Release history demonstrates active maintenance in response to AWS API changes, specifically regional namespaces and encryption configuration drift. Security defaults block public access and warn about IAM user state risks, while guiding users toward BucketOwnerEnforced ownership. Lifecycle examples illustrate cost management patterns with transitions and expiration. The module's integration with cloudposse labeling, IAM policy, and stack config components enables consistent naming and policy generation across environments. The documented outputs provide stable identifiers for downstream consumption. Effective use requires pinning to a specific version, aligning Terraform and provider versions, and understanding the interplay between public access blocks and website hosting. The module remains a central building block for teams requiring repeatable, compliant S3 infrastructure with minimal custom code.