""" Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: MIT-0 """ from cfnlint.helpers import PSEUDOPARAMS from cfnlint.rules import CloudFormationLintRule, 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", "sub"] 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: # pylint: disable=consider-using-f-string 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, str): 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( [ f'when condition "{k}" is {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])), ), ) ) # The do Sub sub_objs = cfn.search_deep_keys(searchText="Fn::Sub", includeGlobals=False) for sub_obj in sub_objs: sub_string = sub_obj[-1] # Filter out bad types of sub_strings. # Lists have two be two items and it can be just a string if not isinstance(sub_string, (list, str)): continue if isinstance(sub_string, str): sub_string = [sub_string, {}] if len(sub_string) != 2: continue sub_params = sub_string[1] string_params = cfn.get_sub_parameters(sub_string[0]) for string_param in string_params: if string_param not in sub_params: # deal with GetAtts by dropping everything after the . string_param = string_param.split(".")[0] if string_param in cfn.template.get("Resources", {}): scenarios = cfn.is_resource_available( sub_obj[:-1], string_param ) for scenario in scenarios: scenario_text = " and ".join( [ f'when condition "{k}" is {v}' for (k, v) in scenario.items() ] ) message = 'Fn::Sub to resource "{0}" that may not be available {1} at {2}' matches.append( RuleMatch( sub_obj[:-1], message.format( string_param, scenario_text, "/".join(map(str, sub_obj[:-1])), ), ) ) return matches
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
__pycache__ | Folder | 0755 |
|
|
Base64.py | File | 1.72 KB | 0644 |
|
Cidr.py | File | 11.94 KB | 0644 |
|
DynamicReferenceSecureString.py | File | 5.72 KB | 0644 |
|
FindInMap.py | File | 11.25 KB | 0644 |
|
FindInMapKeys.py | File | 3.89 KB | 0644 |
|
GetAtt.py | File | 6.05 KB | 0644 |
|
GetAz.py | File | 2.76 KB | 0644 |
|
If.py | File | 1.45 KB | 0644 |
|
ImportValue.py | File | 2.45 KB | 0644 |
|
Join.py | File | 8.63 KB | 0644 |
|
Length.py | File | 3.31 KB | 0644 |
|
Not.py | File | 978 B | 0644 |
|
Ref.py | File | 1.02 KB | 0644 |
|
RefExist.py | File | 1.26 KB | 0644 |
|
RefInCondition.py | File | 1.36 KB | 0644 |
|
RelationshipConditions.py | File | 5.35 KB | 0644 |
|
Select.py | File | 4.41 KB | 0644 |
|
Split.py | File | 3.11 KB | 0644 |
|
Sub.py | File | 9.49 KB | 0644 |
|
SubNeeded.py | File | 5.48 KB | 0644 |
|
SubNotJoin.py | File | 2 KB | 0644 |
|
SubParametersUsed.py | File | 1.4 KB | 0644 |
|
SubUnneeded.py | File | 1.27 KB | 0644 |
|
ToJsonString.py | File | 1.75 KB | 0644 |
|
__init__.py | File | 106 B | 0644 |
|