diff --git a/src/cfnlint/rules/resources/properties/Properties.py b/src/cfnlint/rules/resources/properties/Properties.py index c930e400fe..40c8994964 100644 --- a/src/cfnlint/rules/resources/properties/Properties.py +++ b/src/cfnlint/rules/resources/properties/Properties.py @@ -493,6 +493,26 @@ def propertycheck(self, text, proptype, parenttype, resourcename, path, root): message.format(prop, resourcename), ) ) + elif "Fn::GetAtt" in text[prop]: + getatt = text[prop]["Fn::GetAtt"] + if isinstance(getatt, str): + getatt = getatt.split(".", 1) + valid_getatts = self.cfn.get_valid_getatts() + if getatt[0] in valid_getatts: + if getatt[1] in valid_getatts[getatt[0]]: + getatt_prop = valid_getatts[getatt[0]][ + getatt[1] + ] + if getatt_prop.get("Type") != "List": + message = "Property {0} should be of type List for resource {1}" + matches.append( + RuleMatch( + proppath, + message.format( + prop, resourcename + ), + ) + ) else: if len(text[prop]) == 1: for k in text[prop].keys(): diff --git a/src/cfnlint/template/template.py b/src/cfnlint/template/template.py index cae26fd011..3f102220b5 100644 --- a/src/cfnlint/template/template.py +++ b/src/cfnlint/template/template.py @@ -423,16 +423,10 @@ def build_output_string(resource_type, property_name): valtype = value["Type"] if isinstance(valtype, str): if valtype.startswith(astrik_string_types): - LOGGER.debug( - "Cant build an appropriate getatt list from %s", valtype - ) results[name] = {"*": {"PrimitiveItemType": "String"}} elif valtype.startswith(astrik_unknown_types) or valtype.endswith( "::MODULE" ): - LOGGER.debug( - "Cant build an appropriate getatt list from %s", valtype - ) results[name] = {"*": {}} else: if value["Type"] in resourcetypes: diff --git a/test/fixtures/templates/bad/object_should_be_list.yaml b/test/fixtures/templates/bad/object_should_be_list.yaml index cd07443472..9fe714041d 100644 --- a/test/fixtures/templates/bad/object_should_be_list.yaml +++ b/test/fixtures/templates/bad/object_should_be_list.yaml @@ -677,3 +677,19 @@ Resources: - - AttributeName: !Ref PartitionKeyName KeyType: HASH - "String2" + EC2Instance: + Type: AWS::EC2::Instance + Properties: + InstanceType: t2.micro + ImageId: XXXXXXXXXXXXXXXXXXXXX + Tags: + - Key: Name + Value: !Ref AWS::StackName + SSMAssociation: + Type: AWS::SSM::Association + Properties: + Name: "SSM Document Name" + ScheduleExpression: rate(2 days) + Targets: + - Key: InstanceIds + Values: !GetAtt EC2Instance.InstanceId diff --git a/test/unit/rules/resources/properties/test_properties.py b/test/unit/rules/resources/properties/test_properties.py index b06c6bd556..7a88f4916f 100644 --- a/test/unit/rules/resources/properties/test_properties.py +++ b/test/unit/rules/resources/properties/test_properties.py @@ -37,7 +37,7 @@ def test_file_negative(self): def test_file_negative_2(self): """Failure test""" self.helper_file_negative( - "test/fixtures/templates/bad/object_should_be_list.yaml", 4 + "test/fixtures/templates/bad/object_should_be_list.yaml", 5 ) def test_file_negative_3(self):