Repository: aws-cloudformation/cfn-lint

Issue:
Using If Condition for AWS::S3::Bucket ReplicationConfiguration property
*cfn-lint version: (`cfn-lint --version`)*
cfn-lint 0.34.0
```
E3002 Expecting an object at Resources/CloudAvailS3Bucket/Properties/ReplicationConfiguration/Fn::If/1
devops/infra/cloudavail.yaml:146:11

E3002 Expecting an object at Resources/CloudAvailS3Bucket/Properties/ReplicationConfiguration/Fn::If/2
```

```
    CloudAvailS3Bucket:
    Type: AWS::S3::Bucket
      ReplicationConfiguration: !If
        - S3ReplicationEnabled
        - - 
             Role: !GetAtt CloudAvailReplicationRole.Arn
             Rules: 
               - Destination: 
                      Bucket: arn:aws:s3:::cloudavail.replication.bucket
              Status: Enabled
        - - 
             !Ref "AWS::NoValue"
```



Discussion:

Resolving patch:
diff --git a/src/cfnlint/rules/__init__.py b/src/cfnlint/rules/__init__.py
--- a/src/cfnlint/rules/__init__.py
+++ b/src/cfnlint/rules/__init__.py
@@ -232,12 +232,30 @@ def resource_property(self, filename, cfn, path, properties, resource_type, prop
 
         if property_spec_name in property_spec:
             for rule in self.rules:
-                matches.extend(
-                    self.run_check(
-                        rule.matchall_resource_sub_properties, filename, rule.id,
-                        filename, cfn, properties, property_spec_name, path
+                if isinstance(properties, dict):
+                    if len(properties) == 1:
+                        for k, _ in properties.items():
+                            if k != 'Fn::If':
+                                matches.extend(
+                                    self.run_check(
+                                        rule.matchall_resource_sub_properties, filename, rule.id,
+                                        filename, cfn, properties, property_spec_name, path
+                                    )
+                                )
+                    else:
+                        matches.extend(
+                            self.run_check(
+                                rule.matchall_resource_sub_properties, filename, rule.id,
+                                filename, cfn, properties, property_spec_name, path
+                            )
+                        )
+                else:
+                    matches.extend(
+                        self.run_check(
+                            rule.matchall_resource_sub_properties, filename, rule.id,
+                            filename, cfn, properties, property_spec_name, path
+                        )
                     )
-                )
 
             resource_spec_properties = property_spec.get(property_spec_name, {}).get('Properties')
             if not resource_spec_properties:
@@ -259,10 +277,17 @@ def resource_property(self, filename, cfn, path, properties, resource_type, prop
                             if isinstance(resource_property_value, list):
                                 if len(resource_property_value) == 3:
                                     for index, c_value in enumerate(resource_property_value[1:]):
-                                        matches.extend(self.resource_property(
-                                            filename, cfn,
-                                            property_path[:] + [index + 1],
-                                            c_value, resource_type, property_type))
+                                        if isinstance(c_value, list):
+                                            for s_i, c_l_value in enumerate(c_value):
+                                                matches.extend(self.resource_property(
+                                                    filename, cfn,
+                                                    property_path[:] + [index + 1] + [s_i],
+                                                    c_l_value, resource_type, property_type))
+                                        else:
+                                            matches.extend(self.resource_property(
+                                                filename, cfn,
+                                                property_path[:] + [index + 1],
+                                                c_value, resource_type, property_type))
                         continue
                     if (resource_spec_property.get('Type') == 'List' and
                             not resource_spec_properties.get('PrimitiveItemType')):
diff --git a/src/cfnlint/rules/resources/properties/Properties.py b/src/cfnlint/rules/resources/properties/Properties.py
--- a/src/cfnlint/rules/resources/properties/Properties.py
+++ b/src/cfnlint/rules/resources/properties/Properties.py
@@ -245,9 +245,17 @@ def propertycheck(self, text, proptype, parenttype, resourcename, path, root):
                 if prop in cfnlint.helpers.CONDITION_FUNCTIONS and len_of_text == 1:
                     cond_values = self.cfn.get_condition_values(text[prop])
                     for cond_value in cond_values:
-                        matches.extend(self.propertycheck(
-                            cond_value['Value'], proptype, parenttype, resourcename,
-                            proppath + cond_value['Path'], root))
+                        if isinstance(cond_value['Value'], dict):
+                            matches.extend(self.propertycheck(
+                                cond_value['Value'], proptype, parenttype, resourcename,
+                                proppath + cond_value['Path'], root))
+                        elif isinstance(cond_value['Value'], list):
+                            for index, item in enumerate(cond_value['Value']):
+                                matches.extend(
+                                    self.propertycheck(
+                                        item, proptype, parenttype, resourcename,
+                                        proppath + cond_value['Path'] + [index], root)
+                                )
                 elif text.is_function_returning_object():
                     self.logger.debug('Ran into function "%s".  Skipping remaining checks', prop)
                 elif len(text) == 1 and prop in 'Ref' and text.get(prop) == 'AWS::NoValue':


Test patch:
diff --git a/test/fixtures/templates/good/resource_properties.yaml b/test/fixtures/templates/good/resource_properties.yaml
--- a/test/fixtures/templates/good/resource_properties.yaml
+++ b/test/fixtures/templates/good/resource_properties.yaml
@@ -312,6 +312,7 @@ Parameters:
     Type: "CommaDelimitedList"
     Default: "foo.com, bar.com"
 Conditions:
+  S3ReplicationEnabled: !Equals [!Ref 'AWS::Region', 'us-east']
   HasSingleClusterInstance: !Equals [!Ref 'AWS::Region', 'us-east-1']
   Conditions:
     ConditionTrue:
@@ -727,3 +728,15 @@ Resources:
           - Type: BASE_REF
             Pattern: ^refs/heads/master$
             ExcludeMatchedPattern: false
+  CloudAvailS3Bucket:
+    Type: AWS::S3::Bucket
+    Properties:
+      ReplicationConfiguration: !If
+        - S3ReplicationEnabled
+        - - Role: !GetAtt CloudAvailReplicationRole.Arn
+            Rules:
+            - Destination:
+                Bucket: arn:aws:s3:::cloudavail.replication.bucket
+              Status: Enabled
+            
+        - - !Ref "AWS::NoValue"