How to allow Amazon S3 access from specific IPs - amazon-web-services

I am trying this policy to allow users to Put and List object access with a particular IP (56.160.12.114) only and all the rest should have only Get access. But this policy is not working for me:
{
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPDeny",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-wicked-awesome-bucket/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "56.160.12.114/28"
}
}
}
]
}

This policy is saying: Deny access to anyone who is not using this range of IP addresses
That's fine, but you will also need a policy that Allows access, because the default behaviour is Deny. Thus, you are Denying people who are already denied by default.
A better way would be:
Have default Deny access (happens automatically)
Allow access based on IP
Something like this:
{
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-wicked-awesome-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "56.160.12.114/28"
}
}
}
]
}
Please note, however, that this is granting s3:* access to any system that is coming from that range of IP addresses (including whatever is connected to that network range). Make sure you're okay with that.
Update:
If you only want to grant the user the ability to Put and List the object, then use:
{
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::jstack-b",
"arn:aws:s3:::jstack-b/*"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": "56.160.12.114/28"
}
}
}
]
}

Related

AWS S3 Bucket Policy: How to grant access to EC2 instance?

I am really struggling with this and the AWS Official Docs simply does not help!
I have an S3 bucket set up and it is allowing public access from a few specified ip addresses. This is the custom policy that is working:
{
"Version": "2012-10-17",
"Id": "Policy1111111111",
"Statement": [
{
"Sid": "Stmt111111111",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::myapp-local-test/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"12.122.123.111",
"121.217.73.153"
]
}
}
},
{
"Sid": "Stmt1111111111",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::myapp-local-test/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"12.122.123.111",
"121.217.73.153"
]
}
}
},
]
}
Now, instead of only allowing the above 2 ip addresses to access resources in the bucket, I also want my EC2 instance to access it.
I followed this doc: https://aws.amazon.com/premiumsupport/knowledge-center/ec2-instance-access-s3-bucket/
I followed the exact steps.
I have created a new IAM role, (arn: "arn:aws:iam::1223123156:role/EC2-to-S3")
I have also attached the role to my EC2 instance.
But in step 6:
6. In your bucket policy, edit or remove any Effect: Deny
statements that are denying the IAM instance profile access to
your bucket. For instructions on editing policies,
see Editing IAM policies.
How exactly do I do it? It directs me to another doc about Editing IAM policies, BUT IT DOES NOT HELP !!!
How do I remove any "Effect: Deny" statements that are denying the IAM instance profile access to my bucket?
What keyword should I use?
Here is what I tried:
{
"Version": "2012-10-17",
"Id": "Policy1111111111",
"Statement": [
{
"Sid": "Stmt111111111",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::myapp-local-test/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"12.122.123.111",
"121.217.73.153"
]
},
"StringNotEquals": {
"aws:SourceArn": "arn:aws:iam::1223123156:role/EC2-to-S3"
}
},
{
"Sid": "Stmt1111112222",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::myapp-local-test/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"12.122.123.111",
"121.217.73.153"
]
}
}
},
{
"Sid": "Stmt1639460338435",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::myapp-local-test/*",
"Condition": {
"StringEquals": {
"aws:SourceArn": "arn:aws:iam::1223123156:role/EC2-to-S3"
}
}
}
]
}
which does not work. I still had an "Access Denied" error.
Can the docs be a little bit more specific?
Why is it so hard to get such a basic task done with aws docs??
This finally worked:
{
"Version": "2012-10-17",
"Id": "Policy1111111",
"Statement": [
{
"Sid": "Stmt11111",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::myapp-local-test/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"12.122.123.111",
"121.217.73.153"
]
}
}
},
{
"Sid": "Stmt1222222222",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::1234556:role/EC2-to-S3"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::myapp-local-test/*"
}
]
}
So the trick is to drop the deny statement completely since by default everything is denied access.
And my edits earlier:
"Statement": [
{
"Sid": "Stmt111111111",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::myapp-local-test/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"12.122.123.111",
"121.217.73.153"
]
},
"StringNotEquals": {
"aws:SourceArn": "arn:aws:iam::1223123156:role/EC2-to-S3"
}
},
the StringNotEquals part does not drop the default deny for the iam role.
If possible, you should avoid using Deny statements, since they override any Allow statements.
Your first bucket policy is saying:
Deny access to the bucket if requests are not coming from the given IP addresses
Allow access to the bucket if requests are coming from the given IP addresses
Unfortunately, the Deny will prohibit access from the EC2 instance, since it is not one of the listed IP addresses.
Instead of using Deny, just grant Allow access when needed. Access to S3 is denied by default, so users can only gain access if there is an Allow policy that grants them access.
To grant access to instance create iam instance profile and attach it your EC2 instance.
https://aws.amazon.com/premiumsupport/knowledge-center/ec2-instance-access-s3-bucket/

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"
}
}
}
]
}

How to allow only an IP/range access to AWS API Gateway resources

How best can I restrict access to certain routes in AWS API gateway by IP?
I want to allow only my ECS cluster to access certain routes in API gateway. I tried putting the ECS NAT gateway, the VPC CIDR range in aws:SourceIp but always get denied. I even tried my personal computer public IP address ... same results ... Is this the correct way? Or should I try IAM authorizers? The downside with IAM authorizer is I need to sign my API calls? Perhaps using the API Gateway SDK? Which means code change I prefer to avoid.
{
"Id": "MY_API_POLICY",
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "execute-api:Invoke",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": ["XX.XX.XX.XX/32"]
}
},
"Resource": [
"arn:aws:execute-*:*:apiid/stagename/*/private/route"
]
},
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": [
"arn:aws:execute-*:*:apiid/stagename/*/public/route"
]
}
]
}
As #Visal already mentioned is restricting the ip/range is the correct way. Here is the example: https://aws.amazon.com/de/blogs/compute/control-access-to-your-apis-using-amazon-api-gateway-resource-policies/
There is an example for a policy that allows the access for a certain ip range:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<account_idA>:user/<user>",
"arn:aws:iam::<account_idA>:root"
]
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:<account_idB>:qxz8y9c8a4/*/*/*"
},
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:<account_idB>:qxz8y9c8a4/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": " 203.0.113.0/24"
}
}
}
]
}
Or if you want to deny the access then you will find this policy:
{
"Effect": "Deny",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:<account_idB>:qxz8y9c8a4/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}

AWS access policy to allow access from an IP address or an IAM user

I am using AWS Elasticsearch and I need to setup an access policy to allow access from fixed IP to access the Kibana and the web interface. I also want to allow a specific user access key to be able to access it from any IP, as the records will be inserted from our servers.
So it boils down to create a policy where I need an or relation between IP and ARN.
Here is how my IP policy looks like:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-west-2:xxxxxx:domain/xxxx-xxxx-xxx/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "xxx.xx.xx.173"
}
}
}
]
}
and here is how my ARN policy looks like:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::xxxxxxxxx:user/xxxx"
]
},
"Action": [
"es:*"
],
"Resource": "arn:aws:es:us-west-2:xxxxxxxxx:domain/xxxxxxxxxxxxxxxx/*"
}
]
}
How can I get an or relation between them?
If I'm understanding your question properly you should be able to achieve what you want by adding the two statement objects into the statement array like:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-west-2:xxxxxx:domain/xxxx-xxxx-xxx/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "xxx.xx.xx.173"
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::xxxxxxxxx:user/xxxx"
]
},
"Action": [
"es:*"
],
"Resource": "arn:aws:es:us-west-2:xxxxxxxxx:domain/xxxxxxxxxxxxxxxx/*"
}
]
}

Accessing private files on s3

I have a private s3 bucket. I am trying to access it with the authorization. I am managing to do that only by generated a pre-signed url for each object in the bucket using AWS-SDK, which is not practical at all.
Also I have tried configuring the bucket policy and give premission only to a specific range of ips, but it won't work. How can I see what's wrong there?
What do you think is the best approach for accessing a private bucket? I am a bit confused.
policy:
{
"Version": "2008-10-17",
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPDeny",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::bucket/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "public/private IP of ec2 instance/32"
}
}
},
{
"Sid": "IPDeny",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::bucket/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "myIPAddress/32"
}
}
}
]
}
I think by default accounts are restricted from accessing S3 unless they have been given access via policy. However, S3 is designed by default to allow any IP address access. So to block IP's you would have to specify denies explicitly in the policy instead of allows.
You Should flip around the policy from allowing access from only my IP address to denying access from everywhere that is NOT my IP address.
So I Think You Might be Using this :
{
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": "arn:aws:s3::: bucketname",
"Condition": {
"IpAddress": {
"aws:SourceIp": "CIDR Of Allowed IP"
}
}
}
]
You Should Try This :
{
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPDeny",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": "arn:aws:s3::: bucket name*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "CIDR Of Allowed IP"
}
}
}
]
I Hope This Helps