S3 Policy Deny for all principals but - amazon-web-services

I am attempting to deny public users from accessing signedUrl paths directly, unless it's loaded by my website <img> tag.
Typical users should not allow to copy the image URL directly in the address bar and download the image.
The allow policy
{
"Sid": "Allow public with signedUrl",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-chat-attachments-development/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"http://localhost:4000/*",
"http://localhost:3000/*",
"https://mydomain1/*",
"https://mydomain2/*"
]
}
}
},
Below explicitly deny public access. Without the following policy, public users can still copy and paste image URL directly in the address bar (undesirable).
{
"Sid": "Statement to deny anybody without referrer",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::1234:user/S3UserfullAccess",
"arn:aws:iam::1234:role/LambdaFullAccess"
]
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-chat-attachments-development/*",
"Condition": {
"StringNotLike": {
"aws:Referer": [
"http://localhost:4000/*",
"http://localhost:3000/*",
"https://mydomain1/*",
"https://mydomain2/*"
]
}
}
}
Problem
I have the above policy settings, and it works well (public users are shown a access denied page). However, it also means my lambda, and my nodejs app servers cannot access the S3 even though I added NotPrincipal in the policy.
Please advise how can I correct my policy to achieve my desire behavior.
PS: I do note the above referer hack will not stop technical users from spoofing referring addresses.

Related

How to use referer condition in Amazon S3 bucket policy with CloudFront

Requirement:
We're using AWS CloudFront with S3 bucket for my client to save the tutorial/course videos, hence we would like to prevent the users to download any video with the links either S3 Object link or CloudFront domain url. In other words only with our website these will be readable / accessible or users can only be able to watch them. Therefore, we're trying to restrict the access through direct links.
Tried solution:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3PublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:GetObject",
"s3:GetObjectTagging",
"s3:PutObject",
"s3:PutObjectTagging"
],
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET",
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
],
"Condition": {
"StringLike": {
"aws:Referer": [
"https://dev.mycompany.com/",
"https://mycompany.com/"
]
}
}
},
{
"Sid": "CloudFrontPublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity AAAAAAAAAAA"
},
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET",
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
],
"Condition": {
"StringLike": {
"aws:Referer": [
"https://dev.mycompany.com/",
"https://mycompany.com/"
]
}
}
}
]
}
Problem:
The above policy is working fine with the S3 object urls, like If I open it through the link it is showing Access Denied and within my website the videos are playing fine.
However, the video links with CloudFront Domain, not accessible even within the website. We need the same behavior as with the S3 direct URLs.
Conclusion:
The aws:Referer condition is working fine with s3 object urls but not applying on the CloudFront url, hence making them unaccessible.
Hopefully, I'm able to state the problem as it is occurring.
Thanks in advance.
More Info:
Cloudfront Distribution Behavior Details:
Listing
Details of the second entry (Default)

How do I modify a Bucket Policy to allow Root Credentials/IAM user

Per the documentation at Restricting Access to a Specific HTTP Referrer , I've granted access to a given set of domains, and as instructed, denied access to any site except those domains.
This works all fine and well except when trying to do anything with the root credentials, or any IAM user.
It goes on to say:
This example prevents all users (including the root user) from
performing all Amazon S3 actions, including managing bucket policies.
Consider adding a third Sid that grants the root user s3:* actions.
If Sid#2 is removed, it works, but I see no way to negate that condition if it's the Root User or an IAM record.
The question is HOW to "add a third sid".
As is abundantly clear, I'm new at AWS permissions. I've tried any number of ways to specify this magical "3rd sid", but quite apparently am doing it incorrectly. I've tried many variations from the docs such as below with no luck or clear idea where/how to grant Root privileges in the policy.
{
"Sid": "Allow Root All Access",
"Effect": "Allow",
"Principal": {
"AWS":"arn:aws:iam::123456789012:root"
"AWS": "123456789012",
"CanonicalUser": "57bb2cb8as978f89sreuruapouduasp8udc5ba524fe20eb22853f19088600a67"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::our-bucket/*"
}
Policy implemented from example, and does work (too well)
{
"Version": "2012-10-17",
"Id": "http referer policy example",
"Statement": [
{
"Sid": "Allow get requests originating from Our Site.",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::our-bucket/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"http://www.oursite.com/*",
"https://www.oursite.com/*"
]
}
}
},
{
"Sid": "Explicit deny to ensure requests are allowed only from specific referer.",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::our-bucket/*",
"Condition": {
"StringNotLike": {
"aws:Referer": [
"*oursite.com/*"
]
}
}
}
]
}
Thanks in advance to anyone that can assist!
Instead of -
{
"Sid":"Allow Root All Access",
"Effect":"Allow",
"Principal":{
"AWS":"123456789012",
"CanonicalUser":"..."
},
"Action":"s3:*",
"Resource":"arn:aws:s3:::our-bucket/*"
}
Please try -
{
"Sid":"Allow Root All Access",
"Effect":"Allow",
"Principal":{
"AWS":"arn:aws:iam::123456789012:root"
},
"Action":"s3:*",
"Resource":"arn:aws:s3:::our-bucket/*"
}
I got this format from this link.

Amazon S3 bucket policy for referer condition on specific folder

I want to use condition of StringLike aws:Referer for a particular folder and make rest of the folder publicly accessible.
Here is my bucket policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AddPerm",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::bucketName/folderName/*"
]
},
{
"Sid": "",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketName/folderName/users/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"https://example.com/*"
]
}
}
}
]
}
When I am using above policy, it is not working with first one.
Try with below policy:
{
"Sid": "",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketName/folderName/users/*",
"Condition": {
"StringNotLike": {
"aws:Referer": [
"https://example.com/*"
]
}
}
}
The first part of your policy is granting GetObject access for anything in the folderName path of your bucket. This includes folderName/users/*.
Therefore, the second part of your policy is not being used (since the first policy is already granting access to the folderName/users/* path.
You could solve it by using different buckets, or you could convert the second policy into a Deny with StringNotLike (effectively saying that access is denied to folderName/users/* if the referer is not example.com.
Frankly, your policy looks strange because it is granting access to the entire users path hierarchy, which probably isn't what you'd want it to do. (I'm assuming you'd want to grant access only to a particular user's data based upon who is accessing your application.)
Please note that referer is not secure — it is easy to fake this value in a browser and in web-scraping softare.

AWS S3 Bucket policy public. How to make object private?

I've a bucket with GetObject available to everyone on full bucket(*). I want to make a few objects private(through Object level operation ACL), i.e. only the bucket owner should have read access to the object. I've gone through all available documentation, but couldn't find any possible way. Can anyone confirm is this possible or not?
You cannot use S3 Object ACLs because ACLs do not have a DENY.
You can modify your S3 policy to specify objects and deny access to individual items.
Example S3 Policy (notice that this policy forbids access to everyone for GetObject for two files):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/*"
},
{
"Sid": "DenyPublicReadGetObject",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::mybucket/block_this_file",
"arn:aws:s3:::mybucket/block_this_file_too"
]
}
]
}
If you want to add a condition so that certain users can still access the objects, add a condition after the Resource section like this. This condition will allow IAM users john.wayne and bob.hope to still call GetObject.
"Resource": [
"arn:aws:s3:::mybucket/block_this_file",
"arn:aws:s3:::mybucket/block_this_file_too"
],
"Condition": {
"StringNotEquals": {
"aws:username": [
"john.wayne",
"bob.hope"
]
}
}

S3 bucket policy: In a Public Bucket, make a sub-folder private

I have a bucket filled with contents that need to be mostly public. However, there is one folder (aka "prefix") that should only be accessible by an authenticated IAM user.
{
"Statement": [
{
"Sid": "AllowIAMUser",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::bucket/prefix1/prefix2/private/*",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:user/bobbydroptables"
]
}
},
{
"Sid": "AllowAccessToAllExceptPrivate",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::bucket/*",
"Condition": {
"StringNotLike": {
"s3:prefix": "prefix1/prefix2/private/"
}
},
"Principal": {
"AWS": [
"*"
]
}
}
]
}
When I try to save this policy I get the following error messages from AWS:
Conditions do not apply to combination of actions and resources in statement -
Condition "s3:prefix"
and action "s3:GetObject"
in statement "AllowAccessToAllExceptPrivate"
Obviously this error applies specifically to the second statement. Is it not possible to use the "s3:prefix" condition with the "s3:GetObject" action?
Is it possible to take one portion of a public bucket and make it accessible only to authenticated users?
In case it matters, this bucket will only be accessed read-only via api.
This question is similar to Amazon S3 bucket policy for public restrictions only, except I am trying to solve the problem by taking a different approach.
After much digging through AWS documentation, as well as many trial and error permutations in the policy editor, I think I have found an adequate solution.
Apparently, AWS provides an option called NotResource (not found in the Policy Generator currently).
The NotResource element lets you grant or deny access to all but a few
of your resources, by allowing you to specify only those resources to
which your policy should not be applied.
With this, I do not even need to play around with conditions. This means that the following statement will work in a bucket policy:
{
"Sid": "AllowAccessToAllExceptPrivate",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Effect": "Allow",
"NotResource": [
"arn:aws:s3:::bucket/prefix1/prefix2/private/*",
"arn:aws:s3:::bucket/prefix1/prefix2/private"
],
"Principal": {
"AWS": [
"*"
]
}
}