Skip to content

Commit 81d9fb0

Browse files
authored
EventBridge: fix empty conditions in event rule engine (#12154)
1 parent ed8c76e commit 81d9fb0

13 files changed

+541
-247
lines changed

localstack-core/localstack/services/events/event_rule_engine.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,15 @@ def _evaluate_condition(self, value, condition, field_exists: bool):
6666
# if must_exists is True then field_exists must be True
6767
# if must_exists is False then fields_exists must be False
6868
return must_exist == field_exists
69-
elif anything_but := condition.get("anything-but"):
69+
elif (anything_but := condition.get("anything-but")) is not None:
7070
if isinstance(anything_but, dict):
71-
if not_condition := anything_but.get("prefix"):
71+
if (not_condition := anything_but.get("prefix")) is not None:
7272
predicate = self._evaluate_prefix
73-
elif not_condition := anything_but.get("suffix"):
73+
elif (not_condition := anything_but.get("suffix")) is not None:
7474
predicate = self._evaluate_suffix
75-
elif not_condition := anything_but.get("equals-ignore-case"):
75+
elif (not_condition := anything_but.get("equals-ignore-case")) is not None:
7676
predicate = self._evaluate_equal_ignore_case
77-
elif not_condition := anything_but.get("wildcard"):
77+
elif (not_condition := anything_but.get("wildcard")) is not None:
7878
predicate = self._evaluate_wildcard
7979
else:
8080
# this should not happen as we validate the EventPattern before
@@ -97,7 +97,7 @@ def _evaluate_condition(self, value, condition, field_exists: bool):
9797
return False
9898
elif (prefix := condition.get("prefix")) is not None:
9999
if isinstance(prefix, dict):
100-
if prefix_equal_ignore_case := prefix.get("equals-ignore-case"):
100+
if (prefix_equal_ignore_case := prefix.get("equals-ignore-case")) is not None:
101101
return self._evaluate_prefix(prefix_equal_ignore_case.lower(), value.lower())
102102
else:
103103
return self._evaluate_prefix(prefix, value)
@@ -109,15 +109,18 @@ def _evaluate_condition(self, value, condition, field_exists: bool):
109109
else:
110110
return self._evaluate_suffix(suffix, value)
111111

112-
elif equal_ignore_case := condition.get("equals-ignore-case"):
112+
elif (equal_ignore_case := condition.get("equals-ignore-case")) is not None:
113113
return self._evaluate_equal_ignore_case(equal_ignore_case, value)
114+
115+
# we validated that `numeric` should be a non-empty list when creating the rule, we don't need the None check
114116
elif numeric_condition := condition.get("numeric"):
115117
return self._evaluate_numeric_condition(numeric_condition, value)
116118

119+
# we also validated the `cidr` that it cannot be empty
117120
elif cidr := condition.get("cidr"):
118121
return self._evaluate_cidr(cidr, value)
119122

120-
elif wildcard := condition.get("wildcard"):
123+
elif (wildcard := condition.get("wildcard")) is not None:
121124
return self._evaluate_wildcard(wildcard, value)
122125

123126
return False
@@ -147,7 +150,7 @@ def _evaluate_wildcard(condition: str, value: str) -> bool:
147150
return re.match(re.escape(condition).replace("\\*", ".+") + "$", value)
148151

149152
@staticmethod
150-
def _evaluate_numeric_condition(conditions, value) -> bool:
153+
def _evaluate_numeric_condition(conditions: list, value: t.Any) -> bool:
151154
if not isinstance(value, (int, float)):
152155
return False
153156
try:
@@ -408,6 +411,10 @@ def _validate_rule(self, rule: t.Any, from_: str | None = None) -> None:
408411
raise InvalidEventPatternException(
409412
f"{self.error_prefix}prefix/suffix match pattern must be a string"
410413
)
414+
elif not value:
415+
raise InvalidEventPatternException(
416+
f"{self.error_prefix}Null prefix/suffix not allowed"
417+
)
411418

412419
elif isinstance(value, dict):
413420
for inner_operator in value.keys():
@@ -489,6 +496,10 @@ def _validate_rule(self, rule: t.Any, from_: str | None = None) -> None:
489496
)
490497

491498
def _validate_numeric_condition(self, value):
499+
if not isinstance(value, list):
500+
raise InvalidEventPatternException(
501+
f"{self.error_prefix}Value of numeric must be an array."
502+
)
492503
if not value:
493504
raise InvalidEventPatternException(
494505
f"{self.error_prefix}Invalid member in numeric match: ]"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Based on https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-anything-but
2+
{
3+
"Event": {
4+
"id": "1",
5+
"source": "test-source",
6+
"detail-type": "test-detail-type",
7+
"account": "123456789012",
8+
"region": "us-east-2",
9+
"time": "2022-07-13T13:48:01Z",
10+
"detail": {
11+
"x-limit": 789
12+
}
13+
},
14+
"EventPattern": {
15+
"detail": {
16+
"x-limit": [ { "anything-but": 0 } ]
17+
}
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Based on https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-anything-but
2+
{
3+
"Event": {
4+
"id": "1",
5+
"source": "test-source",
6+
"detail-type": "test-detail-type",
7+
"account": "123456789012",
8+
"region": "us-east-2",
9+
"time": "2022-07-13T13:48:01Z",
10+
"detail": {
11+
"FileName": "file.txt.bak"
12+
}
13+
},
14+
"EventPattern": {
15+
"detail": {
16+
"FileName": [ { "anything-but": { "prefix": "" } } ]
17+
}
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Based on https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-anything-but
2+
{
3+
"Event": {
4+
"id": "1",
5+
"source": "test-source",
6+
"detail-type": "test-detail-type",
7+
"account": "123456789012",
8+
"region": "us-east-2",
9+
"time": "2022-07-13T13:48:01Z",
10+
"detail": {
11+
"FileName": "file.txt.bak"
12+
}
13+
},
14+
"EventPattern": {
15+
"detail": {
16+
"FileName": [ { "anything-but": { "suffix": "" } } ]
17+
}
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Based on https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-anything-but
2+
{
3+
"Event": {
4+
"id": "1",
5+
"source": "test-source",
6+
"detail-type": "test-detail-type",
7+
"account": "123456789012",
8+
"region": "us-east-2",
9+
"time": "2022-07-13T13:48:01Z",
10+
"detail": {
11+
"FilePath": "dir/init/file"
12+
}
13+
},
14+
"EventPattern": {
15+
"detail": {
16+
"FilePath": [ { "anything-but": { "wildcard": "" } } ]
17+
}
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Based on https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-equals-ignore-case-matching
2+
{
3+
"Event": {
4+
"id": "1",
5+
"source": "test-source",
6+
"detail-type": "random-value",
7+
"account": "123456789012",
8+
"region": "us-east-2",
9+
"time": "2022-07-13T13:48:01Z",
10+
"detail": {
11+
"value": ""
12+
}
13+
},
14+
"EventPattern": {
15+
"detail": {
16+
"value": [ { "equals-ignore-case": "" } ]
17+
}
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Based on https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-equals-ignore-case-matching
2+
{
3+
"Event": {
4+
"id": "1",
5+
"source": "test-source",
6+
"detail-type": "random-value",
7+
"account": "123456789012",
8+
"region": "us-east-2",
9+
"time": "2022-07-13T13:48:01Z",
10+
"detail": {
11+
"value": "test-value"
12+
}
13+
},
14+
"EventPattern": {
15+
"detail": {
16+
"value": [ { "equals-ignore-case": "" } ]
17+
}
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Based on https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#filtering-numeric-matching
2+
{
3+
"Event": {
4+
"id": "1",
5+
"source": "test-source",
6+
"detail-type": "test-detail-type",
7+
"account": "123456789012",
8+
"region": "us-east-2",
9+
"time": "2022-07-13T13:48:01Z",
10+
"detail": {
11+
"c-count": 3,
12+
}
13+
},
14+
"EventPattern": {
15+
"detail": {
16+
"c-count": [ { "numeric": 10 } ],
17+
}
18+
}
19+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Based on https://stackoverflow.com/questions/62406933/aws-eventbridge-pattern-to-capture-all-events
2+
{
3+
"Event": {
4+
"id": "1",
5+
"source": "test-source",
6+
"detail-type": "test-detail-type",
7+
"account": "123456789012",
8+
"region": "us-east-2",
9+
"time": "2022-07-13T13:48:01Z",
10+
"detail": {
11+
"state": "pending"
12+
}
13+
},
14+
"EventPattern": {
15+
"source": [{"suffix": ""}]
16+
}
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Based on https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-wildcard-matching
2+
{
3+
"Event": {
4+
"id": "1",
5+
"source": "test-source",
6+
"detail-type": "test-detail-type",
7+
"account": "123456789012",
8+
"region": "us-east-2",
9+
"time": "2022-07-13T13:48:01Z",
10+
"EventBusArn": "arn:aws:events:us-east-1:123456789012:event-bus/myEventBus"
11+
},
12+
"EventPattern": {
13+
"EventBusArn": [ { "wildcard": "" } ]
14+
}
15+
}

0 commit comments

Comments
 (0)