Skip to content

Commit 695e607

Browse files
authored
Add new rules for SQS queue (#3952)
1 parent 53ac0a5 commit 695e607

File tree

11 files changed

+534
-4
lines changed

11 files changed

+534
-4
lines changed

src/cfnlint/data/schemas/extensions/aws_sqs_queue/__init__.py

Whitespace-only changes.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"allOf": [
3+
{
4+
"if": {
5+
"properties": {
6+
"FifoQueue": {
7+
"enum": [
8+
true,
9+
"true"
10+
]
11+
}
12+
},
13+
"required": [
14+
"FifoQueue"
15+
]
16+
},
17+
"then": {
18+
"if": {
19+
"properties": {
20+
"QueueName": {
21+
"type": "string"
22+
}
23+
},
24+
"required": [
25+
"QueueName"
26+
]
27+
},
28+
"then": {
29+
"properties": {
30+
"QueueName": {
31+
"pattern": "^.*\\.fifo$"
32+
}
33+
}
34+
}
35+
}
36+
},
37+
{
38+
"if": {
39+
"properties": {
40+
"FifoQueue": {
41+
"enum": [
42+
false,
43+
"false"
44+
]
45+
}
46+
}
47+
},
48+
"then": {
49+
"properties": {
50+
"ContentBasedDeduplication": false,
51+
"DeduplicationScope": false,
52+
"FifoThroughputLimit": false
53+
}
54+
}
55+
}
56+
]
57+
}

src/cfnlint/data/schemas/patches/providers/all/aws_sqs_queue/__init__.py

Whitespace-only changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[
2+
{
3+
"op": "add",
4+
"path": "/properties/RedrivePolicy/additionalProperties",
5+
"value": false
6+
},
7+
{
8+
"op": "add",
9+
"path": "/properties/RedrivePolicy/properties",
10+
"value": {
11+
"deadLetterTargetArn": {
12+
"type": "string"
13+
},
14+
"maxReceiveCount": {
15+
"type": "integer"
16+
}
17+
}
18+
}
19+
]

src/cfnlint/data/schemas/providers/us_east_1/aws-sqs-queue.json

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,16 @@
8282
]
8383
},
8484
"RedrivePolicy": {
85-
"type": [
86-
"object",
87-
"string"
88-
]
85+
"additionalProperties": false,
86+
"properties": {
87+
"deadLetterTargetArn": {
88+
"type": "string"
89+
},
90+
"maxReceiveCount": {
91+
"type": "integer"
92+
}
93+
},
94+
"type": "object"
8995
},
9096
"SqsManagedSseEnabled": {
9197
"type": "boolean"
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from __future__ import annotations
7+
8+
from collections import deque
9+
from typing import Any, Iterator
10+
11+
import cfnlint.data.schemas.extensions.aws_sqs_queue
12+
from cfnlint.helpers import bool_compare, is_function
13+
from cfnlint.jsonschema import ValidationError, ValidationResult, Validator
14+
from cfnlint.rules.helpers import get_value_from_path
15+
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema, SchemaDetails
16+
17+
18+
class QueueDLQ(CfnLintJsonSchema):
19+
id = "E3502"
20+
shortdesc = "Validate SQS DLQ queues are the same type"
21+
description = (
22+
"SQS queues using DLQ have to have the destination "
23+
"queue as the same type (FIFO or standard)"
24+
)
25+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html"
26+
tags = ["resources", "sqs"]
27+
28+
def __init__(self) -> None:
29+
super().__init__(
30+
keywords=[
31+
"Resources/AWS::SQS::Queue/Properties",
32+
],
33+
schema_details=SchemaDetails(
34+
module=cfnlint.data.schemas.extensions.aws_sqs_queue,
35+
filename="properties.json",
36+
),
37+
all_matches=True,
38+
)
39+
40+
def _is_fifo_queue(
41+
self, validator: Validator, instance: Any
42+
) -> Iterator[tuple[str, Validator]]:
43+
standard = "standard"
44+
fifo = "FIFO"
45+
46+
if "FifoQueue" not in instance:
47+
yield standard, validator
48+
return
49+
50+
for queue_type, queue_type_validator in get_value_from_path(
51+
validator=validator, instance=instance, path=deque(["FifoQueue"])
52+
):
53+
yield (
54+
fifo if bool_compare(queue_type, True) else standard
55+
), queue_type_validator
56+
57+
def validate(
58+
self, validator: Validator, _: Any, instance: Any, schema: dict[str, Any]
59+
) -> ValidationResult:
60+
61+
for queue_type, queue_type_validator in self._is_fifo_queue(
62+
validator=validator,
63+
instance=instance,
64+
):
65+
queue_type_validator = queue_type_validator.evolve(
66+
context=queue_type_validator.context.evolve(
67+
path=validator.context.path.evolve()
68+
)
69+
)
70+
71+
for target, target_validator in get_value_from_path(
72+
queue_type_validator,
73+
instance,
74+
path=deque(["RedrivePolicy", "deadLetterTargetArn"]),
75+
):
76+
k, v = is_function(target)
77+
if k != "Fn::GetAtt":
78+
return
79+
80+
if target_validator.is_type(v, "string"):
81+
v = v.split(".")
82+
83+
if len(v) < 1:
84+
return
85+
86+
dest_queue = validator.cfn.template.get("Resources", {}).get(v[0], {})
87+
88+
if dest_queue.get("Type") != "AWS::SQS::Queue":
89+
return
90+
91+
for dest_queue_type, _ in self._is_fifo_queue(
92+
target_validator,
93+
instance=dest_queue.get("Properties", {}),
94+
):
95+
if queue_type != dest_queue_type:
96+
yield ValidationError(
97+
(
98+
f"Source queue type {queue_type!r} does not "
99+
f"match destination queue type {dest_queue_type!r}"
100+
),
101+
rule=self,
102+
path=target_validator.context.path.path,
103+
)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from typing import Any
7+
8+
import cfnlint.data.schemas.extensions.aws_sqs_queue
9+
from cfnlint.jsonschema import ValidationResult, Validator
10+
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema, SchemaDetails
11+
12+
13+
class QueueProperties(CfnLintJsonSchema):
14+
id = "E3501"
15+
shortdesc = "Validate SQS queue properties are valid"
16+
description = (
17+
"Depending on if the queue is FIFO or not the "
18+
"properties and allowed values change. "
19+
"This rule validates properties and values based on the queue type."
20+
)
21+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html"
22+
tags = ["resources", "sqs"]
23+
24+
def __init__(self) -> None:
25+
super().__init__(
26+
keywords=[
27+
"Resources/AWS::SQS::Queue/Properties",
28+
],
29+
schema_details=SchemaDetails(
30+
module=cfnlint.data.schemas.extensions.aws_sqs_queue,
31+
filename="properties.json",
32+
),
33+
all_matches=True,
34+
)
35+
36+
def validate(
37+
self, validator: Validator, keywords: Any, instance: Any, schema: Any
38+
) -> ValidationResult:
39+
for err in super().validate(validator, keywords, instance, schema):
40+
if err.schema is False:
41+
err.message = (
42+
f"Additional properties are not allowed ({err.path[-1]!r} "
43+
"was unexpected)"
44+
)
45+
46+
yield err

src/cfnlint/rules/resources/sqs/__init__.py

Whitespace-only changes.

test/unit/rules/resources/sqs/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)