Repository: aws-cloudformation/cfn-lint

Issue:
Duplicate properties on a resource can cause unhandled exceptions
*cfn-lint version: (`cfn-lint --version`)*
0.48.3

*Description of issue.*
Duplicate properties can cause unhandled exceptions

Please provide as much information as possible:
* Template linting issues:
  * Please provide a CloudFormation sample that generated the issue.
  * If present, please add links to the (official) documentation for clarification.
  * Validate if the issue still exists with the latest version of `cfn-lint` and/or the latest Spec files

e.g.
```yaml
  PublicHttpsListener:
    Type: 'AWS::ElasticLoadBalancingV2::Listener'
    Properties:
      LoadBalancerArn: !Ref PublicLoadBalancer
      Port: 443
      Protocol: HTTPS
      Certificates: !Ref LoadBalancerCertificateArn
      DefaultActions:
      - Type: fixed-response
        FixedResponseConfig:
          StatusCode: 404
      Port: 443
      Protocol: HTTPS
```
results in:
```bash
Traceback (most recent call last):
  File "/Users/nick.chadwick/Projects/msd/miniconda3/bin/cfn-lint", line 10, in <module>
    sys.exit(main())
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/cfnlint/__main__.py", line 28, in main
    (template, rules, errors) = cfnlint.core.get_template_rules(filename, args)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/cfnlint/core.py", line 187, in get_template_rules
    (template, errors) = cfnlint.decode.decode(filename)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/cfnlint/decode/__init__.py", line 28, in decode
    template = cfn_yaml.load(filename)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/cfnlint/decode/cfn_yaml.py", line 237, in load
    return loads(content, filename)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/cfnlint/decode/cfn_yaml.py", line 215, in loads
    template = loader.get_single_data()
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/yaml/constructor.py", line 51, in get_single_data
    return self.construct_document(node)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/yaml/constructor.py", line 55, in construct_document
    data = self.construct_object(node)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/yaml/constructor.py", line 100, in construct_object
    data = constructor(self, node)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/cfnlint/decode/cfn_yaml.py", line 81, in construct_yaml_map
    value = self.construct_object(value_node, False)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/yaml/constructor.py", line 100, in construct_object
    data = constructor(self, node)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/cfnlint/decode/cfn_yaml.py", line 81, in construct_yaml_map
    value = self.construct_object(value_node, False)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/yaml/constructor.py", line 100, in construct_object
    data = constructor(self, node)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/cfnlint/decode/cfn_yaml.py", line 81, in construct_yaml_map
    value = self.construct_object(value_node, False)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/yaml/constructor.py", line 100, in construct_object
    data = constructor(self, node)
  File "/Users/nick.chadwick/Projects/msd/miniconda3/lib/python3.7/site-packages/cfnlint/decode/cfn_yaml.py", line 98, in construct_yaml_map
    key, mapping[key].start_mark.line + 1),
AttributeError: 'int' object has no attribute 'start_mark'
```
* Feature request:
  * Please provide argumentation about the missing feature. Context is key!


Cfn-lint uses the [CloudFormation Resource Specifications](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html) as the base to do validation. These files are included as part of the application version. Please update to the latest version of `cfn-lint` or update the spec files manually (`cfn-lint -u`)



Discussion:
It's the duplicate Port property that causes the error.

On a related note, the duplicate Protocol property results in a slightly misleading output:

E0000 Duplicate resource found "Protocol" (line 440)
client-environment/client-keycloak-service.yaml:440:7

It's not a duplicate resource.

Resolving patch:
diff --git a/src/cfnlint/decode/cfn_yaml.py b/src/cfnlint/decode/cfn_yaml.py
--- a/src/cfnlint/decode/cfn_yaml.py
+++ b/src/cfnlint/decode/cfn_yaml.py
@@ -80,28 +80,29 @@ def construct_yaml_map(self, node):
             key = self.construct_object(key_node, False)
             value = self.construct_object(value_node, False)
 
-            if key in mapping:
-                raise CfnParseError(
-                    self.filename,
-                    [
-                        build_match(
-                            filename=self.filename,
-                            message='Duplicate resource found "{}" (line {})'.format(
-                                key, key_node.start_mark.line + 1),
-                            line_number=key_node.start_mark.line,
-                            column_number=key_node.start_mark.column,
-                            key=key
-                        ),
-                        build_match(
-                            filename=self.filename,
-                            message='Duplicate resource found "{}" (line {})'.format(
-                                key, mapping[key].start_mark.line + 1),
-                            line_number=mapping[key].start_mark.line,
-                            column_number=mapping[key].start_mark.column,
-                            key=key
-                        )
-                    ]
-                )
+            for key_dup in mapping:
+                if key_dup == key:
+                    raise CfnParseError(
+                        self.filename,
+                        [
+                            build_match(
+                                filename=self.filename,
+                                message='Duplicate resource found "{}" (line {})'.format(
+                                    key, key_dup.start_mark.line + 1),
+                                line_number=key_dup.start_mark.line,
+                                column_number=key_dup.start_mark.column,
+                                key=key
+                            ),
+                            build_match(
+                                filename=self.filename,
+                                message='Duplicate resource found "{}" (line {})'.format(
+                                    key, key_node.start_mark.line + 1),
+                                line_number=key_node.start_mark.line,
+                                column_number=key_node.start_mark.column,
+                                key=key
+                            ),
+                        ]
+                    )
             mapping[key] = value
 
         obj, = SafeConstructor.construct_yaml_map(self, node)


Test patch: