Secure Access to S3 Buckets
Background
Some application-owned S3 buckets allowed direct public access when applications needed to expose objects publicly. To improve platform security, application-owned S3 buckets should no longer be publicly accessible unless there is a specific business need. Instead, publicly accessible content should be served through Amazon CloudFront while the S3 bucket itself remains private. CloudFront accesses the bucket using Origin Access Control (OAC), ensuring that only CloudFront can access objects in the bucket.
Architecture Diagram
flowchart LR
client@{ label: "Client" }
cloudfront@{ label: "CloudFront" }
s3@{ label: "Private S3 Bucket" }
blocked@{ label: "❌" , shape: circle}
client A@-.-> cloudfront
cloudfront B@-.->|OAC| s3
client C@-.- blocked
blocked D@-.-> s3
A@{ animation: fast }
B@{ animation: fast }
linkStyle 2 stroke:#D32F2F,stroke-width:2px;
linkStyle 3 stroke:#D32F2F,stroke-width:2px;
classDef client fill:#E8F5E9,stroke:#43A047,stroke-width:2px,color:#1B5E20;
classDef cloudfront fill:#E3F2FD,stroke:#1E88E5,stroke-width:2px,color:#0D47A1;
classDef s3 fill:#F3E5F5,stroke:#8E24AA,stroke-width:2px,color:#4A148C;
classDef blocked fill:none,stroke:none,color:#D32F2F;
class client client;
class cloudfront cloudfront;
class s3 s3;
class blocked blocked;
This approach removes the need for publicly accessible S3 buckets while still allowing applications to expose static content or other public resources through CloudFront.
For private content, authentication can also be added at the CloudFront layer using Lambda@Edge.
Configuring CloudFront for a Private S3 Bucket
To expose an existing private S3 bucket through CloudFront, define a distribution in the cloudfront_distributions section of the application module.
Example:
module "application" {
cloudfront_distributions = {
example = {
default_s3_origin_type = "private_storage"
default_s3_origin_bucket_name = <bucket_name>
default_s3_origin_bucket_arn = <bucket_arn>
default_s3_origin_domain = <bucket_regional_domain_name>
use_s3_bucket_regional_domain_name = true
}
}
}
Setting default_s3_origin_type = "private_storage" tells the CloudFront module to use an existing private S3 bucket as the origin.
When this option is configured, the module expects the bucket information (bucket_name, bucket_arn, and bucket_regional_domain_name) to be provided and does not create a new S3 bucket.
If default_s3_origin_type is omitted, the CloudFront module uses its default behavior and provisions a new S3 bucket. This is the same behavior used by the BYKS platform when deploying static websites backed by S3 and CloudFront.