Overview
S3Bucket extends the CDK Bucket with Fjall’s secure defaults: SSL enforcement, Block Public Access asserted on every deploy, automatic multipart-upload cleanup, and versioning driven by the application’s backup tier. One class covers private storage, static website hosting, and public read access.
Resource Class
Basic Usage
Standard Private Bucket
Website Hosting Bucket
websiteHosting requires appName. The website exports are keyed on the pair (app, bucket), so two applications with identically named buckets stay deployable side by side.
Public Read Bucket
Default Behaviour
Removal policy
The default is environment-aware, not fixed:productionresolves toRETAIN. The bucket survives stack deletion.staging,development,platform,compliance,rootresolve toDESTROY. The bucket is tagged for the deploy-time pre-empty pass, which empties it SDK-side before CloudFormation deletes it.- An unrecognised
ENVIRONMENTvalue fails at synth rather than defaulting toDESTROY. A barecdk synthwith no environment signal falls back toDESTROY, because a template you only inspect deploys nothing.
removalPolicy explicitly to override the default in either direction.
Configuration Options
Core Properties
All standard CDK
BucketProps are also supported. enforceSSL and autoDeleteObjects are the two exceptions: both are fixed by the construct.
StorageFactory.build() and CdnFactory fill appName and appBackupTier from the App automatically. Only direct new S3Bucket(...) or new Storage(...) construction needs to pass them.WebsiteHostingConfig
ResourcePolicyStatement
Service and Federated principals are not modelled. The TLS-only
enforceSSL deny is applied separately and must not be listed here.
Use Cases
Private Application Storage
The default configuration creates a private bucket with SSL enforcement andBLOCK_ALL public access.
Static Website Hosting
SetwebsiteHosting to serve the bucket as an S3 website. This turns on public read access and opens the bucket-policy halves of Block Public Access.
WebsiteEndpoint and WebsiteHostedZoneId, both qualified by appName and the bucket name. Domain alias targets import that pair to point DNS at the website endpoint.
Public Asset Delivery
SetpublicReadAccess: true for a publicly readable bucket.
blockPublicPolicy and restrictPublicBuckets). The ACL halves, blockPublicAcls and ignorePublicAcls, stay true, because access here is bucket-policy-based and ACLs are disabled on modern buckets.
Versioning Follows the Backup Tier
Versioning resolves from the bucket’s effective backup tier: the per-bucketbackupVaultTier if set, otherwise the application’s backup.tier from App.getApp. Tiers resilient and enterprise turn versioning on. An explicit versioned wins over the tier in either direction. Buckets built through StorageFactory, the StaticSite site bucket, and the Buildkite artefact bucket inherit the application tier automatically.
lifecycleRules, the construct pairs it with a 30-day noncurrent-version expiry.
A bucket in a backup plan publishes its object events
AWS Backup does not watch an S3 bucket to build its continuous backup. It subscribes to the bucket’s object events on the default EventBridge bus and replays them to keep the point-in-time window moving. The bucket-level setting that publishes those events is off unless something turns it on. So a bucket that is versioned, carries a backup tier and claims no exemption — the same three conditions that put it in the plan — haseventBridgeEnabled
turned on for it. Reading one condition for both means a bucket cannot be
selected into a plan whose events it does not publish.
An explicit eventBridgeEnabled: false still wins: turning it off chooses
snapshots over a point-in-time window, and the tier tag the plan selects on is
untouched, so the bucket stays enrolled. Turning it on costs a
Custom::S3BucketNotifications resource per bucket and one shared notification
handler Lambda per stack, which is how CDK writes a bucket’s notification
configuration.
Buckets unversioned by design
Some buckets hold contents that are rebuilt or expired rather than kept, and versioning them would only keep a billed copy of everything they discard: a build-output bucket, an ISR cache, a database’s cold tier, the stack’s shared access-log bucket. A construct that leaves such a bucket unversioned says so withversioningExemption, and the bucket carries the fjall:s3:versioning-exempt tag valued with that reason.
Tags outlive the stack, so a posture scan can tell a bucket left unversioned on purpose from one that was forgotten. The tag is stamped only while the bucket’s resolved versioned is false: turn versioning on and the marker goes with it.
The Payload pattern, the ClickHouse cold tier and the stack’s access-log bucket set it for you.
Advanced Configuration
Encryption
KMS-encrypted buckets getbucketKeyEnabled: true automatically, which cuts KMS request cost. Pass bucketKeyEnabled: false to opt out.
Lifecycle Rules
AbortIncompleteMultipartUploads rule is added on top of these. Do not restate it.
Event Notifications
Access Control
Declarative Bucket Policy
resourcePolicyStatements keeps the policy in the props. The shape mirrors the generator’s S3ResourcePlanSchema.resourcePolicyStatements, so a bucket edited by the codemod engine and one written by hand look the same.
Imperative Bucket Policy
IAM Permissions
CORS Configuration
Monitoring
Access Logging
Complete Example
Best Practices
- Set
appNameon any bucket withwebsiteHosting, or synth fails. - Set
removalPolicyexplicitly when a non-production bucket holds data you want to keep. - Carry
noncurrentVersionExpirationin every custom rule set on a versioned bucket. - Use encryption for sensitive data, and leave
bucketKeyEnabledat its default to keep KMS cost down. - Configure lifecycle transitions to move cold objects to cheaper storage classes.
- Enable access logging for security audits.
- Use least-privilege IAM grants over broad bucket policies.
- Use
websiteHostingandpublicReadAccessrather than editing Block Public Access or bucket policies by hand.
Next Steps
ECR Repository
Store container images alongside object storage
Lambda Function
Process objects on upload with event notifications
IAM Role
Grant least-privilege access to bucket objects
Storage Factory
Create buckets with the StorageFactory pattern