forked from aws-cloudformation/cfn-lint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFindInMapKeys.py
90 lines (81 loc) · 3.92 KB
/
FindInMapKeys.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
81
82
83
84
85
86
87
88
89
90
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
from cfnlint.rules import CloudFormationLintRule
from cfnlint.rules import RuleMatch
class FindInMapKeys(CloudFormationLintRule):
"""Check if FindInMap values are correct"""
id = 'W1011'
shortdesc = 'FindInMap keys exist in the map'
description = (
'Checks the keys in a FindInMap to make sure they exist. '
'Check only if the Map Name is a string and if the key is a string.'
)
source_url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html'
tags = ['functions', 'findinmap']
def check_keys(self, map_name, keys, mappings, tree):
"""Check the validity of the first key"""
matches = []
first_key = keys[0]
second_key = keys[1]
if isinstance(second_key, (str, int)):
if isinstance(map_name, (str)):
mapping = mappings.get(map_name)
if mapping:
if isinstance(first_key, (str, int)):
if isinstance(map_name, (str)):
if mapping.get(first_key) is None:
message = 'FindInMap first key "{0}" doesn\'t exist in map "{1}" at {3}'
matches.append(
RuleMatch(
tree[:] + [1],
message.format(
first_key,
map_name,
first_key,
'/'.join(map(str, tree)),
),
)
)
if mapping.get(first_key):
# Don't double error if they first key doesn't exist
if mapping.get(first_key, {}).get(second_key) is None:
message = 'FindInMap second key "{0}" doesn\'t exist in map "{1}" under "{2}" at {3}'
matches.append(
RuleMatch(
tree[:] + [2],
message.format(
second_key,
map_name,
first_key,
'/'.join(map(str, tree)),
),
)
)
else:
for key, value in mapping.items():
if value.get(second_key) is None:
message = 'FindInMap second key "{0}" doesn\'t exist in map "{1}" under "{2}" at {3}'
matches.append(
RuleMatch(
tree[:] + [2],
message.format(
second_key,
map_name,
key,
'/'.join(map(str, tree)),
),
)
)
return matches
def match(self, cfn):
matches = []
findinmaps = cfn.search_deep_keys('Fn::FindInMap')
mappings = cfn.get_mappings()
for findinmap in findinmaps:
tree = findinmap[:-1]
map_obj = findinmap[-1]
if len(map_obj) == 3:
matches.extend(self.check_keys(map_obj[0], map_obj[1:], mappings, tree))
return matches