AWS S3 Permissions: Locking down view to a domain

203 views Asked by At

I'm attempting to lock down viewing of S3 resources - really just images - to my web application's domain. For instance, if someone goes to my site - let's say example.com - and there's a src reference to the image, I want it to be viewable. But if someone were to right click and open up the image directly in a new tab, they shouldn't be able to.

There's tons on the web out there, but I just can't seem to find the correct combination or permissions. And most tutorials don't usually talk about the "Block Public Access" settings, and I'm not sure how that fits in.

Here's the policy I'm attempting:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Allow get requests originating from example.com",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::my-bucket",
            "Condition": {
                "StringLike": {
                    "aws:Referer": [
                        "https://www.example.com/*"
                    ]
                }
            }
        },
        {
            "Sid": "Do not allow requests from anywhere else.",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::my-bucket",
            "Condition": {
                "StringNotLike": {
                    "aws:Referer": [
                        "https://www.example.com/*"
                    ]
                }
            }
        }
    ]
}

This doesn't seem to do anything. If "block public access" is on, both are blocked. If it's off, both are shown. That is, even though I have an explicit "Deny" list above, going right to the image on that bucket in the browser works fine.

I can also edit CORS, but I'd still then wonder why the deny list here wouldn't take care of that itself. Finally, after implementing the policy, I lose lots of abilities myself, such as setting CORS, even when using the root user account. I can probably just do things in a different order to make it happen, but I'd like to still be able to manage my permissions after submitting the policy.

enter image description here

Thanks.

1

There are 1 answers

5
Rakeshkumar Taninki On BEST ANSWER

Step 1: Block all public access should be disabled to apply the bucket policy settings, You can make your block all public settings as shown in the above image.

S3 access block settings

Step 2: Organize all your website images in to one folder like “images”

Step 3: Setup a bucket policy as below. It has two statements. Statement 1 denies images folder to all except from your domain. Statement 2 allows everything. Since deny overwrites allow, statement 1 has more power than statement 2 hence it blocks images which calling from outside of your domain.

{ 
"Version": "2012-10-17", 
"Id": "http referer policy example", 
"Statement": [ 
    { 
        "Sid": "Deny get requests not originating from www.example.com and example.com.", 
        "Effect": "Deny", 
        "Principal": "*", 
        "Action": "s3:Get*", 
        "Resource": "arn:aws:s3:::your-bucket/images/*", 
        "Condition": { 
            "StringNotLike": { 
                "aws:Referer": [ 
                    "http://www.example.com/*", 
                    "http://www.example.com/" 
                ] 
            } 
        } 
    }, 
    {
        "Sid": "Allow get requests", 
        "Effect": "Allow", 
        "Principal": "*", 
        "Action": "s3:Get*", 
        "Resource": "arn:aws:s3:::your-bucket/*" 
    } 
] }

Step 4: You have to change your front end code a little bit, wherever you are using image tags you need to add “referrerpolicy” set to “origin”, if you don’t set this field referer header won’t be forwarded to S3 and rule evaluation failed and 403 will occur.

Example: <img src="images/pic_trulli.jpg" alt="Trulli" width="500" height="333" referrerpolicy="origin">

This solution is tested and working. If you also need CORS, you can enable CORS on S3 bucket as well. But this policy is good enough to handle.

When calling with domain -->

enter image description here

When calling with S3 URL -->

enter image description here

If this solution helps you, mark it as answered.