user1532587
user1532587

Reputation: 1023

In AWS s3, how to allow read and write only in specific prefixes (using a wildcard)

I have a bucket that has these prefixes:

Users have access to all bucket by default, but I want to deny access to this specific bucket to all prefixes except those listed above (read/write), for which I tried something like this:

{
    "Version": "2012-10-17",
    "Id": "BlockReadWriteListAccessExceptUser",
    "Statement": [
        {
            "Sid": "BlockReadWriteAccess",
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::mybucket",
                "arn:aws:s3:::mybucket/*"
            ]
        },
        {
            "Sid": "AllowReadWriteAccess",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::mybucket/*_user"
        }
    ]
}

I realized that for get and put, I cannot use conditions, so how can I achieve that?

Upvotes: 1

Views: 1818

Answers (2)

wristbands
wristbands

Reputation: 1369

jellycsc's answer was super helpful to me, but it's not complete. You must also include an Allow statement for all resources in your bucket. Otherwise, you won't be able to access any resources.

You then follow that Allow statement with the Deny statement provided by jellycsc, which overrides the allow and denies all resources except the specific ones you'd still like to allow.

So the full policy should be the following:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadWriteAccess",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::mybucket/*"
        },
        {
            "Sid": "BlockReadWriteAccess",
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "NotResource": "arn:aws:s3:::mybucket/*_user*"
        }
    ]
}

Upvotes: 0

jellycsc
jellycsc

Reputation: 12289

Your bucket policy will not work because explicit deny always overrides the allows. I want to make this crystal clear. For example, say you want to add an object 999_user. The object ARN is arn:aws:s3:::mybucket/999_user, which matches the deny statement with sid "BlockReadWriteAccess". S3 will deny this request right away without even looking at the "AllowReadWriteAccess" statement.

How to achieve the behaviour you want? The policy element NotResource comes in handy in this case.

{
    "Version": "2012-10-17",
    "Id": "BlockReadWriteListAccessExceptUser",
    "Statement": [
        {
            "Sid": "BlockReadWriteAccess",
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "NotResource": "arn:aws:s3:::mybucket/*_user*"
        }
    ]
}

Upvotes: 1

Related Questions