How can I use wildcards with explicit deny with Principal elements instead of NotPrincipal elements in an Amazon S3 bucket policy?

Last updated: 2019-05-08

How can I use wildcards with explicit deny with Principal elements instead of NotPrincipal elements in an Amazon Simple Storage Service (Amazon S3) bucket policy?

Short Description

You can prevent AWS Identity and Access Management (IAM) entities from accessing your Amazon S3 buckets by designating permissions in a bucket policy that uses the NotPrincipal element and explicit deny. However, NotPrincipal doesn't support wildcards.

In the following policy example, you must list the role session name of every user and every instance ID that will be assuming the role:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "NotPrincipal": {
        "AWS": [
          "arn:aws:sts::444455556666:assumed-role/cross-account-read-only-role/cross-account-audit-app",
          "arn:aws:sts::444455556666:assumed-role/cross-account-read-only-role/instanceID",
          "arn:aws:iam::444455556666:role/cross-account-read-only-role",
          "arn:aws:iam::444455556666:root"
        ]
      }
    }
  ]
}

To cover all of those users and instances, you need a wildcard in the statement to represent the assumed role:

"arn:aws:sts::444455556666:assumed-role/cross-account-read-only-role/*"

However, wildcards aren't supported with the NotPrincipal element.

Resolution

Instead of NotPrincipal, use Principal as the target entity in each statement block, which includes the condition for each allow block.

Before beginning, you must have the following resources:

In this example, wildcards are used in aws:userid to include all names that are passed by the calling process (such as application, service, or instance ID) when it makes a call to get temporary credentials. For more information, see Information Available in All Requests. The root account is included to prevent lockout:

Note: Be sure that you replace the example names with your own role IDs and bucket names.

"Condition": {
                "StringLike": {
                    "aws:userid": [
                        "AROAID2GEXAMPLEROLEID:*",
                        "444455556666"
                    ]
                }
            }

StringNotLike in the deny block:

"Condition": {
                "StringNotLike": {
                    "aws:userid": [
                        "AROAID2GEXAMPLEROLEID:*",
                        "444455556666"
                    ]
                }
            }

Here is the complete policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::myExampleBucket",
            "Condition": {
                "StringLike": {
                    "aws:userid": [
                        "AROAID2GEXAMPLEROLEID:*",
                        "444455556666"
                    ]
                }
            }
        },
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:DeleteObject",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::myExampleBucket/*",
            "Condition": {
                "StringLike": {
                    "aws:userid": [
                        "AROAID2GEXAMPLEROLEID:*",
                        "444455556666"
                    ]
                }
            }
        },
        {
            "Sid": "",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::myExampleBucket/*",
                "arn:aws:s3:::myExampleBucket"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:userid": [
                        "AROAID2GEXAMPLEROLEID:*",
                        "444455556666"
                    ]
                }
            }
        }
    ]
}