Preventing hotlinking on Amazon S3 with CloudFront - json

I tried preventing hotlinking media files on Amazon S3 with this bucket policy.
{
"Version": "2008-10-17",
"Id": "my-id",
"Statement": [
{
"Sid": "Allow get requests to specific referrers",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketname/*",
"Condition": {
"StringLike": {
"aws:Referer": "http://sitename.com/"
}
}
},
{
"Sid": "Allow CloudFront get requests",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::amazonaccountid:root"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketname/*"
}
]
}
The ACL is set to private. I am still unable to get it to accept the files that I am trying to access.
I tried many different policies that I found here but none of them seem to have any effect.
The files that I am trying to prevent from hotlinking are .swf files.
When I use the exact (bucketname.s3.amazonaws.com) link without the cloudfront, it works.

Here is the bucket policy I used that got it to work.
{
"Version": "2008-10-17",
"Id": "http referer policy",
"Statement": [
{
"Sid": "Allow get requests referred by www.mysite.com and mysite.com",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketname/*",
"Condition": {
"StringLike": {
"aws:Referer": "http://www.mysite.com/*"
}
}
}
]
}

Related

how to give json content inside a yaml file - serverless

I have been trying to add a json policy inside a yaml file but unsuccessful so far
custom:
deploymentBucket:
versioning: true
policy: |
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowSSLRequestsOnly",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::deeperion-deployment-bucket",
"arn:aws:s3:::deeperion-deployment-bucket/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}
below serverless framework plugin allows you to add bucket policy to the deployment bucket
https://www.serverless.com/plugins/serverless-deployment-bucket

Bucket policy to allow based on provided ip address but allow a snowflake role inspite of ip address

I have a situation where I need to restrict s3 bucket to deny all other ips except the list of ips provided but also allow access for snowflake. Since the list of possible ip addresses used by snowflake in a region is a lot - https://ip-ranges.amazonaws.com/ip-ranges.json, I was trying to see if I can provide an 'Allow' based on the snowflake role created for snowflake s3 stage. The policy I tried looks like below.
{
"Version": "2012-10-17",
"Id": "SourceIP",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::11111111111:role/snowflake-role"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::s3-bucket"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/snowflake-role"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::s3-bucket/*"
},
{
"Sid": "SourceIP",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::s3-bucket",
"arn:aws:s3:::s3-bucket/*"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"10.10.100.10",
"10.10.100.11",
"10.10.100.12",
"10.10.100.13"
]
}
}
}
]
}
This works perfectly on blocking other ip addresses but Snowflake cannot access.
Since 'Deny' possibly denied all the ip addresses irrespective of above 'Allow' statement for snowflake, I tried Allow ip address as below.
{
"Version": "2012-10-17",
"Id": "SourceIP",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::11111111111:role/snowflake-role"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::s3-bucket"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/snowflake-role"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::s3-bucket/*"
},
{
"Sid": "SourceIP",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::s3-bucket",
"arn:aws:s3:::s3-bucket/*"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"10.10.100.10",
"10.10.100.11",
"10.10.100.12",
"10.10.100.13"
]
}
}
}
]
}
Now snowflake can access but ip restriction doesnt work. All ips can access the bucket. Can someone help me with my scenario?
I think that indeed the most elegant solution would be to create an IAM role and assign it to the corresponding snowflakes you want to allow accessing the S3 bucket. After that block all the access to the bucket with an explicit Deny for "Principal" : "*". Finally, you can use aws:userId or aws:PrincipalArn condition keys to only allow the users with the role to access the bucket.
Have a look at this article for more details https://levelup.gitconnected.com/how-i-locked-the-whole-company-out-of-an-amazon-s3-bucket-1781de51e4be
Best, Stefan

Can I use PrincipalTag in resource arn within AWS IAM policy to authorize a team?

I have s3 buckets named as per team names. For example the below policy works if I want to provide Get, List permissions by using a PrincipalTag in Condition operator. But I'll have to define similar policy by changing the S3 arn for every team.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": "*"
},
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::companyName-TeamName*",
"arn:aws:s3:::companyName-TeamName*/*"
],
"Condition": {
"StringEquals": {
"s3:ExistingObjectTag/teamname": "${aws:PrincipalTag/teamname}"
}
}
}
]
}
What if I want to define the resource arn using the PrincipalTag like below
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": "*"
},
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::companyName-${aws:PrincipalTag/teamname}*",
"arn:aws:s3:::companyName-${aws:PrincipalTag/teamname}*/*"
],
"Condition": {
"StringEquals": {
"s3:ExistingObjectTag/teamname": "${aws:PrincipalTag/teamname}"
}
}
}
]
}
All teams assumes their roles which has a tag 'teamname':'Their Team Name'
Can I define a policy like this? This will reduce the redundancy of policies. I do not want to define all the S3 arns in the resource section, it will be long list of teams and their buckets.

MalformedPolicyDocumentException when creating AWS::KSM::Key

I'm trying to create a KSM key to use it in the S3 service, but I get the MalformedPolicyDocument exception. Here is the resource:
"CustomerMasterKey":{
"Type" : "AWS::KMS::Key",
"Condition" : "EnableEncryption",
"Properties" : {
"Description" : "Client Master Key used to encrypt data",
"Enabled" : true,
"EnableKeyRotation" : true,
"KeyPolicy" :
{
"Version": "2012-10-17",
"Id": {"Fn::Join": ["",["Key","Policy",{"Ref": "CustomerParam"}]]},
"Statement":
[{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": {"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},"moimeco"]]}
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS":
[
{"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"}, {"Ref": "CustomerParam"}]]},
{"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},"userprod"]]}
]
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "s3.eu-west-1.amazonaws.com"
}
}
}]
}
}
},
I don't know where is the error, for me it is all good. Any idea please ?
::EDIT::
This code is giving the same error:
"CustomerMasterKey":{
"Type" : "AWS::KMS::Key",
"Properties" : {
"Description" : "A sample key",
"KeyPolicy" : {
"Version": "2012-10-17",
"Id": {"Fn::Join": ["-",["Key","Policy",{"Ref": "CustomerParam"}]]},
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": {"Fn::Join": ["", ["arn:aws:iam::",{"Ref": "AWS::AccountId"},":root"]]}
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow administration of the key",
"Effect": "Allow",
"Principal": { "AWS": {"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},":user/","userprod"]]} },
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": { "AWS": [{"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},":user/",{"Ref": "CustomerParam"}]]},
{"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},":user/","moimeco"]]}]
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": {"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},":user/",{"Ref": "CustomerParam"}]]}
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {"Bool": {"kms:GrantIsForAWSResource": "true"}}
}
]
}
}
},
The defined principals do not evaluate into Arns.
The first principal would evaluate to:
"AWS": "arn:aws:iam::11111111moimeco"
A valid ARN for a user would look like this:
"arn:aws:iam::1111111:user/username"
Additionally, you need to include the root user into your principals.
Otherwise, AWS wouldn't let you create the key at all. The reason behind this is described here:
AWS Key policies under "Allows Access to the AWS Account and Enables IAM Policies"

How to structure IAM power user to have read-only access to an S3 bucket?

(background) Currently I am trying to make a general policy for anyone who needs an account at my company so that they have access to anything they need on AWS except the ability to change their own permissions. The idea there is to give them the managed policy "PowerUserAccess". Also, in their account, they will have an S3 bucket with billing permissions, "arn:aws:s3:::c3-uits-s3".
(problem) I have try to make this s3 bucket read only, so that they can see/download their billing, but not be able to upload/delete from the bucket. My first attempt was to
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": "iam:*",
"Resource": "*"
},
{
"Effect": "Deny",
"NotAction": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
}
]
}
deny every action but Get* and List* but with those permissions I was still able to upload/delete, so I tried to get only the necessary permissions from there to only view and do nothing else and I came up with
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": "iam:*",
"Resource": "*"
},
{
"Effect": "Deny",
"NotAction": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
}
]
}
Which still had the same effect of being able to upload/delete. Another variation I tried was
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": [
"iam:*",
"s3:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"NotResource": [
"arn:aws:s3:::c3-uits-s3"
]
},
{
"Effect": "Allow",
"Action": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
}
]
}
and
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": "iam:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
},
{
"Effect": "Deny",
"Action": [
"s3:Put*",
"s3:Create*",
"s3:Delete*",
"s3:Replicate*"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
}
]
}
any help or pointers in the right direction would be greatly appreciated!
The Resource for a bucket is "arn:aws:s3:::bucket-name" but the Resource for the objects in a bucket is "arn:aws:s3:::bucket-name/*".
You aren't denying any operations on objects, here.