AWS CloudFront S3 origina with OAC and OAI.
As per the current documentation, OAC authenticated requests supports:
- All Amazon S3 buckets in all AWS Regions, including opt-in Regions launched after December 2022
- Amazon S3 server-side encryption with AWS KMS (SSE-KMS)
- Dynamic requests (PUT and DELETE) to Amazon S3
First, create a key pair for the CloudFront signed URL stuff (ref1, ref2):
mkdir keys
openssl genrsa -des3 -out keys/private.pem 2048
openssl rsa -in keys/private.pem -outform PEM -pubout -out keys/public.pem
Create the .auto.tfvars
file from the sample:
The ACM certificate verification will be required
cloudfront_price_class = "PriceClass_100"
certificate_domain = "cf.example.com"
cloudfront_minimum_protocol_version = "TLSv1.2_2021"
To create the infrastructure:
terraform init
terraform apply -auto-approve
As described in the S3 origin documentation, S3 regional domains should be used:
# Use the regional bucket domain
<bucket-name>.s3.<region>.amazonaws.com
For server-side encryption (SSE) The implementation enabled aws:kms
(SSE-KMS) encryption for OAC, and AES256
(SSE-S3)for OAI.
To test the distribution access the endpoints on paths /oac
and /oai
respectively.
Policy implementation between the two authentication methods differ:
Policy | OAC | OAI |
---|---|---|
Principal | cloudfront.amazonaws.com |
OAI identity id |
Condition | AWS:SourceArn with the distribution ARN |
n/a |
There are two types of share with URLs:
You can generate a presigned URL which will use the credentials of the user who generated the URLs. This would be useful for users who do not have access to the account with AWS credentials ("anonymous").
Generate a presigned URL, open an anonymous browser session and use the link to access the object:
# For regions launched prior to 2019
aws s3 presign s3://bucket-presignedurl-vouchers010203/vouchers/voucher.txt --expires-in 604800
Signed URLs are more secure and offer additional controls with canned policies but specially with custom policies.
Edit the policy.json
file accordingly, and generate the signature:
cat policy | tr -d "\n" | tr -d " \t\n\r" | openssl sha1 -sign keys/private.pem | openssl base64 -A | tr -- '+=/' '-_~'
The signed URL will look like this:
https://ddddddd00001111.cloudfront.net/vouchers/voucher.txt?Expires=1698637841&Signature=<SIGNATURE>&Key-Pair-Id=KQPALV128937
Setting a custom certificate on ACM for CloudFront allows you to select the Ciphers list.
For details, check Supported protocols and ciphers between viewers and CloudFront.
The following S3 bucket policy enforces TLS by denying insecure transport via "aws:SecureTransport" : "false"
:
"Statement" : [
{
"Sid" : "EnforceTLS",
"Action" : "s3:*",
"Effect" : "Deny",
"Resource" : [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET",
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
],
"Condition" : {
"Bool" : {
"aws:SecureTransport" : "false"
}
}
}
]
Destroy the resources when you're done using it:
terraform destroy -auto-approve