forked from aws-cloudformation/cfn-lint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RelationshipConditions.py
68 lines (61 loc) · 3 KB
/
RelationshipConditions.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
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
import six
from cfnlint.helpers import PSEUDOPARAMS
from cfnlint.rules import CloudFormationLintRule
from cfnlint.rules import RuleMatch
class RelationshipConditions(CloudFormationLintRule):
"""Check if Ref/GetAtt values are available via conditions"""
id = 'W1001'
shortdesc = 'Ref/GetAtt to resource that is available when conditions are applied'
description = 'Check the Conditions that affect a Ref/GetAtt to make sure ' \
'the resource being related to is available when there is a resource ' \
'condition.'
source_url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html'
tags = ['conditions', 'resources', 'relationships', 'ref', 'getatt']
def match(self, cfn):
"""Check CloudFormation Ref/GetAtt for Conditions"""
matches = []
# Start with Ref checks
ref_objs = cfn.search_deep_keys(searchText='Ref', includeGlobals=False)
for ref_obj in ref_objs:
value = ref_obj[-1]
if value not in PSEUDOPARAMS:
scenarios = cfn.is_resource_available(ref_obj, value)
for scenario in scenarios:
scenario_text = ' and '.join(
['when condition "%s" is %s' % (k, v) for (k, v) in scenario.items()])
message = 'Ref to resource "{0}" that may not be available {1} at {2}'
matches.append(
RuleMatch(
ref_obj[:-1],
message.format(
value,
scenario_text,
'/'.join(map(str, ref_obj[:-1])))))
# The do GetAtt
getatt_objs = cfn.search_deep_keys(searchText='Fn::GetAtt', includeGlobals=False)
for getatt_obj in getatt_objs:
value_obj = getatt_obj[-1]
value = None
if isinstance(value_obj, list):
value = value_obj[0]
elif isinstance(value_obj, six.string_types):
value = value_obj.split('.')[0]
if value:
if value not in PSEUDOPARAMS:
scenarios = cfn.is_resource_available(getatt_obj, value)
for scenario in scenarios:
scenario_text = ' and '.join(
['when condition "%s" is %s' % (k, v) for (k, v) in scenario.items()])
message = 'GetAtt to resource "{0}" that may not be available {1} at {2}'
matches.append(
RuleMatch(
getatt_obj[:-1],
message.format(
value,
scenario_text,
'/'.join(map(str, getatt_obj[:-1])))))
return matches