简体   繁体   中英

Restrict S3 Static Website access to Cloudfront

I understand this is a common question, but I was unsuccessful with their solutions.

I have two websites hosted on S3:

  • bucket.ca (Allows *.bucket.ca )
  • dev.bucket.ca (Allows dev.bucket.ca )

They are publicly accessible, but I do not want anyone to access their S3 url. So I edited the bucket policy with StringEquals .

One for each of the buckets:

arn:aws:s3:::bucket.ca/* arn:aws:s3:::dev.bucket.ca/*

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::dev.bucket.ca/*",
            "Condition": {
                "StringEquals": {
                    "aws:UserAgent": "random-hash"
                }
            }
        }
    ]
}

Here is the part that gets frustrating. Every time I make a change to Cloudfront or make a change to the bucket, the behavior is highly inconsistent.

dev.bucket.ca appears to be working as intended where its S3 url results in Access Denied, and I can access any of its child paths dev.bucket.ca/* . So I replicated this configuration for bucket.ca , but the result is always 403.

Checking back with dev.bucket.ca , I am no longer able to access it's child paths. dev.bucket.ca/404 results in 403.

Is there a reliable way to test S3 and Cloudfront configurations? Each time Cloudfront is edited, the changes are slow to update. Should I be wiping my browser cache and reopen an incognito mode each time to get a more reliable result?

To debug this issue, I reverted the policy to allow all public:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::dev.bucket.ca/*",
        }
    ]
}

This policy works fully for bucket.ca and dev.bucket.ca . So it looks like it's my conditional that is the issue.

"aws:UserAgent": "random-hash"

It turns out the custom header needed to be User-Agent and not UserAgent . So Cloudfront should use User-Agent for its custom header and S3 policy to use UserAgent .

I tested this after Cloudfront has been deployed, and both websites worked correctly. S3 buckets cannot be accessed either, which is great.


The working policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::dev.bucket.ca/*",
            "Condition": {
                "StringEquals": {
                    "aws:UserAgent": "RandomHash"
                }
            }
        }
    ]
}

With the following cloudfront setting:

Header Name: User-Agent

Value: MatchingRandomHash

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM