forked from aws-cloudformation/cfn-lint
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProperties.py
More file actions
135 lines (121 loc) · 4.77 KB
/
Properties.py
File metadata and controls
135 lines (121 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
import logging
from collections import deque
from typing import Any
from cfnlint.helpers import FUNCTIONS, is_function
from cfnlint.jsonschema import ValidationError, ValidationResult, Validator
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema
from cfnlint.schema.manager import PROVIDER_SCHEMA_MANAGER
LOGGER = logging.getLogger(__name__)
class Properties(CfnLintJsonSchema):
"""Check Base Resource Configuration"""
id = "E3002"
shortdesc = "Resource properties are invalid"
description = "Making sure that resources properties are properly configured"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#properties"
tags = ["resources"]
def __init__(self):
"""Init"""
super().__init__(
keywords=["Resources/*"],
all_matches=True,
)
self.rule_set = {
"additionalProperties": "E3002",
"anyOf": "E3017",
"properties": "E3002",
"dependentExcluded": "E3020",
"dependentRequired": "E3021",
"required": "E3003",
"requiredOr": "E3058",
"requiredXor": "E3014",
"enum": "E3030",
"enumCaseInsensitive": "E3030",
"type": "E3012",
"minLength": "E3033",
"maxLength": "E3033",
"uniqueItems": "E3037",
"maximum": "E3034",
"minimum": "E3034",
"exclusiveMaximum": "E3034",
"exclusiveMinimum": "E3034",
"maxItems": "E3032",
"minItems": "E3032",
"pattern": "E3031",
"prefixItems": "E3008",
"oneOf": "E3018",
"cfnLint": "E1101",
"tagging": "E3024",
}
self.child_rules = dict.fromkeys(list(self.rule_set.values()))
def validate(
self, validator: Validator, _, instance: Any, schema: Any
) -> ValidationResult:
if not validator.is_type(instance, "object"):
return
resolved_conditions = {}
if validator.is_type(instance.get("Condition"), "string"):
resolved_conditions = {instance.get("Condition"): True}
validator = validator.evolve(
context=validator.context.evolve(
functions=list(FUNCTIONS),
strict_types=False,
conditions=validator.context.conditions.evolve(
resolved_conditions,
),
),
function_filter=validator.function_filter.evolve(
add_cfn_lint_keyword=True,
),
)
t = instance.get("Type")
if not validator.is_type(t, "string"):
return
if "Properties" not in instance:
# assume properties is an empty object
# this helps with validating if the resource
# has required properties
properties = {}
else:
# covers if Properties is null
properties = instance.get("Properties")
# Properties needs to be an object
if not validator.is_type(properties, "object"):
yield ValidationError(
# Expected an object
message=f"{properties!r} is not of type object",
path=deque(["Properties"]),
rule=self.child_rules.get(self.rule_set.get("type")), # type: ignore
validator="type",
)
return
fn_k, fn_v = is_function(properties)
if fn_k == "Ref" and fn_v == "AWS::NoValue":
yield ValidationError(
# Expected an object, received {"Ref":"AWS::NoValue"}
message=f"{properties!r} is not of type object",
path=deque(["Properties", fn_k]),
rule=self.child_rules.get(self.rule_set.get("type")), # type: ignore
validator="type",
)
return
for regions, schema in PROVIDER_SCHEMA_MANAGER.get_resource_schemas_by_regions(
t, validator.context.regions
):
region_validator = validator.evolve(
context=validator.context.evolve(
regions=regions,
path=validator.context.path.evolve(
cfn_path=deque(["Resources", t, "Properties"]),
).descend(path="Properties"),
),
)
region_validator = self.extend_validator(
region_validator, schema.schema, region_validator.context.evolve()
)
for err in self._validate(region_validator, properties):
err.path.appendleft("Properties")
yield err