Repository: aws-cloudformation/cfn-lint

Issue:
E3002, E3003, E3012 - AWS::SSM::MaintenanceWindowTarget errors
cfn-lint version: 0.19.1

cfn-lint -u has been run

I am unable to to get a clean lint on a SSM template file that seems alright and that has loaded properly in AWS.  Would really appreciate any assistance. 

The documentation is here on MaintenanceWindowTarget:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-maintenancewindowtarget.html

And the associated targets:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-maintenancewindowtarget-targets.html

The below cf should be syntactically correct..... 

```
  BaselinePatchDailySSMMaintenanceWindowTarget:
    Type: AWS::SSM::MaintenanceWindowTarget
    Properties:
      Name: BaselinePatchDailyTarget
      Description: Systems with Tag Key=Patch,Value=Daily.
      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
      ResourceType: INSTANCE
      Targets:
      - Key: tag:Patch
        Values:
        - Daily
        - daily
```
Results in the following cfn-lint errors:

```
E0002 Unknown exception while processing rule E3002: 'AWS::SSM::MaintenanceWindowTarget.Target'
BaselineSSMConfig.yaml:1:1

E0002 Unknown exception while processing rule E3003: 'AWS::SSM::MaintenanceWindowTarget.Target'
BaselineSSMConfig.yaml:1:1

E3012 Property Resources/BaselinePatchDailySSMMaintenanceWindowTarget/Properties/Targets/0 should be of type String
BaselineSSMConfig.yaml:292:9
```
Edited file as follows to attempt to make target a string:

```
  BaselinePatchDailySSMMaintenanceWindowTarget:
    Type: AWS::SSM::MaintenanceWindowTarget
    Properties:
      Name: BaselinePatchDailyTarget
      Description: Systems with Tag Key=Patch,Value=Daily.
      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
      ResourceType: INSTANCE
      Targets: Key=tag:Patch,Values=Daily,daily
```
Results in the following cfn-lint error:

```
E3002 Property Targets should be of type List for resource BaselinePatchDailySSMMaintenanceWindowTarget
BaselineSSMConfig.yaml:291:7
```
Attempting to make the string a list:
```
  BaselinePatchDailySSMMaintenanceWindowTarget:
    Type: AWS::SSM::MaintenanceWindowTarget
    Properties:
      Name: BaselinePatchDailyTarget
      Description: Systems with Tag Key=Patch,Value=Daily.
      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
      ResourceType: INSTANCE
      Targets:
      - Key=tag:Patch,Values=Daily,daily
```
Results in the following errors:
```
E0002 Unknown exception while processing rule E3002: 'AWS::SSM::MaintenanceWindowTarget.Target'
BaselineSSMConfig.yaml:1:1

E0002 Unknown exception while processing rule E3003: 'AWS::SSM::MaintenanceWindowTarget.Target'
BaselineSSMConfig.yaml:1:1
```

Thanks!




Discussion:
cfn-lint version: 0.20.1

cfn-lint -u has run

I updated to the newest patch and a slightly different set of errors are happening.  They are now E3002, and E3012.

The original cf that should be correct:

```
  BaselinePatchDailySSMMaintenanceWindowTarget:
    Type: AWS::SSM::MaintenanceWindowTarget
    Properties:
      Name: BaselinePatchDailyTarget
      Description: Systems with Tag Key=Patch,Value=Daily.
      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
      ResourceType: INSTANCE
      Targets:
      - Key: tag:Patch
        Values:
        - Daily
        - daily
```
Still has one of the errors from before:
```
E3012 Property Resources/BaselinePatchDailySSMMaintenanceWindowTarget/Properties/Targets/0 should be of type String
BaselineSSMConfig.yaml:292:9
```
Changing that line to a string format as it asks:
```
  BaselinePatchDailySSMMaintenanceWindowTarget:
    Type: AWS::SSM::MaintenanceWindowTarget
    Properties:
      Name: BaselinePatchDailyTarget
      Description: Systems with Tag Key=Patch,Value=Daily.
      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
      ResourceType: INSTANCE
      Targets: Key=tag:Patch,Values=Daily,daily
```
Leads to the same error as before:
```
E3002 Property Targets should be of type List for resource BaselinePatchDailySSMMaintenanceWindowTarget
BaselineSSMConfig.yaml:295:7
```
Note it was a list originally.  Changing the string to a list:
```
  BaselinePatchDailySSMMaintenanceWindowTarget:
    Type: AWS::SSM::MaintenanceWindowTarget
    Properties:
      Name: BaselinePatchDailyTarget
      Description: Systems with Tag Key=Patch,Value=Daily.
      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
      ResourceType: INSTANCE
      Targets:
      - Key=tag:Patch,Values=Daily,daily
```
Has the following different from before error:
```
E3002 Expecting an object at Resources/BaselinePatchDailySSMMaintenanceWindowTarget/Properties/Targets/0
BaselineSSMConfig.yaml:296:9
```
Looking into this.
ok, I think I got what my issues are.  It may take a day or two to get a fix fully in if I don't run into anything major.  They did something new in the specs that we hadn't accounted for.
Thanks for your help!
I'm sure you tried a few of these options too (against CloudFormation)
This works.
```
Targets:
      - Key: tag:Patch
        Values:
        - Daily
        - daily
```

This does not even though the documentation says it should
```
Targets:
      - Key=tag:Patch,Values=Daily,daily
```

Hmm.  Both of those are coming up with the same errors as earlier for me.  The first one that you mention as working is erroring for me:
```
E3012 Property Resources/BaselinePatchDailySSMMaintenanceWindowTarget/Properties/Targets/0 should be of type String
BaselineSSMConfig.yaml:292:9
```
Second one is still:
```
E3002 Expecting an object at Resources/BaselinePatchDailySSMMaintenanceWindowTarget/Properties/Targets/0
BaselineSSMConfig.yaml:292:9
```
I haven't been able to get any clean runs.  Just uninstalled the module and resinstalled in case there was some leftover cruft as well.

Resolving patch:
diff --git a/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py b/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py
--- a/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py
+++ b/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py
@@ -138,6 +138,10 @@ def check_value(self, value, path, **kwargs):
                     if not isinstance(map_value, dict):
                         matches.extend(self.check_primitive_type(map_value, primitive_type, path + [map_key]))
         else:
+            # some properties support primitive types and objects
+            # skip in the case it could be an object and the value is a object
+            if item_type and isinstance(value, dict):
+                return matches
             matches.extend(self.check_primitive_type(value, primitive_type, path))
 
         return matches


Test patch:
diff --git a/test/fixtures/templates/good/resources/properties/primitive_types.yaml b/test/fixtures/templates/good/resources/properties/primitive_types.yaml
new file mode 100644
--- /dev/null
+++ b/test/fixtures/templates/good/resources/properties/primitive_types.yaml
@@ -0,0 +1,23 @@
+---
+AWSTemplateFormatVersion: "2010-09-09"
+Resources:
+  BaselinePatchDailySSMMaintenanceWindow:
+    Type: AWS::SSM::MaintenanceWindow
+    Properties:
+      Name: Test
+      Cutoff: 0
+      Schedule: 'rate(1 days)'
+      AllowUnassociatedTargets: false
+      Duration: 1
+  BaselinePatchDailySSMMaintenanceWindowTarget:
+    Type: AWS::SSM::MaintenanceWindowTarget
+    Properties:
+      Name: BaselinePatchDailyTarget
+      Description: Systems with Tag Key=Patch,Value=Daily.
+      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
+      ResourceType: INSTANCE
+      Targets:
+      - Key: tag:Patch
+        Values:
+        - Daily
+        - daily
diff --git a/test/rules/resources/properties/test_value_primitive_type.py b/test/rules/resources/properties/test_value_primitive_type.py
--- a/test/rules/resources/properties/test_value_primitive_type.py
+++ b/test/rules/resources/properties/test_value_primitive_type.py
@@ -28,6 +28,7 @@ def setUp(self):
     success_templates = [
         'test/fixtures/templates/good/generic.yaml',
         'test/fixtures/templates/good/resource_properties.yaml',
+        'test/fixtures/templates/good/resources/properties/primitive_types.yaml',
     ]
 
     def test_file_positive(self):