I have an AWS S3 bucket called test33333 I need to lock down to minimum necessary permissions. I've created a bucket policy to Deny all except user account MyUser a role MyRole. (account name xxx out)

    "Version": "2012-10-17",
    "Id": "Policy1571158084375",
    "Statement": [
            "Sid": "Stmt1568227480842",
            "Effect": "Deny",
            "NotPrincipal": {
                "AWS": [
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::test33333"

Apparently this doesn't work, even though MyRole and MyUser both have full S3 read access and can read and write to this bucket when the above bucket policy is deleted.

What am I missing? I thought this policy above should just refuse everyone but MyUser and MyRole and then use existing policies attached to the users to grant access. Ultimately I'd like for the bucket policy to control all access and not have to explicitly grant users or roles access to buckets via policies.

I've tried everything I can think of thus far. Thanks!

  • All buckets refuse all actions by all users by default. The perceived need to deny for all but a specific user means you have elsewhere granted those other users access to the bucket. If other users shouldn't have access, don't grant them access. Oct 16, 2019 at 1:00
  • It's a protection in place to prevent those with global S3 read-only access to be able to read from these buckets. You are correct that permissions should be assigned properly on the user account, but we are using bucket accounts to ensure S3 bucket policies to ensure buckets cannot be accessed even if someone is granted access via an IAM policy.
    – Boss2000
    Oct 18, 2019 at 17:52

2 Answers 2


Thanks guys. I tried the above but didn't change anything. However I did discover the issue and will post it here.

The approach above works great for user account, but is problematic with IAM roles because the role’s Principal value is composed of two Amazon Resource Names (ARNs), the role ARN and the assumed-role ARN. The role ARN is the identifier for the IAM role itself and the assumed-role ARN is what identifies the role session in the logs. When using the NotPrincipal element, you must include both ARNs for this approach to work, and the second of these ARNs should include a variable name. Normally you would specify a wildcard where the variable string would go, but this is not allowed in a Principal or NotPrincipal element. So there's another way you can restrict S3 bucket access to a specific IAM role or user within an account using Conditions instead of with the NotPrincipal element. Even if another user in the same account has an Admin policy or a policy with s3:*, they will be denied if they are not explicitly listed.

There is a good AWS article on this: https://aws.amazon.com/blogs/security/how-to-restrict-amazon-s3-bucket-access-to-a-specific-iam-role/

So in the end, the above worked fine for user account access, but not when switching roles, so the roles needs additional config to include the assumed-role ARN.

  • 1
    Thanks! Note that article suggests the use of aws:userId in conditions, but they are awkward to use (not really human-readable). The following article suggests the use of aws:PrincipalArn instead, which can take the real role (or user) name instead: dev.to/jansonsa/…
    – paulcm
    Jan 21, 2022 at 16:38
  • @paulcm This is why aws:userId is preferred.
    – jellycsc
    Mar 15 at 18:18

It sounds like you might need to specify both the bucket and its contents in the Resource tag - some permissions apply directly to the bucket only and other permissions apply to objects only, e.g.

"Resource": [


  • I think this is correct. All my IAM policies that refer to S3 buckets have both the bucket then the wildcard specified.
    – Tim
    Oct 15, 2019 at 18:40
  • Good comment, that is necessary in order to drill down into the buckets, so I was missing that above.
    – Boss2000
    Oct 15, 2019 at 20:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .