We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
E3001 Missing properties raised as an error when they're not required
*cfn-lint version: 0.4.2*

*Description of issue.*

An error about missing properties is not always useful. There are resources which don't necessarily need properties.

Please provide as much information as possible:
* Template linting issues:
```
    "WaitCondition": {
      "Type": "AWS::CloudFormation::WaitCondition",
      "CreationPolicy": {
        "ResourceSignal": {
          "Timeout": "PT15M",
          "Count": {
            "Ref": "TargetCapacity"
          }
        }
      }
    }
```
Getting `E3001 Properties not defined for resource WaitCondition`

* Feature request:

I'm not sure if there's a list of resources which don't need properties in many situations. S3 buckets and WaitCondition seem like good candidates for not raising this.
[AWS docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) say:
> Use the optional Parameters section to customize your templates.
so it doesn't sound like it needs to be provided.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/cfnlint/rules/resources/Configuration.py`
Content:
```
1 """
2   Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 
4   Permission is hereby granted, free of charge, to any person obtaining a copy of this
5   software and associated documentation files (the "Software"), to deal in the Software
6   without restriction, including without limitation the rights to use, copy, modify,
7   merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
8   permit persons to whom the Software is furnished to do so.
9 
10   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
11   INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
12   PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
13   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
14   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
15   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16 """
17 from cfnlint import CloudFormationLintRule
18 from cfnlint import RuleMatch
19 import cfnlint.helpers
20 
21 
22 class Configuration(CloudFormationLintRule):
23     """Check Base Resource Configuration"""
24     id = 'E3001'
25     shortdesc = 'Basic CloudFormation Resource Check'
26     description = 'Making sure the basic CloudFormation resources ' + \
27                   'are properly configured'
28     source_url = 'https://github.com/awslabs/cfn-python-lint'
29     tags = ['resources']
30 
31     def match(self, cfn):
32         """Check CloudFormation Resources"""
33 
34         matches = list()
35 
36         valid_attributes = [
37             'CreationPolicy',
38             'DeletionPolicy',
39             'DependsOn',
40             'Metadata',
41             'UpdatePolicy',
42             'Properties',
43             'Type',
44             'Condition'
45         ]
46 
47         valid_custom_attributes = [
48             'Version',
49             'Properties',
50             'DependsOn',
51             'Metadata',
52             'Condition',
53             'Type',
54         ]
55 
56         resources = cfn.template.get('Resources', {})
57         if not isinstance(resources, dict):
58             message = 'Resource not properly configured'
59             matches.append(RuleMatch(['Resources'], message))
60         else:
61             for resource_name, resource_values in cfn.template.get('Resources', {}).items():
62                 self.logger.debug('Validating resource %s base configuration', resource_name)
63                 if not isinstance(resource_values, dict):
64                     message = 'Resource not properly configured at {0}'
65                     matches.append(RuleMatch(
66                         ['Resources', resource_name],
67                         message.format(resource_name)
68                     ))
69                     continue
70                 resource_type = resource_values.get('Type', '')
71                 check_attributes = []
72                 if resource_type.startswith('Custom::') or resource_type == 'AWS::CloudFormation::CustomResource':
73                     check_attributes = valid_custom_attributes
74                 else:
75                     check_attributes = valid_attributes
76 
77                 for property_key, _ in resource_values.items():
78                     if property_key not in check_attributes:
79                         message = 'Invalid resource attribute {0} for resource {1}'
80                         matches.append(RuleMatch(
81                             ['Resources', resource_name, property_key],
82                             message.format(property_key, resource_name)))
83 
84                 resource_type = resource_values.get('Type', '')
85                 if not resource_type:
86                     message = 'Type not defined for resource {0}'
87                     matches.append(RuleMatch(
88                         ['Resources', resource_name],
89                         message.format(resource_name)
90                     ))
91                 else:
92                     self.logger.debug('Check resource types by region...')
93                     for region, specs in cfnlint.helpers.RESOURCE_SPECS.items():
94                         if region in cfn.regions:
95                             if resource_type not in specs['ResourceTypes']:
96                                 if not resource_type.startswith(('Custom::', 'AWS::Serverless::')):
97                                     message = 'Invalid or unsupported Type {0} for resource {1} in {2}'
98                                     matches.append(RuleMatch(
99                                         ['Resources', resource_name, 'Type'],
100                                         message.format(resource_type, resource_name, region)
101                                     ))
102 
103                 if 'Properties' not in resource_values:
104                     resource_spec = cfnlint.helpers.RESOURCE_SPECS['us-east-1']
105                     if resource_type in resource_spec['ResourceTypes']:
106                         properties_spec = resource_spec['ResourceTypes'][resource_type]['Properties']
107                         # pylint: disable=len-as-condition
108                         if len(properties_spec) > 0:
109                             required = 0
110                             for _, property_spec in properties_spec.items():
111                                 if property_spec.get('Required', False):
112                                     required += 1
113                             if required > 0:
114                                 message = 'Properties not defined for resource {0}'
115                                 matches.append(RuleMatch(
116                                     ['Resources', resource_name],
117                                     message.format(resource_name)
118                                 ))
119 
120         return matches
121
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/cfnlint/rules/resources/Configuration.py b/src/cfnlint/rules/resources/Configuration.py
--- a/src/cfnlint/rules/resources/Configuration.py
+++ b/src/cfnlint/rules/resources/Configuration.py
@@ -111,10 +111,13 @@
                                 if property_spec.get('Required', False):
                                     required += 1
                             if required > 0:
-                                message = 'Properties not defined for resource {0}'
-                                matches.append(RuleMatch(
-                                    ['Resources', resource_name],
-                                    message.format(resource_name)
-                                ))
+                                if resource_type == 'AWS::CloudFormation::WaitCondition' and 'CreationPolicy' in resource_values.keys():
+                                    self.logger.debug('Exception to required properties section as CreationPolicy is defined.')
+                                else:
+                                    message = 'Properties not defined for resource {0}'
+                                    matches.append(RuleMatch(
+                                        ['Resources', resource_name],
+                                        message.format(resource_name)
+                                    ))
 
         return matches

{"golden_diff": "diff --git a/src/cfnlint/rules/resources/Configuration.py b/src/cfnlint/rules/resources/Configuration.py\n--- a/src/cfnlint/rules/resources/Configuration.py\n+++ b/src/cfnlint/rules/resources/Configuration.py\n@@ -111,10 +111,13 @@\n                                 if property_spec.get('Required', False):\n                                     required += 1\n                             if required > 0:\n-                                message = 'Properties not defined for resource {0}'\n-                                matches.append(RuleMatch(\n-                                    ['Resources', resource_name],\n-                                    message.format(resource_name)\n-                                ))\n+                                if resource_type == 'AWS::CloudFormation::WaitCondition' and 'CreationPolicy' in resource_values.keys():\n+                                    self.logger.debug('Exception to required properties section as CreationPolicy is defined.')\n+                                else:\n+                                    message = 'Properties not defined for resource {0}'\n+                                    matches.append(RuleMatch(\n+                                        ['Resources', resource_name],\n+                                        message.format(resource_name)\n+                                    ))\n \n         return matches\n", "issue": "E3001 Missing properties raised as an error when they're not required\n*cfn-lint version: 0.4.2*\r\n\r\n*Description of issue.*\r\n\r\nAn error about missing properties is not always useful. There are resources which don't necessarily need properties.\r\n\r\nPlease provide as much information as possible:\r\n* Template linting issues:\r\n```\r\n    \"WaitCondition\": {\r\n      \"Type\": \"AWS::CloudFormation::WaitCondition\",\r\n      \"CreationPolicy\": {\r\n        \"ResourceSignal\": {\r\n          \"Timeout\": \"PT15M\",\r\n          \"Count\": {\r\n            \"Ref\": \"TargetCapacity\"\r\n          }\r\n        }\r\n      }\r\n    }\r\n```\r\nGetting `E3001 Properties not defined for resource WaitCondition`\r\n\r\n* Feature request:\r\n\r\nI'm not sure if there's a list of resources which don't need properties in many situations. S3 buckets and WaitCondition seem like good candidates for not raising this.\r\n[AWS docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) say:\r\n> Use the optional Parameters section to customize your templates.\r\nso it doesn't sound like it needs to be provided.\n", "before_files": [{"content": "\"\"\"\n  Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this\n  software and associated documentation files (the \"Software\"), to deal in the Software\n  without restriction, including without limitation the rights to use, copy, modify,\n  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n  permit persons to whom the Software is furnished to do so.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\n  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\"\"\"\nfrom cfnlint import CloudFormationLintRule\nfrom cfnlint import RuleMatch\nimport cfnlint.helpers\n\n\nclass Configuration(CloudFormationLintRule):\n    \"\"\"Check Base Resource Configuration\"\"\"\n    id = 'E3001'\n    shortdesc = 'Basic CloudFormation Resource Check'\n    description = 'Making sure the basic CloudFormation resources ' + \\\n                  'are properly configured'\n    source_url = 'https://github.com/awslabs/cfn-python-lint'\n    tags = ['resources']\n\n    def match(self, cfn):\n        \"\"\"Check CloudFormation Resources\"\"\"\n\n        matches = list()\n\n        valid_attributes = [\n            'CreationPolicy',\n            'DeletionPolicy',\n            'DependsOn',\n            'Metadata',\n            'UpdatePolicy',\n            'Properties',\n            'Type',\n            'Condition'\n        ]\n\n        valid_custom_attributes = [\n            'Version',\n            'Properties',\n            'DependsOn',\n            'Metadata',\n            'Condition',\n            'Type',\n        ]\n\n        resources = cfn.template.get('Resources', {})\n        if not isinstance(resources, dict):\n            message = 'Resource not properly configured'\n            matches.append(RuleMatch(['Resources'], message))\n        else:\n            for resource_name, resource_values in cfn.template.get('Resources', {}).items():\n                self.logger.debug('Validating resource %s base configuration', resource_name)\n                if not isinstance(resource_values, dict):\n                    message = 'Resource not properly configured at {0}'\n                    matches.append(RuleMatch(\n                        ['Resources', resource_name],\n                        message.format(resource_name)\n                    ))\n                    continue\n                resource_type = resource_values.get('Type', '')\n                check_attributes = []\n                if resource_type.startswith('Custom::') or resource_type == 'AWS::CloudFormation::CustomResource':\n                    check_attributes = valid_custom_attributes\n                else:\n                    check_attributes = valid_attributes\n\n                for property_key, _ in resource_values.items():\n                    if property_key not in check_attributes:\n                        message = 'Invalid resource attribute {0} for resource {1}'\n                        matches.append(RuleMatch(\n                            ['Resources', resource_name, property_key],\n                            message.format(property_key, resource_name)))\n\n                resource_type = resource_values.get('Type', '')\n                if not resource_type:\n                    message = 'Type not defined for resource {0}'\n                    matches.append(RuleMatch(\n                        ['Resources', resource_name],\n                        message.format(resource_name)\n                    ))\n                else:\n                    self.logger.debug('Check resource types by region...')\n                    for region, specs in cfnlint.helpers.RESOURCE_SPECS.items():\n                        if region in cfn.regions:\n                            if resource_type not in specs['ResourceTypes']:\n                                if not resource_type.startswith(('Custom::', 'AWS::Serverless::')):\n                                    message = 'Invalid or unsupported Type {0} for resource {1} in {2}'\n                                    matches.append(RuleMatch(\n                                        ['Resources', resource_name, 'Type'],\n                                        message.format(resource_type, resource_name, region)\n                                    ))\n\n                if 'Properties' not in resource_values:\n                    resource_spec = cfnlint.helpers.RESOURCE_SPECS['us-east-1']\n                    if resource_type in resource_spec['ResourceTypes']:\n                        properties_spec = resource_spec['ResourceTypes'][resource_type]['Properties']\n                        # pylint: disable=len-as-condition\n                        if len(properties_spec) > 0:\n                            required = 0\n                            for _, property_spec in properties_spec.items():\n                                if property_spec.get('Required', False):\n                                    required += 1\n                            if required > 0:\n                                message = 'Properties not defined for resource {0}'\n                                matches.append(RuleMatch(\n                                    ['Resources', resource_name],\n                                    message.format(resource_name)\n                                ))\n\n        return matches\n", "path": "src/cfnlint/rules/resources/Configuration.py"}], "after_files": [{"content": "\"\"\"\n  Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this\n  software and associated documentation files (the \"Software\"), to deal in the Software\n  without restriction, including without limitation the rights to use, copy, modify,\n  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n  permit persons to whom the Software is furnished to do so.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\n  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\"\"\"\nfrom cfnlint import CloudFormationLintRule\nfrom cfnlint import RuleMatch\nimport cfnlint.helpers\n\n\nclass Configuration(CloudFormationLintRule):\n    \"\"\"Check Base Resource Configuration\"\"\"\n    id = 'E3001'\n    shortdesc = 'Basic CloudFormation Resource Check'\n    description = 'Making sure the basic CloudFormation resources ' + \\\n                  'are properly configured'\n    source_url = 'https://github.com/awslabs/cfn-python-lint'\n    tags = ['resources']\n\n    def match(self, cfn):\n        \"\"\"Check CloudFormation Resources\"\"\"\n\n        matches = list()\n\n        valid_attributes = [\n            'CreationPolicy',\n            'DeletionPolicy',\n            'DependsOn',\n            'Metadata',\n            'UpdatePolicy',\n            'Properties',\n            'Type',\n            'Condition'\n        ]\n\n        valid_custom_attributes = [\n            'Version',\n            'Properties',\n            'DependsOn',\n            'Metadata',\n            'Condition',\n            'Type',\n        ]\n\n        resources = cfn.template.get('Resources', {})\n        if not isinstance(resources, dict):\n            message = 'Resource not properly configured'\n            matches.append(RuleMatch(['Resources'], message))\n        else:\n            for resource_name, resource_values in cfn.template.get('Resources', {}).items():\n                self.logger.debug('Validating resource %s base configuration', resource_name)\n                if not isinstance(resource_values, dict):\n                    message = 'Resource not properly configured at {0}'\n                    matches.append(RuleMatch(\n                        ['Resources', resource_name],\n                        message.format(resource_name)\n                    ))\n                    continue\n                resource_type = resource_values.get('Type', '')\n                check_attributes = []\n                if resource_type.startswith('Custom::') or resource_type == 'AWS::CloudFormation::CustomResource':\n                    check_attributes = valid_custom_attributes\n                else:\n                    check_attributes = valid_attributes\n\n                for property_key, _ in resource_values.items():\n                    if property_key not in check_attributes:\n                        message = 'Invalid resource attribute {0} for resource {1}'\n                        matches.append(RuleMatch(\n                            ['Resources', resource_name, property_key],\n                            message.format(property_key, resource_name)))\n\n                resource_type = resource_values.get('Type', '')\n                if not resource_type:\n                    message = 'Type not defined for resource {0}'\n                    matches.append(RuleMatch(\n                        ['Resources', resource_name],\n                        message.format(resource_name)\n                    ))\n                else:\n                    self.logger.debug('Check resource types by region...')\n                    for region, specs in cfnlint.helpers.RESOURCE_SPECS.items():\n                        if region in cfn.regions:\n                            if resource_type not in specs['ResourceTypes']:\n                                if not resource_type.startswith(('Custom::', 'AWS::Serverless::')):\n                                    message = 'Invalid or unsupported Type {0} for resource {1} in {2}'\n                                    matches.append(RuleMatch(\n                                        ['Resources', resource_name, 'Type'],\n                                        message.format(resource_type, resource_name, region)\n                                    ))\n\n                if 'Properties' not in resource_values:\n                    resource_spec = cfnlint.helpers.RESOURCE_SPECS['us-east-1']\n                    if resource_type in resource_spec['ResourceTypes']:\n                        properties_spec = resource_spec['ResourceTypes'][resource_type]['Properties']\n                        # pylint: disable=len-as-condition\n                        if len(properties_spec) > 0:\n                            required = 0\n                            for _, property_spec in properties_spec.items():\n                                if property_spec.get('Required', False):\n                                    required += 1\n                            if required > 0:\n                                if resource_type == 'AWS::CloudFormation::WaitCondition' and 'CreationPolicy' in resource_values.keys():\n                                    self.logger.debug('Exception to required properties section as CreationPolicy is defined.')\n                                else:\n                                    message = 'Properties not defined for resource {0}'\n                                    matches.append(RuleMatch(\n                                        ['Resources', resource_name],\n                                        message.format(resource_name)\n                                    ))\n\n        return matches\n", "path": "src/cfnlint/rules/resources/Configuration.py"}]}