How to restrict access to S3 hosted website using VPN - amazon-web-services

I have a simple website hosted on aws s3. And currently it is being accessible by anyone.
But I need to restrict the access.
So, I have an aws client vpn endpoint setup with the CIDR block of 10.3.0.0/22
So is it possible to give access only to anyone who's ONLY connected to VPN and restrict the access anything else.

We can restrict S3 access to certain ip range. Here are some examples.
Requests to S3 is allowed only when sourceIp falls under 10.3.0.0/22
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-s3-static-assets-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"10.3.0.0/22"
]
}
}
}
]
}

Related

Restricting Amazon S3 access only on VPN connectivity

I have hosted a web application on an Amazon S3 bucket and we are trying to restrict the access to the application within our VPN. So we have added the below policy to restrict the access only when we are connected to VPN. We are using Terraform software tool and Jenkins for building and deploying the application into Amazon S3 buckets.
For the first time when we deploy the application, it gets deployed successfully and also able to restrict only to VPN connected users. But now the problem I am facing is when I try to deploy the application for the second time, deployment is failing due to access restriction(Forbidden access error) and the reason for this is, our jenkins server is not on VPN and terraform refresh is failing with 403 error. The code I have used is as below.
"Sid": "VPNAccessIP",
"Action": "s3:GetObject",
"Effect": "Deny",
"Resource": [
"arn:aws:s3::: demo-dev",
"arn:aws:s3::: demo-dev/*"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"130.110.0.0/22"
]
}
},
"Principal": "*"
Is there any other approach to achieve the access restriction only for VPN connection and also it should allow deploying the application from Jenkins?
You need to use VPC Endpoint for S3, type Gateway.
Using VPC Endpoint with policy below will only allow access from your on-premise IP range and from VPCE.
VPC Endpoint type gateway is not charged, so it is a good way to use S3.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Access-from-specific-VPCE-or-IP-only",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Effect": "Deny",
"Resource": [
"arn:aws:s3:::demo-dev",
"arn:aws:s3:::demo-dev/*"
],
"Condition": {
"StringNotEquals": {
"aws:sourceVpce": "vpce-abcde12345"
},
"NotIpAddress": {
"aws:SourceIp": "130.110.0.0/22"
}
}
}
]
}

S3 Bucket Policy for Limiting Access to Cloudflare IP Addresses

I will be using Cloudflare as a proxy for my S3 website bucket to make sure users can't directly access the website with the bucket URL.
I have an S3 bucket set up for static website hosting with my custom domain: www.mydomain.com and have uploaded my index.html file.
I have a CNAME record with www.mydomain.com -> www.mydomain.com.s3-website-us-west-1.amazonaws.com and Cloudflare Proxy enabled.
Issue: I am trying to apply a bucket policy to Deny access to my website bucket unless the request originates from a range of Cloudflare IP addresses. I am following the official AWS docs to do this, but every time I try to access my website, I get a Forbidden 403 AccessDenied error.
This is my bucket policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CloudflareGetObject",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::ACCOUNT_ID:user/Administrator",
"arn:aws:iam::ACCOUNT_ID:root"
]
},
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::www.mydomain.com/*",
"arn:aws:s3:::www.mydomain.com"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"2c0f:f248::/32",
"2a06:98c0::/29",
"2803:f800::/32",
"2606:4700::/32",
"2405:b500::/32",
"2405:8100::/32",
"2400:cb00::/32",
"198.41.128.0/17",
"197.234.240.0/22",
"190.93.240.0/20",
"188.114.96.0/20",
"173.245.48.0/20",
"172.64.0.0/13",
"162.158.0.0/15",
"141.101.64.0/18",
"131.0.72.0/22",
"108.162.192.0/18",
"104.16.0.0/12",
"103.31.4.0/22",
"103.22.200.0/22",
"103.21.244.0/22"
]
}
}
}
]
}
By default, AWS Deny all the request. Source
Your policy itself does not grant access to the Administrator [or any other user], it only omits him from the list of principals that are explicitly denied. To allow him access to the resource, another policy statement must explicitly allow access using "Effect": "Allow". Source
Now, we have to create Two Policy Statment's:- First with Allow and Second with Deny. Then, It is better to have only One Policy With "allow" only to Specific IP.
It is better not to complicate simple things like using Deny with Not Principal and NotIPAddress. Even AWS says :
Very few scenarios require the use of NotPrincipal, and we recommend that you explore other authorization options before you decide to use NotPrincipal. Source
Now, the questions come on how to whitelist Cloudflare IP's???.
Let's go with a simple approach. Below is the Policy. Replace your bucket name and your Cloudflare Ip's. I have tested it and it is running.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFlareIP",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:getObject",
"Resource": [
"arn:aws:s3:::my-poc-bucket",
"arn:aws:s3:::my-poc-bucket/*"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"IP1/32",
"IP2/32"
]
}
}
}
]
}

Access Elastic Search internet endpoint only from my VPC/Subnets

I have an internet Elastic Search endpoint. I wanted to access it only within my 2 VPC's, to be specific from my EC2 instances only. Here is the policy i am trying with my VPC CIDR block IP's, but i am unable to access the endpoint from my EC2 instances. My EC2 instances are in private subnets , accessing internet through NAT Gateway. Here is my access policy which is not working
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-east-1:1XXXXXXXXXXX:domain/my-elasticsearch/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"xx.xx.xx.xx/24",
"xx.xx.xx.xx/24"
]
}
}
}
]
}
I have also tried something like this to allow access from only my EC2 instances assigned IAM role, that didnt work either
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::XXXXXXXXXXX:role/MyEC2Role"
]
},
"Action": [
"es:*"
],
"Resource": "arn:aws:es:us-east-1:XXXXXXXXXXX:domain/my-elasticsearch/*"
}
]
}
What am i doing wrong ? Or is there a better way to restrict access ?
Since you have a public AWS Elasticsearch cluster, allowing your EC2 instance from a private subnet having private IP's wont work.
Try adding the public IP of the NAT in the Access policy of your AWS ES cluster and see if that works.
Also if you are having IAM based access polices, make sure all the requests to AWS ES are signed as mentioned here: https://aws.amazon.com/blogs/database/get-started-with-amazon-elasticsearch-service-an-easy-way-to-send-aws-sigv4-signed-requests/

Making S3 static web hosting content private

I want to be able to publish test reports to S3 and have it accessible to the URL sent at the end of the Drone build.
Is it possible to have the S3 static site not view-able by anyone? So its only accessible by people who can already access resources in the VPC using a VPN.
I read that the content must have public read access, so checking if that is avoidable.
Yes:
Set up the static website as normal,
Add a VPC endpoint for S3,
Use a bucket policy to deny all but traffic from your VPC.
Here is a good article describing it in more detail: https://blog.monsterxx03.com/2017/08/19/build-private-staticwebsite-on-s3/
The other option is to write an S3 bucket policy like below, where x.x.x.x/x is the CIDR of the VPC:
{
"Id": "Policy1564215115240",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1564215036691",
"Action": "s3:*",
"Effect": "Deny",
"Resource": "arn:aws:s3:::<s3 bucket name>",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "x.x.x.x/x"
}
},
"Principal": "*"
}
]
}

Grant Access to AWS S3 bucket from specific IP without credentials

I do not want to make my S3 bucket publicly accessible. But I expect it to be accessible from my local organization network without the AWS CLI or any credentials. How can I achieve it?.
I tried bucket policy with principal as * and source IP as the public IP of organization network.
If the intention is to grant anonymous access to a particular CIDR range, while also permitting IAM policies to grant additional access to specific people (eg Administrators), then this would not be appropriate.
IF you were to follow the initial example laid out by the AWS documentation - you’ll end up with a policy that probably looks similar to this.
{
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::examplebucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "x.x.x.x/xx"
}
}
}
]
}
What you’re going to find, after banging your head on the table a few times, is that this policy does not work. There does not appear to be an implied deny rule with S3 buckets (similar to how IAM access policies are setup).
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.
Once You learn this - the policy is easy to adjust. You just flipp around the policy from allowing access from only my IP address to denying access from everywhere that was NOT my IP address.
{
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPDeny",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::examplebucket/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "xxx.x.x/xx"
}
}
}
] }
Hope this helps!
Yes, that is the correct way to do it.
From Bucket Policy Examples - Amazon Simple Storage Service:
{
"Version": "2012-10-17",
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::examplebucket/*",
"Condition": {
"IpAddress": {"aws:SourceIp": "54.240.143.0/24"}
}
}
]
}