

# Amazon SNS subscription filter policies
<a name="sns-subscription-filter-policies"></a>

A subscription filter policy allows you to specify property names and assign a list of values to each property name. For more information, see [Amazon SNS message filtering](sns-message-filtering.md).

When Amazon SNS evaluates message attributes or message body properties against the subscription filter policy, it ignores the ones that aren't specified in the policy.

**Important**  
AWS services such as IAM and Amazon SNS use a distributed computing model called eventual consistency. Additions or changes to a subscription filter policy require up to 15 minutes to fully take effect. 

A subscription accepts a message under the following conditions:
+ When the filter policy scope is set to `MessageAttributes`, each property name in the filter policy matches a message attribute name. For each matching property name in the filter policy, at least one property value matches the message attribute value.
+ When the filter policy scope is set to `MessageBody`, each property name in the filter policy matches a message body property name. For each matching property name in the filter policy, at least one property value matches the message body property value.

Amazon SNS currently supports the following filter operators:
+ [AND logic](and-or-logic.md#and-logic)
+ [OR logic](and-or-logic.md#or-logic)
+ [OR operator](and-or-logic.md#or-operator)
+ [Key matching](attribute-key-matching.md)
+ [Numeric value exact matching](numeric-value-matching.md#numeric-exact-matching)
+ [Numeric value anything-but matching](numeric-value-matching.md#numeric-anything-but-matching)
+ [Numeric value range matching](numeric-value-matching.md#numeric-value-range-matching)
+ [String value exact matching](string-value-matching.md#string-exact-matching)
+ [String value anything-but matching](string-value-matching.md#string-anything-but-matching)
+ [String matching using a prefix with the anything-but operator](string-value-matching.md#string-anything-but-matching)
+ [String value equals-ignore case](string-value-matching.md#string-equals-ignore)
+ [String value IP address matching](string-value-matching.md#string-address-matching)
+ [String value prefix matching](string-value-matching.md#string-prefix-matching)
+ [String value suffix matching](string-value-matching.md#string-suffix-matching)

# Amazon SNS example filter policies
<a name="example-filter-policies"></a>

The following example shows a message payload delivered by an Amazon SNS topic that processes customer transactions.

The first example includes the `MessageAttributes` field with attributes that describe the transaction:
+ Customer's interests
+ Store name
+ Event state
+ Purchase price in USD

Because this message includes the `MessageAttributes` field, any topic subscription that sets a `FilterPolicy` can selectively accept or reject the message, as long as `FilterPolicyScope` is set to `MessageAttributes` in the subscription. For information about applying attributes to a message, see [Amazon SNS message attributes](sns-message-attributes.md).

```
{
   "Type": "Notification",
   "MessageId": "a1b2c34d-567e-8f90-g1h2-i345j67klmn8",
   "TopicArn": "arn:aws:sns:us-east-2:123456789012:MyTopic",
   "Message": "message-body-with-transaction-details",
   "Timestamp": "2019-11-03T23:28:01.631Z",
   "SignatureVersion": "4",
   "Signature": "signature",
   "UnsubscribeURL": "unsubscribe-url",
   "MessageAttributes": {
      "customer_interests": {
         "Type": "String.Array",
         "Value": "[\"soccer\", \"rugby\", \"hockey\"]"
      },
      "store": {
         "Type": "String",
         "Value":"example_corp"
      },
      "event": {
         "Type": "String",
         "Value": "order_placed"
      },
      "price_usd": {
         "Type": "Number", 
         "Value": "210.75"
      }
   }
}
```

The following example shows the same attributes included within the `Message` field, also referred to as the *message payload* or *message body*. Any topic subscription that includes a `FilterPolicy` can selectively accept or reject the message, as long as `FilterPolicyScope` is set to `MessageBody` in the subscription. 

```
{
"Type": "Notification",
   "MessageId": "a1b2c34d-567e-8f90-g1h2-i345j67klmn8",
   "TopicArn": "arn:aws:sns:us-east-2:123456789012:MyTopic",
   "Message": "{
      \"customer_interests\": [\"soccer\", \"rugby\", \"hockey\"],
      \"store\": \"example_corp\",
      \"event\":\"order_placed\",
      \"price_usd\":210.75
   }",
   "Timestamp": "2019-11-03T23:28:01.631Z",
   "SignatureVersion": "4",
   "Signature": "signature",
   "UnsubscribeURL": "unsubscribe-url"
}
```

The following filter policies accept or reject messages based on their property names and values.

## A policy that accepts the example message
<a name="policy-accepts-messages"></a>

The properties in the following subscription filter policy match the attributes assigned to the example message. Note that the same filter policy works for a `FilterPolicyScope` whether it's set to `MessageAttributes` or `MessageBody`. Each subscriber chooses their filtering scope according to the composition of the messages that they receive from the topic.

If any single property in this policy doesn't match an attribute assigned to the message, the policy rejects the message.

```
{
   "store": ["example_corp"],
   "event": [{"anything-but": "order_cancelled"}],
   "customer_interests": [
      "rugby",
      "football",
      "baseball"
   ],
   "price_usd": [{"numeric": [">=", 100]}]
}
```

## A policy that rejects the example message
<a name="policy-rejects-messages"></a>

The following subscription filter policy has multiple mismatches between its properties and the attributes assigned to the example message. For example, because the `encrypted` property name isn't present in the message attributes, this policy property causes the message to be rejected regardless of the value assigned to it. 

If any mismatches occur, the policy rejects the message.

```
{
   "store": ["example_corp"],
   "event": ["order_cancelled"],
   "encrypted": [false],
   "customer_interests": [
      "basketball",
      "baseball"
   ]
}
```

# Filter policy constraints in Amazon SNS
<a name="subscription-filter-policy-constraints"></a>

When you’re setting up filter policies in Amazon SNS, there are a few important rules to keep in mind. These rules help ensure the effective application of filter policies while maintaining system performance and compatibility.

## Common policy constraints
<a name="subscription-filter-policy-common-constraints"></a>

When configuring filter policies in Amazon SNS, follow these important rules to ensure they work effectively while maintaining system performance and compatibility:
+ **String matching** – For string matching in the filter policy, the comparison is case-sensitive.
+ **Numeric matching** – For numeric matching, the value can range from -109 to 109 (-1 billion to 1 billion), with five digits of accuracy after the decimal point.
+ **Filter policy complexity** – The total combination of values in a filter policy must not exceed **150**. To calculate the total combination, multiply the number of values in each array in the filter policy.
+ **Limit number of keys** – A filter policy can have a maximum of **five** keys.

****Additional considerations****
+ The JSON of the filter policy can contain the following:
  + Strings enclosed in quotation marks
  + Numbers
  + The keywords `true`, `false`, and `null`, without quotation marks
+ When using the Amazon SNS API, you must pass the JSON of the filter policy as a valid **UTF-8 **string.
+ The maximum size of a filter policy is **256 KB**.
+ By default, you can have up to **200** filter policies per topic, and **10,000** filter policies per AWS account.

  This policy limit won't stop Amazon SQS queue subscriptions from being created with the [https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html](https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html) API. However, it will fail when you attach the filter policy in the `Subscribe` API call (or the [https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html](https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html) API call).

  To increase this quota, you can use [AWS Service Quotas](https://docs.aws.amazon.com/servicequotas/latest/userguide/intro.html).

## Policy constraints for attribute-based filtering
<a name="subscription-filter-policy-attribute-constraints"></a>

Attribute-based filtering is the default option. [https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html#API_SetSubscriptionAttributes_RequestParameters](https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html#API_SetSubscriptionAttributes_RequestParameters) is set to `MessageAttributes` in the subscription.
+ Amazon SNS doesn't accept a nested filter policy for attribute-based filtering.
+ Amazon SNS compares policy properties only to message attributes that have the following data types:
  + `String`
  + `String.Array`
**Important**  
When using attribute-based filtering in Amazon SNS, you must double-escape certain special characters, specifically:  
Double quotes (")
Backslashes ()
Failure to double-escape these characters will result in the filter policy not matching the attributes of a published message, and the notification won't be delivered.

**Additional considerations**
+ Passing objects in arrays isn't recommended because it may yield unexpected results due to the nesting, which isn't supported by attribute-based filtering. Use payload-based filtering for nested policies.
+ `Number` is supported for numeric attribute values.
+ Amazon SNS ignores message attributes with the Binary data type.

**Example policy for complexity:**

In the following policy example, the first key has **three** match operators, the second has **one** match operator, and the third has **two** match operators.

```
{
   "key_a": ["value_one", "value_two", "value_three"],
   "key_b": ["value_one"],
   "key_c": ["value_one", "value_two"]
}
```

The total combination is calculated as the product of the number of match operators for each key in the filter policy:

```
3(match operators of key_a) 
x 1(match operators of key_b) 
x 2(match operators of key_c) 
= 6
```

## Policy constraints for payload-based filtering
<a name="subscription-filter-policy-payload-constraints"></a>

To switch from attribute-based (default) to payload-based filtering, you must set the [https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeprovisionIpamPoolCidr.html](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeprovisionIpamPoolCidr.html) to `MessageBody` in the subscription.
+ Amazon SNS accepts a nested filter policy for payload-based filtering.
+ For a nested policy, only **leaf keys** are counted towards the **five** key limit.

**Example policy for key limit:**

In the following policy example:
+ There are two leaf keys: `key_c` and `key_e`.
+ `key_c` has **four** match operators with a nested level of **three**, and `key_e` has **three** match operators with a nested level of **two**.

```
{
"key_a": {
    "key_b": {
        "key_c": ["value_one", "value_two", "value_three", "value_four"]
        }
    },
"key_d": {
    "key_e": ["value_one", "value_two", "value_three"]
    }
}
```

The total combination is calculated as the product of the number of match operators and the nested level for each key in the filter policy:

```
4(match operators of key_c) 
x 3(nested level of key_c) 
x 3(match operators of key_e) 
x 2(nested level of key_e) 
= 72
```

## Wildcard pattern usage guidelines
<a name="filter-policy-constraints-wildcard"></a>

 Amazon SQS implements protections for when you register a filter policy containing wildcards to ensure that filter policies too complex are not created, as this would impact your application performance. 

**Pattern structure**

Fields contain one or more patterns. The following example shows a field using two patterns:

```
{
    "greeting": [
      {"anything-but": {"prefix": "Hello"}},
      {"wildcard": "H*"}
    ] // 2 patterns
  }
```

**Complexity rules**
+  Total wildcard complexity across all fields must not exceed 100 points 
+  Maximum 3 wildcards per pattern 

**Complexity calculation**
+  Field complexity = `(Sum of pattern points)` × `(Number of patterns)` 
+ Pattern points:

   Single wildcard: 1 point 

   Multiple wildcards: 3 points each 

   Anything-but: 1 point 

  The following is an example of the complexity calculation:

  ```
  {
    "filename": [
      {"wildcard": "*.txt"},     // 1 point
      {"wildcard": "log*"}      // 1 point
    ]                           // Total: (1 + 1) × 2 = 4 points
  }
  ```

# AND/OR logic
<a name="and-or-logic"></a>

Use AND/OR logic in filter policies to match message attributes or message body properties in Amazon SNS. This enables more precise and flexible message filtering.

## AND logic
<a name="and-logic"></a>

You can apply AND logic using multiple property names.

Consider the following policy:

```
{
  "customer_interests": ["rugby"],
  "price_usd": [{"numeric": [">", 100]}]
}
```

It matches any message attribute or message body property with the value of `customer_interests` set to `rugby` *and* the value of `price_usd` set to a number larger than 100.

**Note**  
You can't apply AND logic to values of the same attribute.

## OR logic
<a name="or-logic"></a>

You can apply OR logic by assigning multiple values to a property name.

Consider the following policy:

```
{
   "customer_interests": ["rugby", "football", "baseball"]
}
```

It matches any message attribute or message body property with the value of `customer_interests` set to `rugby`, `football`, *or* `baseball`.

## OR operator
<a name="or-operator"></a>

You can use the `"$or"` operator to explicitly define a filter policy to express the OR relationship between multiple attributes in the policy.

Amazon SNS only recognizes an `"$or"` relationship when the policy has met all of the following conditions. When all of these conditions are not met, `"$or"` is treated as a regular attribute name, the same as any other string in the policy.
+ There is an `"$or"` field attribute in the rule followed with an array, for example `“$or” : []`.
+ There are at least 2 objects in the `"$or"` array: `"$or": [{}, {}]`.
+ None of the objects in the `"$or"` array have field names that are reserved keywords.

Otherwise `"$or"` is treated as a normal attribute name, the same as other strings in the policy.

The following policy isn't parsed as an OR relationship because numeric and prefix are reserved keywords.

```
{ 
   "$or": [ {"numeric" : 123}, {"prefix": "abc"} ] 
}
```

**`OR` operator examples**

Standard `OR`:

```
{
  "source": [ "aws.cloudwatch" ], 
  "$or": [
    { "metricName": [ "CPUUtilization" ] },
    { "namespace": [ "AWS/EC2" ] }
  ] 
}
```

The filter logic for this policy is:

```
"source" && ("metricName" || "namespace")
```

It matches either of the following sets of message attributes:

```
"source": {"Type": "String", "Value": "aws.cloudwatch"},
"metricName": {"Type": "String", "Value": "CPUUtilization"}
```

or

```
"source": {"Type": "String", "Value": "aws.cloudwatch"},
"namespace": {"Type": "String", "Value": "AWS/EC2"}
```

It also matches either of the following message bodies:

```
{
    "source": "aws.cloudwatch",
    "metricName": "CPUUtilization"
}
```

or

```
{
    "source": "aws.cloudwatch",
    "namespace": "AWS/EC2"
}
```

### Policy constraints that include `OR` relationships
<a name="or-operator-constraints"></a>

Consider the following policy:

```
{
    "source": [ "aws.cloudwatch" ],
    "$or": [
      { "metricName": [ "CPUUtilization", "ReadLatency" ] },
      {
        "metricType": [ "MetricType" ] ,
        "$or" : [
          { "metricId": [ 1234, 4321 ] },
          { "spaceId": [ 1000, 2000, 3000 ] }
        ]
      }
    ]
  }
```

The logic for this policy can also be simplified as:

```
("source" AND "metricName") 
OR 
("source" AND "metricType" AND "metricId") 
OR 
("source" AND "metricType" AND "spaceId")
```

The complexity calculation for policies with OR relationships can be simplified as the sum of the combination complexities for each OR statement.

The total combination is calculated as follows:

```
(source * metricName) + (source * metricType * metricId) + (source * metricType * spaceId)
= (1 * 2) + (1 * 1 * 2) + (1 * 1 * 3) 
= 7
```

`source` has one value, `metricName` has two values, `metricType` has one value, `metricId` has two values and `spaceId` has three values.

Consider the following nested filter policy:

```
{
    "$or": [
      { "metricName": [ "CPUUtilization", "ReadLatency" ] },
      { "namespace": [ "AWS/EC2", "AWS/ES" ] }
    ],
    "detail" : {
      "scope" : [ "Service" ],
      "$or": [
        { "source": [ "aws.cloudwatch" ] },
        { "type": [ "CloudWatch Alarm State Change"] }
      ]
    }
  }
```

The logic for this policy can be simplified as:

```
("metricName" AND ("detail"."scope" AND "detail"."source")
OR
("metricName" AND ("detail"."scope" AND "detail"."type")
OR
("namespace" AND ("detail"."scope" AND "detail"."source")
OR
("namespace" AND ("detail"."scope" AND "detail"."type")
```

The calculation for total combinations is the same for non-nested policies except we need to consider the a key’s nesting level.

The total combination is calculated as follows:

```
(2 * 2 * 2) + (2 * 2 * 2) + (2 * 2 * 2) + (2 * 2 * 2) = 32
```

`metricName` has two values, `namespace` has two values, `scope` is a two level nested key with one value, `source` is a two level nested key with one value, and `type` is a two level nested key with one value.

# Key matching
<a name="attribute-key-matching"></a>

Use the `exists` operator in a filter policy to match incoming messages based on whether a specific property is present or absent.
+ `exists` works only on leaf nodes (final attributes in the structure).
+ It does not apply to intermediate nodes within a nested JSON structure.
+ Use `"exists": true` to match incoming messages that include the specified property. The key must have a non-null and non-empty value.

  For example, the following policy property uses the `exists` operator with a value of `true`:

  ```
  "store": [{"exists": true}]
  ```

  It matches any list of message attributes that contains the `store` attribute key, such as the following:

  ```
  "store": {"Type": "String", "Value": "fans"}
  "customer_interests": {"Type": "String.Array", "Value": "[\"baseball\", \"basketball\"]"}
  ```

  It also matches either of the following message body:

  ```
  {
      "store": "fans"
      "customer_interests": ["baseball", "basketball"]
  }
  ```

  However, it doesn't match any list of message attributes *without* the `store` attribute key, such as the following:

  ```
  "customer_interests": {"Type": "String.Array", "Value": "[\"baseball\", \"basketball\"]"}
  ```

  Nor does it match the following message body:

  ```
  {
      "customer_interests": ["baseball", "basketball"]
  }
  ```
+ Use `"exists": false` to match incoming messages that *don't* include the specified property.
**Note**  
`"exists": false` only matches if at least one attribute is present. An empty set of attributes results in the filter not matching.

  For example, the following policy property uses the `exists` operator with a value of `false`:

  ```
  "store": [{"exists": false}]
  ```

  It *doesn't* match any list of message attributes that contains the `store` attribute key, such as the following:

  ```
  "store": {"Type": "String", "Value": "fans"}
  "customer_interests": {"Type": "String.Array", "Value": "[\"baseball\", \"basketball\"]"}
  ```

  It also doesn’t match the following message body:

  ```
  {
      "store": "fans"
      "customer_interests": ["baseball", "basketball"]
  }
  ```

  However, it matches any list of message attributes *without* the `store` attribute key, such as the following:

  ```
  "customer_interests": {"Type": "String.Array", "Value": "[\"baseball\", \"basketball\"]"}
  ```

  It also matches the following message body:

  ```
  {
      "customer_interests": ["baseball", "basketball"]
  }
  ```

# Numeric value matching
<a name="numeric-value-matching"></a>

Filter messages by matching numeric values to message attribute values or to message body property values. Numeric values aren't enclosed in double quotation marks in the JSON policy. You can use the following numeric operations for filtering.

**Note**  
Prefixes are supported for *string* matching only.

## Exact matching
<a name="numeric-exact-matching"></a>

When a policy property value includes the keyword `numeric` and the operator `=`, it matches any message attribute or message body property values that have the same name and an equal numeric value.

Consider the following policy property:

```
"price_usd": [{"numeric": ["=",301.5]}]
```

It matches either of the following message attributes:

```
"price_usd": {"Type": "Number", "Value": 301.5}
```

```
"price_usd": {"Type": "Number", "Value": 3.015e2}
```

It also matches either of the following message bodies:

```
{
   "price_usd": 301.5
}
```

```
{
   "price_usd": 3.015e2
}
```

## Anything-but matching
<a name="numeric-anything-but-matching"></a>

When a policy property value includes the keyword `anything-but`, it matches any message attribute or message body property values that *don't* include any of the policy property values.

Consider the following policy property:

```
"price": [{"anything-but": [100, 500]}]
```

It matches either of the following message attributes:

```
"price": {"Type": "Number", "Value": 101}
```

```
"price": {"Type": "Number", "Value": 100.1}
```

It also matches either of the following message bodies:

```
{
   "price": 101
}
```

```
{
   "price": 100.1
}
```

Moreover, it matches the following message attribute (because it contains a value that *isn't* `100` or `500`):

```
"price": {"Type": "Number.Array", "Value": "[100, 50]"}
```

And it also matches the following message body (because it contains a value that *isn't* `100` or `500`):

```
{
   "price": [100, 50]
}
```

However, it doesn't match the following message attribute:

```
"price": {"Type": "Number", "Value": 100}
```

Nor does it match the following message body:

```
{
   "price": 100
}
```

## Value range matching
<a name="numeric-value-range-matching"></a>

In addition to the operator `=`, a numeric policy property can include the following operators: `<`, `<=`, `>`, and `>=`.

Consider the following policy property:

```
"price_usd": [{"numeric": ["<", 0]}]
```

It matches any message attribute or message body property with negative numeric values.

Consider another message attribute:

```
"price_usd": [{"numeric": [">", 0, "<=", 150]}]
```

It matches any message attribute or message body property with positive numbers up to and including 150.

# String value matching
<a name="string-value-matching"></a>

Filter messages by matching string values to message attribute values or message body property values. String values are enclosed in double quotation marks in the JSON policy. You can use the following string operations to match message attributes or message body properties:

## Exact matching
<a name="string-exact-matching"></a>

Exact matching occurs when a policy property value matches one or more message attribute values. For `String.Array` type attributes, each element in the array is treated as a separate string for matching purposes.

Consider the following policy property:

```
"customer_interests": ["rugby", "tennis"]
```

It matches the following message attributes:

```
"customer_interests": {"Type": "String", "Value": "rugby"}
```

```
"customer_interests": {"Type": "String", "Value": "tennis"}
```

```
"customer_interests": {"Type": "String.Array", "Value": "[\"rugby\", \"tennis\"]"}
```

It also matches the following message bodies:

```
{
   "customer_interests": "rugby"
}
```

```
{
   "customer_interests": "tennis"
}
```

However, it doesn't match the following message attributes:

```
"customer_interests": {"Type": "String", "Value": "baseball"}
```

```
"customer_interests": {"Type": "String.Array", "Value": "[\"baseball\"]"}
```

Nor does it match the following message body:

```
{
   "customer_interests": "baseball"
}
```

## Anything-but matching
<a name="string-anything-but-matching"></a>

When a policy property value includes the keyword `anything-but`, it matches any message attribute or message body values that *don't* include any of the policy property values. `anything-but` can be combined with `"exists": false`. For `String.Array` type attributes, it matches if none of the array elements are listed in the policy property.

Consider the following policy property:

```
"customer_interests": [{"anything-but": ["rugby", "tennis"]}]
```

It matches any of the following message attributes:

```
"customer_interests": {"Type": "String", "Value": "baseball"}
```

```
"customer_interests": {"Type": "String", "Value": "football"}
```

```
"customer_interests": {"Type": "String.Array", "Value": "[\"rugby\", \"baseball\"]"}
```

It also matches either of the following message bodies:

```
{
   "customer_interests": "baseball"
}
```

```
{
   "customer_interests": "football"
}
```

Moreover, it matches the following message attribute (because it contains a value that *isn't* `rugby` or `tennis`):

```
"customer_interests": {"Type": "String.Array", "Value": "[\"rugby\", \"baseball\"]"}
```

And it also matches the following message body (because it contains a value that isn't `rugby` or `tennis`):

```
{
   "customer_interests": ["rugby", "baseball"]
}
```

However, it doesn't match the following message attributes:

```
"customer_interests": {"Type": "String", "Value": "rugby"}
```

```
"customer_interests": {"Type": "String.Array", "Value": "[\"rugby\"]"}
```

Nor does it match the following message body:

```
{
   "customer_interests": ["rugby"]
}
```

**Using a prefix with `anything-but`**

For string matching, you can also use a prefix with the `anything-but` operator. For example, the following policy property denies the `order-` prefix:

```
"event":[{"anything-but": {"prefix": "order-"}}]
```

It matches either of the following attributes:

```
"event": {"Type": "String", "Value": "data-entry"}
```

```
"event": {"Type": "String", "Value": "order_number"}
```

It also matches either of the following message bodies:

```
{
   "event": "data-entry"
}
```

```
{
   "event": "order_number"
}
```

However, it doesn't match the following message attribute:

```
"event": {"Type": "String", "Value": "order-cancelled"}
```

Nor does it match the following message body:

```
{
   "event": "order-cancelled"
}
```

**anything-but wildcard**

The following policy property denies the `*ball` wildcard:

```
"customer_interests" : [{ "anything-but": { "wildcard": "*ball" }}]
```

It matches the following attributes:

```
{"customer_interests": ["hockey", "rugby", "soccer] }
```

However, it does not match the following message attribute:

```
{"customer_interests": ["baseball", "basketball"] }
```

**anything-but suffix** 

The following policy property denies the `-ball`

 suffix:

```
"customer_interests": [ { "anything-but": { "suffix": "ball" } } ]
```

It matches the following attributes:

```
{"customer_interests": ["hockey", "rugby", "soccer] }
```

However, it does not match the following message attribute:

```
 {"customer_interests": ["baseball", "basketball"] }
```

## Equals-ignore-case matching
<a name="string-equals-ignore"></a>

When a policy property includes the keyword `equals-ignore-case`, it will perform a case-insensitive match with any message attribute or body property value.

Consider the following policy property:

```
"customer_interests": [{"equals-ignore-case": "tennis"}]
```

It matches either of the following message attributes:

```
"customer_interests": {"Type": "String", "Value": "TENNIS"}
```

```
"customer_interests": {"Type": "String", "Value": "Tennis"}
```

It also matches either of the following message bodies:

```
{
    "customer_interests": "TENNIS"
}
```

```
{
    "customer_interests": "teNnis"
{
```

## IP address matching
<a name="string-address-matching"></a>

You can use the `cidr` operator to check whether an incoming message originates from a specific IP address or subnet. 

Consider the following policy property:

```
"source_ip":[{"cidr": "10.0.0.0/24"}]
```

It matches either of the following message attributes:

```
"source_ip": {"Type": "String", "Value": "10.0.0.0"}
```

```
"source_ip": {"Type": "String", "Value": "10.0.0.255"}
```

It also matches either of the following message bodies:

```
{
   "source_ip": "10.0.0.0"
}
```

```
{
   "source_ip": "10.0.0.255"
}
```

However, it doesn't match the following message attribute:

```
"source_ip": {"Type": "String", "Value": "10.1.1.0"}
```

Nor does it match the following message body:

```
{
   "source_ip": "10.1.1.0"
}
```

## Prefix matching
<a name="string-prefix-matching"></a>

When a policy property includes the keyword `prefix`, it matches any message attribute or body property values that begin with the specified characters.

Consider the following policy property:

```
"customer_interests": [{"prefix": "bas"}]
```

It matches either of the following message attributes:

```
"customer_interests": {"Type": "String", "Value": "baseball"}
```

```
"customer_interests": {"Type": "String", "Value": "basketball"}
```

It also matches either of the following message bodies:

```
{
   "customer_interests": "baseball"
}
```

```
{
   "customer_interests": "basketball"
}
```

However, it doesn't match the following message attribute:

```
"customer_interests": {"Type": "String", "Value": "rugby"}
```

Nor does it match the following message body:

```
{
   "customer_interests": "rugby"
}
```

## Suffix matching
<a name="string-suffix-matching"></a>

When a policy property includes the keyword `suffix`, it matches any message attribute or body property values that end with the specified characters.

Consider the following policy property:

```
"customer_interests": [{"suffix": "ball"}]
```

It matches either of the following message attributes:

```
"customer_interests": {"Type": "String", "Value": "baseball"}
```

```
"customer_interests": {"Type": "String", "Value": "basketball"}
```

It also matches either of the following message bodies:

```
{
    "customer_interests": "baseball"
}
```

```
{
    "customer_interests": "basketball"
}
```

However, it doesn't match the following message attribute:

```
"customer_interests": {"Type": "String", "Value": "rugby"}
```

Nor does it match the following message body:

```
{
    "customer_interests": "rugby"
}
```

## Wildcard
<a name="string-value-wildcard"></a>

 You can use the wildcard character (\$1) to match string values in event patterns. 

The following policy uses the wildcard (\$1) character:

```
"customer_interests": [ { "wildcard": "*ball" } ]
```

It matches the following attributes:

```
{"customer_interests": ["baseball", "basketball"] }
```