I've been trying all possible options but with no results. My Bucket Policy works well with aws:Referer but it doesn't work at all with Source Ip as the condition.

My Server is hosted with EC2 and I am using the Public IP in this format xxx.xxx.xxx.xxx/32 (Public_Ip/32) as the Source Ip parameter.

Can anyone tell me what I am doing wrong?

Currently my Policy is the following

{
   "Version": "2008-10-17",
   "Id": "S3PolicyId1",
   "Statement": [
                {
                 "Sid": "IPDeny",
                 "Effect": "Deny",
                 "Principal": {
                               "AWS": "*"
                               },
                 "Action": "s3:*",
                 "Resource": "arn:aws:s3:::my_bucket/*",
                 "Condition": {
                               "NotIpAddress": {
                                                "aws:SourceIp": "xx.xx.xxx.xxx/32"
                                                }
                               }
               }
               ]
}

I read all examples and case studies but it doesn't seem to allow access based on Source IP...

Thanks a lot!!!

有帮助吗?

解决方案

From the discussion on the comments on the question, it looks like your situation can be rephrased as follows:

How can I give an specific EC2 instance full access to an S3 bucket, and deny access from every other source?

Usually, the best approach is to create an IAM Role and launch your EC2 instance associated with that IAM Role. As I'm going to explain, it is usually much better to use IAM Roles to define your access policies than it is to specify source IP addresses.

IAM Roles

IAM, or Identity and Access Management, is a service that can be used to create users, groups and roles, manage access policies associated with those three kinds of entities, manage credentials, and more.

Once you have your IAM role created, you are able to launch an EC2 instance "within" that role. In simple terms, it means that the EC2 instance will inherit the access policy you associated with that role. Note that you cannot change the IAM Role associated with an instance after you launched the instance. You can, however, modify the Access Policy associated with an IAM Role whenever you want.

The IAM service is free, and you don't pay anything extra when you associate an EC2 instance with an IAM Role.

In your situation

In your situation, what you should do is create an IAM Role to use within EC2 and attach a policy that will give the permissions you need, i.e., that will "Allow" all the "s3:xxx" operations it will need to execute on that specific resource "arn:aws:s3:::my_bucket/*".

Then you launch a new instance with this role (on the current AWS Management Console, on the EC2 Launch Instance wizard, you do this on the 3rd step, right after choosing the Instance Type).

Temporary Credentials

When you associate an IAM Role with an EC2 instance, the instance is able to obtain a set of temporary AWS credentials (let's focus on the results and benefits, and not exactly on how this process works). If you are using the AWS CLI or any of the AWS SDKs, then you simply don't specify any credential at all and the CLI or SDK will figure out it has to look for those temporary credentials somewhere inside the instance.

This way, you don't have to hard code credentials, or inject the credentials into the instance somehow. The instance and the CLI or SDK will manage this for you. As an added benefit, you get increased security: the credentials are temporary and rotated automatically.

In your situation

If you are using the AWS CLI, you would simply run the commands without specifying any credentials. You'll be allowed to run the APIs that you specified in the IAM Role Access Policy. For example, you would be able to upload a file to that bucket:

aws s3 cp my_file.txt s3://my_bucket/

If you are using an SDK, say the Java SDK, you would be able to interact with S3 by creating the client objects without specifying any credentials:

AmazonS3 s3 = new AmazonS3Client(); // no credentials on the constructor!
s3.putObject("my_bucket", ........);

I hope this helps you solve your problem. If you have any further related questions, leave a comment and I will try to address them on this answer.

其他提示

While I won't disagree that policies are better than IP address wherever possible, the accepted answer didn't actually achieve the original question's goal. I needed to do this (I need access from a machine that wasn't EC2, and thus didn't have policies).

Here is a policy that only allows a certain (or multiple IPs) to access a bucket's object. This assumes that there is no other policy to allow access to the bucket (by default, buckets grant no public access).

This policy also does not allow listing. Only if you know if the full url to the object you need. If you need more permissions, just add them to the Action bit.

{
  "Id": "Policy123456789",
  "Statement": [
    {
      "Sid": "IPAllow",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "s3:GetObject"
      ],
      "Resource": "arn:aws:s3:::mybucket/*",
      "Condition" : {
        "IpAddress" : {
          "aws:SourceIp": [
            "xx.xx.xx.xx/32"
          ]
        }
      } 
    } 
  ]
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top