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.
Buckets unversioned by design
Some buckets churn by nature, and versioning them would keep a billed copy of every overwrite: a build-output bucket, an ISR cache, a database’s cold tier. 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 and the ClickHouse cold tier 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