R.B.
R.B.

Reputation: 537

S3 Bucket access policy: Deny on IP range and VPC Endpoint not working

I have a bucket in AWS S3. I want to allow the following access to it:

  1. From my EC2 instances in same account.
  2. From a fix set of IP addresses (from my corp network).

I have tried following:

{
"Version": "2008-10-17",
"Statement": [
    {
        "Sid": "Allow from VPCE",
        "Effect": "Allow",
        "Principal": "*",
        "Action": [
            "s3:GetObject",
            "s3:ListBucket",
            "s3:PutObject"
        ],
        "Resource": [
            "arn:aws:s3:::mybucket/*",
            "arn:aws:s3:::mybucket"
        ],
        "Condition": {
            "StringEquals": {
                "aws:sourceVpce": "vpce-1234"
            }
        }
    },
    {
        "Sid": "Allow from IP",
        "Effect": "Allow",
        "Principal": "*",
        "Action": [
            "s3:GetObject",
            "s3:ListBucket",
            "s3:PutObject"
        ],
        "Resource": [
            "arn:aws:s3:::mybucket/*",
            "arn:aws:s3:::mybucket"
        ],
        "Condition": {
            "IpAddress": {
                "aws:SourceIp": [
                    "X.X.X.X/32",
                ]
            }
        }
    },
    {
        "Sid": "Deny from NOT-IP",
        "Effect": "Deny",
        "Principal": "*",
        "Action": [
            "s3:GetObject",
            "s3:ListBucket",
            "s3:PutObject"
        ],
        "Resource": [
            "arn:aws:s3:::mybucket/*",
            "arn:aws:s3:::mybucket"
        ],
        "Condition": {
            "NotIpAddress": {
                "aws:SourceIp": [
                    "X.X.X.X/32",
                ]
            }
        }
    },
    {
        "Sid": "Deny from VPCE",
        "Effect": "Deny",
        "Principal": "*",
        "Action": [
            "s3:GetObject",
            "s3:ListBucket",
            "s3:PutObject"
        ],
        "Resource": [
            "arn:aws:s3:::mybucket/*",
            "arn:aws:s3:::mybucket"
        ],
        "Condition": {
            "StringNotEquals": {
                "aws:sourceVpce": "vpce-1234"
            }
        }
    }
]

}

My intent is to allow access from IP or VPCE and deny access from any other IP/VPCE. My public access settings blocks ALL at the account level. (Everything is blocked). This policy is not working when I try to get the object from a browser running on machine with public-ip X.X.X.X

My Questions:

IAM role (on EC2 machine) has the permissions to the bucket.

Upvotes: 0

Views: 1488

Answers (2)

Tim
Tim

Reputation: 715

This answer had useful hints, but here's concrete code that I believe should work as required to allow access from a fixed set of public IPs and from one or more VPC endpoints. I have tested this, but I have made some changes to remove private information before posting it, so please test it carefully before trusting your data to it. If anyone finds problems with it please comment. I've added a requirement for mandatory encryption in transit as well.

Change "s3:ListBucket" to whatever s3 actions you want to restrict. I have ListBucket here because it's easy to test with, and if you mess things up you don't lock yourself out of your bucket.

{
    "Version": "2012-10-17",
    "Id": "Restrictions",
    "Statement": [
        {
            "Sid": "AccessRestriction",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:ListBucket",
            "Resource": [
                "arn:aws:s3:::bucket-name",
                "arn:aws:s3:::bucket-name/*"
            ],
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": [
                        "103.21.244.0/22",
                        "173.245.48.0/20"
                    ]
                },
                "StringNotEquals": {
                    "aws:SourceVpce": "vpce-012345f67a890123"
                }
            }
        },
        {
            "Sid": "AllowSSLRequestsOnly",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::bucket-name",
                "arn:aws:s3:::bucket-name/*"
            ],
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            }
        }
    ]
}

Upvotes: 1

John Rotenstein
John Rotenstein

Reputation: 269101

The first two policies are permitting access via VPCE OR IP address range.

The first Deny is denying access to anybody not on the given IP address range. This also denies access via the VPCE if they are not coming from those IP address ranges.

The second Deny is denying access to anybody not coming from the VPCE. This also denies access to requests from the correct IP ranges if they aren't coming via the VPCE.

You can probably fix it by combining the two Deny policies together with both conditions in the same policy. This will make them act like an AND condition.

As an aside, I normally recommend against using Deny policies unless they are totally unavoidable. They can lead to many unexpected situations.

Upvotes: 1

Related Questions