Filters: Condition

Learn about the final filter element for IAM policies.

Condition

The last filter element is the Condition that matches additional data attached to the request, as we’ve discussed in the Metadata lesson. This allows powerful fine-grained control over when the policy matches the request.

Strings

There are multiple types of metadata that IAM policies support, but the most common is the String type, which is a simple text format. With the String operators, we can specify what the value needs to be for the policy to match.

For example, this condition matches when the value of the s3:ExistingObjectTag/access is projectA:

{
    "Condition": {
        "StringEquals": {
            "s3:ExistingObjectTag/access": "projectA"
        }
    },
    // ...
}

s3:ExistingObjectTag: The s3:ExistingObjectTag/<key> is the tag attached to the S3 object. It is defined when the resource in the request targets the object, such as for the s3:GetObject action. It is not effective when the target of the operation is the bucket, such as for the s3:DeleteObject or s3:PutObject actions.
The name of the tag is in the key of the condition, so the s3:ExistingObjectTag/access is the value for the access tag. This way we can target different tags by specifying multiple s3:ExistingObjectTag keys.

Conditions also support multiple values. The following condition matches when the object has the access tag as either projectA or projectB:

{
    "Condition": {
        "StringEquals": {
            "s3:ExistingObjectTag/access": [
                "projectA",
                "projectB"
            ]
        }
    },
    // ...
}

The StringEquals is for strict equality check, but we can also use StringLike that supports wildcards. The following condition matches all access tags that start with project:

{
    "Condition": {
        "StringLike": {
            "s3:ExistingObjectTag/access": "project*"
        }
    },
    // ...
}

Multiple values inside an operator, such as StringEquals, are all needed to pass for the policy to match. This policy matches only when the S3 object is tagged with projectA and the user with admin:

{
    "Condition": {
        "StringEquals": {
            "s3:ExistingObjectTag/access": "projectA",
            "aws:PrincipalTag/access": "admin"
        }
    },
    // ...
}

It works the same across different operators. This condition matches when the object’s access tag starts with project and the user’s access tag is admin:

{
    "Condition": {
        "StringLike": {
            "s3:ExistingObjectTag/access": "project*"
        },
        "StringEquals": {
            "aws:PrincipalTag/access": "admin"
        }
    },
    // ...
}

aws:PrincipalTag: The aws:PrincipalTag/<key> is a tag attached to the Principal, for example, the IAM user making the request. It works similar to the s3:ExistingObjectTag, as different tags are accessible using different keys.

Apart from checking for equality, the operators have Not counterparts too. These work like NotPrincipal, NotAction, and NotResource and they match when the value in the metadata does not equal the provided value or values. For example, this condition tests the aws:RequestedRegion and matches if it is outside the predefined values:

{
    "Condition": {
        "StringNotEquals": {
            "aws:RequestedRegion": [
                "eu-west-1", "eu-central-1"
            ]
        }
    },
    // ...
}

aws:RequestedRegion: The aws:RequestedRegion contains the region the request is made to. Most services are regional, but there are some global ones, such as IAM, that need all their requests to go to the us-east-1 region.

This is especially useful with ‘Deny’ policies, where we can ensure that anything other than the allowed values are denied.

Let’s test your knowledge of strings!

Get hands-on with 1200+ tech skills courses.