How To Prevent Image Hotlinking With Bucket Policy AWS S3 - amazon-web-services

I'm trying to prevent hotlinking of images in my S3 bucket. I thought bucket policy this would work but so far no luck:
{
"Version": "2008-10-17",
"Id": "Bucket policy for example.com",
"Statement": [
{
"Sid": "Allow GET requests referred by example.com",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"https://www.example.com/*",
"http://www.example.com/*",
"https://example.com/*",
"http://example.com/*"
]
}
}
},
{
"Sid": "Allow GET requests that don't specify a referrer",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example/*",
"Condition": {
"Null": {
"aws:Referer": true
}
}
}
]
}
How do I make it so this policy denies access to images embedded on other websites?

Related

S3 Policy for Application Load Balancer

I am struggling with the setting up an S3 policy to give access to Application Load Balancer to push logs.
{
"Id": "Policy1629585161607",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1629585158642",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::S3bucketname/*",
"Principal": {
"AWS":"arn:aws:iam:LoadBalancerId:root"
}
}
]
}
The LoadBalancerIdcame from the last part of the loan balancer's ARN; follows the trailing slash after the load balancer's name in the ARN.
The error got from S3 is Invalid principal in policy, what have I done wrong?
The AWS docs explain well what the policy should be exactly. Sadly, your policy is incorrect. It should follow the following format:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::elb-account-id:root"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::bucket-name/prefix/AWSLogs/your-aws-account-id/*"
},
{
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::bucket-name/prefix/AWSLogs/your-aws-account-id/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
},
{
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::bucket-name"
}
]
}
On top of that, bucket must be in same region and be encrypted.

Give EC2 instance temporary S3 permission without changing instance profile

I have a Lambda function to SendCommand from an SSM Document to an EC2 instance whenever the instance changes its state to running. The Document basically downloads a package from an S3 bucket from another account and installs it on the instance. The bucket policy allows everyone to List* and Get*.
The issue is that I'm not allowed to modify the instance profile to give it S3 permission. So the question is how do I get this specific package on the instance without changing the instance profile? Is there a different approach to this?
Bucket policy
{
"Version": "2012-10-17",
"Id": "Policy111",
"Statement": [
{
"Sid": "NoDelete",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:DeleteBucket",
"Resource": "arn:aws:s3:::<bucket_name>"
},
{
"Sid": "Stmt111",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:List*",
"Resource": "arn:aws:s3:::<bucket_name>",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-111"
}
}
},
{
"Sid": "list",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:List*",
"Resource": "arn:aws:s3:::<bucket_name>/*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-111"
}
}
},
{
"Sid": "Stmt1111",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:Get*",
"Resource": "arn:aws:s3:::<bucket_name>",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-111"
}
}
},
{
"Sid": "get",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:Get*",
"Resource": "arn:aws:s3:::<bucket_name>/*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-111"
}
}
}
]
}
SSM Document
"inputs": {
"runCommand": [
"aws s3 cp {{S3Path}} .",
"sudo yum install {{PackageName}} -y"
]
}

s3 bucket policy for sso user

I wanted to allow all s3 actions on a particular bucket "test-bucket" for a specific role "test-role". Deny the bucket for all others. The s3 policy I have written :
{
"Version": "2012-10-17",
"Id": "Policy1601973417173",
"Statement": [
{
"Sid": "Allow role test-role",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxx:role/test-role"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::test-bucket/*"
},
{
"Sid": "Deny rest",
"Effect": "Deny",
"NotPrincipal": {
"AWS": "arn:aws:iam::xxxxxxxx:role/test-role"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::test-bucket/*"
}
]
}
Even after applying the above policy, the sso users which are mapped to the role "test-role" is getting Access denied on the bucket.
Note : The AWS console shows logged in user as "Federated Login: test-role/sam#abc.com".
I have also tried the "assumed-role" options are still failing. Any help appreciated.
Try this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::test-bucket",
"arn:aws:s3:::test-bucket/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"AIDA<udserid-1-suppressed>:*",
"AIDA<udserid-1-suppressed>",
"AIDA<udserid-2-suppressed>:*",
"AIDA<udserid-2-suppressed>",
"AIDA<udserid-n-suppressed>:*",
"AIDA<udserid-n-suppressed>",
"111111111111"
]
}
}
}
]
}

Lambda function to write into S3 - IAM policy to access S3

Here is my policy which grants read/write access still not able to write into S3 bucket
Problem
Still getting below error:
Failed to upload /tmp/test.txt to bucketname/Automation_Result_2019-07-09 04:20:32_.csv: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ConsoleAccess",
"Effect": "Allow",
"Action": [
"s3:GetAccountPublicAccessBlock",
"s3:GetBucketAcl",
"s3:GetBucketLocation",
"s3:GetBucketPolicyStatus",
"s3:GetBucketPublicAccessBlock",
"s3:ListAllMyBuckets"
],
"Resource": "*"
},
{
"Sid": "ListObjectsInBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": [
"arn:aws:s3:::bucketname"
]
},
{
"Sid": "AllObjectActions",
"Effect": "Allow",
"Action": "s3:*Object",
"Resource": [
"arn:aws:s3:::bucketname/*"
]
}
]
}
Bucket policy
{
"Version": "2012-10-17",
"Id": "MYBUCKETPOLICY",
"Statement": [
{
"Sid": "DenyIncorrectEncryptionHeader",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::bucket-name/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "aws:kms"
}
}
},
{
"Sid": "DenyUnEncryptedObjectUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::bucket-name/*",
"Condition": {
"Null": {
"s3:x-amz-server-side-encryption": "true"
}
}
}
]
}
Python code (within Lambda function)
Relevant part of code
s3 = boto3.resource('s3', config=Config(signature_version='s3v4'))
target_bucket = 'bucket-name'
target_file = "Output/Automation_Result_"+EST+"_.txt"
s3.meta.client.upload_file('/tmp/test.txt', target_bucket, target_file, ExtraArgs={"ServerSideEncryption": "aws:kms", "SSEKMSKeyId":"XXXXXXX-XXXX-XXXX" })
This is how my bucket public access looks like!
It works fine for me!
I took your policy, renamed the bucket and attached it to a user as their only policy.
I was then able to successfully copy an object to and from the bucket.
If it is not working for you, then either you are not using the credentials that are associated with this policy, or there is another policy that is preventing the access, such as a Deny policy or a scope-limiting policy.

How to limit access to an S3 bucket to a specific VPC while allowing console access

I am setting up a selection of S3 buckets and wish to restrict access to them to a VPC while still allowing access to the buckets from the AWS console.
As proposed here I have created an S3 endpoint and also added it to the main routing table. The policy on the endpoint allows full access to all resources.
I have created an S3 policy (see below) and added it to the bucket. As soon as I save the policy, access to the bucket from the console is no longer possible.
I have also tried to specifically add a user to the condition "StringNotEquals" in the form of "aws:username": "user1", to no avail.
{
"Version": "2012-10-17",
"Id": "Policy-S3-Bucket-myBucket",
"Statement": [
{
"Sid": "Access-via-VPC-only",
"Principal": "*",
"Action": "s3:*",
"Effect": "Deny",
"Resource": [
"arn:aws:s3:::myBucket",
"arn:aws:s3:::myBucket/*"
],
"Condition": {
"StringNotEquals": {
"aws:sourceVpc": "vpc-01c9d66c12345"
}
}
},
{
"Sid": "Allow-console-access",
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::myBucket",
"arn:aws:s3:::myBucket/*"
],
"Principal": {
"AWS": [
"arn:aws:iam::<account-id>:user/user1", "arn:aws:iam::<account-id>:user/user2"
]
}
}
]
}
The expected result would be that the S3 bucket is only accessible by the aforementioned VPC and via the AWS console.
The actual result is:
The bucket overview shows an "Error: Access Denied" and the permissions page(public access settings) shows: "You don't have access to view this configuration. Contact your account administrator to request access."
I have to login using the root user and delete the policy to regain access to the bucket.
I found a solution which seems to work. I have tested it in the policy simulator and it also appears to work correctly in the live environment. The following policy does the trick:
{
"Version": "2012-10-17",
"Id": "Policy-S3-Bucket-myBucket",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:username": ["user1", "user2"]
}
}
},
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::myBucket"],
"Condition": {
"StringEquals": {
"aws:sourceVpc": "vpc-01c9d66c12345"
}
}
},
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::myBucket"],
"Condition": {
"StringEquals": {
"aws:username": ["user1", "user2"]
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": ["arn:aws:s3:::myBucket/*"],
"Condition": {
"StringEquals": {
"aws:sourceVpc": "vpc-01c9d66c12345"
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": ["arn:aws:s3:::myBucket/*"],
"Condition": {
"StringEquals": {
"aws:username": ["user1", "user2"]
}
}
}
]
}
The policy requires for either the sourceVpc string OR the username to be as listed in the condition.
Admittedly, the policy is verbose and there is a substantial amount of replication. If anyone has an idea to solve this more efficiently, I'm all ears.
This policy was tested and gives exactly what you need:
Statement": {
"Sid": "Allow-anonymous-access-from-specific-VPC",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket_name/*",
"Condition": {
"StringEquals": {
"aws:SourceVpc": "some-vpc-id"
}
}
}
This will allow anonymous access from requests coming from "some-vpc-id", while yet allowing access from AWS console.
Your VPC has to have S3 endpoint configured for it to work.
The trick seems to be on denying everything except if it comes from the user or from the VPC but it has to be in the same condition. The way policies work is that Deny rules precede over every other rule, so if you deny, you can't then allow on a subsequent rule; it's already denied and that's it.
By the way, the aws:userid of the root user is the Account Id. Probably a bad practice to use this user but oh well :P
So my bucket now only accepts traffic from the VPC and from the user I log into via the AWS web console (so I don't get access denied errors in the web console)
{
"Version": "2012-10-17",
"Id": "Policy154336817545456388",
"Statement": [
{
"Sid": "Block-if-not-from-VPC-or-Me",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::bucket-name",
"arn:aws:s3:::bucket-name/*"
],
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": "vpce-4598ujfjrhc",
"aws:userid": "576767373466"
}
}
}
]
}