forked from aws-cloudformation/cfn-lint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Modules.py
80 lines (66 loc) · 2.9 KB
/
Modules.py
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
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
from cfnlint._typing import RuleMatches
from cfnlint.rules import CloudFormationLintRule, RuleMatch
from cfnlint.template import Template
class Modules(CloudFormationLintRule):
"""Check that Modules do not contain invalid data"""
id = "E5001"
shortdesc = "Check that Modules resources are valid"
description = "Check that Modules resources are valid"
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/"
tags = ["resources", "modules"]
def match(self, cfn: Template) -> RuleMatches:
matches = []
resource_properties = cfn.get_resources()
resource_dict = {
key: resource_properties[key]
for key in resource_properties
if isinstance(resource_properties[key], dict)
}
for resource_name, resource_values in resource_dict.items():
module = {
"Type": v
for (k, v) in resource_values.items()
if str(v).endswith("::MODULE") is True
}
if module:
matches.extend(self.check_metadata_keys(cfn))
matches.extend(self.check_tags(resource_name, resource_values))
matches.extend(
self.check_policy("CreationPolicy", resource_name, resource_values)
)
matches.extend(
self.check_policy("UpdatePolicy", resource_name, resource_values)
)
return matches
def check_policy(self, policy, resource_name, resource_values):
"""Ensure invalid policies are not used"""
matches = []
if resource_values.get(policy, {}):
path = ["Resources", resource_name, policy]
matches.append(RuleMatch(path, f"{policy} is not permitted within Modules"))
return matches
def check_tags(self, resource_name, resource_values):
"""Ensure invalid policies are not used"""
matches = []
properties = resource_values.get("Properties", {})
if properties.get("Tags"):
path = ["Resources", resource_name, "Properties", "Tags"]
matches.append(RuleMatch(path, "Tags is not permitted within Modules"))
return matches
def check_metadata_keys(self, cfn):
"""Ensure reserved metadata key AWS::CloudFormation::Module is not used"""
modules = cfn.get_modules().keys()
matches = []
reserved_key = "AWS::CloudFormation::Module"
refs = cfn.search_deep_keys(reserved_key)
for ref in refs:
if (ref[1] in modules) and (len(ref) > 3):
if ref[0] == "Resources" and ref[2] == "Metadata":
matches.append(
RuleMatch(ref, f"The Metadata key {reserved_key} is reserved")
)
return matches