""" Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: MIT-0 """ import logging import cfnlint.helpers from cfnlint.rules import CloudFormationLintRule, RuleMatch LOGGER = logging.getLogger("cfnlint") class GetAtt(CloudFormationLintRule): """Check if GetAtt values are correct""" id = "E1010" shortdesc = "GetAtt validation of parameters" description = "Validates that GetAtt parameters are to valid resources and properties of those resources" source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html" tags = ["functions", "getatt"] def __init__(self): """Init""" super().__init__() self.propertytypes = [] self.resourcetypes = [] def initialize(self, cfn): resourcespecs = cfnlint.helpers.RESOURCE_SPECS[cfn.regions[0]] self.resourcetypes = resourcespecs["ResourceTypes"] self.propertytypes = resourcespecs["PropertyTypes"] def match(self, cfn): matches = [] getatts = cfn.search_deep_keys("Fn::GetAtt") valid_getatts = cfn.get_valid_getatts() valid_attribute_functions = ["Ref"] for getatt in getatts: if len(getatt[-1]) < 2: message = "Invalid GetAtt for {0}" matches.append( RuleMatch(getatt, message.format("/".join(map(str, getatt[:-1])))) ) continue if isinstance(getatt[-1], str): resname, restype = getatt[-1].split(".", 1) else: resname = None restype = None if isinstance(getatt[-1][1], str): resname = getatt[-1][0] restype = ".".join(getatt[-1][1:]) elif isinstance(getatt[-1][1], dict): # You can ref the secondary part of a getatt resname = getatt[-1][0] restype = getatt[-1][1] if len(restype) == 1: for k in restype.keys(): if k not in valid_attribute_functions: message = 'GetAtt only supports functions "{0}" for attributes at {1}' matches.append( RuleMatch( getatt, message.format( ", ".join( map(str, valid_attribute_functions) ), "/".join(map(str, getatt[:-1])), ), ) ) else: message = "Invalid GetAtt structure {0} at {1}" matches.append( RuleMatch( getatt, message.format( getatt[-1], "/".join(map(str, getatt[:-1])) ), ) ) # setting restype to None as we can't validate that anymore restype = None else: message = "Invalid GetAtt structure {0} at {1}" matches.append( RuleMatch( getatt, message.format(getatt[-1], "/".join(map(str, getatt[:-1]))), ) ) # only check resname if its set. if it isn't it is because of bad structure # and an error is already provided if resname: if resname in valid_getatts: if restype is not None: # Check for maps restypeparts = restype.split(".") if ( restypeparts[0] in valid_getatts[resname] and len(restypeparts) >= 2 ): if ( valid_getatts[resname][restypeparts[0]].get("Type") != "Map" ): message = "Invalid GetAtt {0}.{1} for resource {2}" matches.append( RuleMatch( getatt[:-1], message.format(resname, restype, getatt[1]), ) ) else: continue if ( restype not in valid_getatts[resname] and "*" not in valid_getatts[resname] ): message = "Invalid GetAtt {0}.{1} for resource {2}" matches.append( RuleMatch( getatt[:-1], message.format(resname, restype, getatt[1]), ) ) else: modules = cfn.get_modules() if any(resname.startswith(s) for s in modules.keys()): LOGGER.debug( "Will consider valid getatt %s because it references a resource within a module", resname, ) else: message = "Invalid GetAtt {0}.{1} for resource {2}" matches.append( RuleMatch( getatt, message.format(resname, restype, getatt[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 |
|