Repository: aws-cloudformation/cfn-lint

Issue:
E2532 - StateMachine Json not parsing when using multi param !Sub
**cfn-lint version:**
```
$ cfn-lint --version
cfn-lint 0.9.1
```
**Description of issue:**
When using `!Sub` with 2 parameters as defined [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) then cfn-lint chokes on the parameter being subbed in because technically this is not valid json. This is valid cloud formation though.
 
**Here is basic example showing issue:**
```yaml
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31

Parameters:
  TestParam:
    Type: String

Resources:

  StateMachine:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      StateMachineName: TestStatemachine
      RoleArn: arn:aws:iam::123456789012:role/test-role
      DefinitionString:
        !Sub
      - |
        {
          "StartAt": "FlowChoice",
          "States": {
            "FlowChoice": {
              "Type": "Choice",
              "Choices": [
                {
                  "Variable": "$.sleep",
                  "StringEquals": "true",
                  "Next": "Sleep"
                },
                {
                  "Variable": "$.sleep",
                  "StringEquals": "false",
                  "Next": "Stop"
                }
              ],
              "Default": "Stop"
            },
            "Sleep": {
              "Type": "Wait",
              "Seconds": ${TestParam},   # <--- Not handled!
              "Next": "Stop"
            },
            "Stop": {
              "Type": "Succeed"
            }
          }
        }
      - {TestParam: !Ref TestParam}
```



Discussion:
Agreed. Should be able to fix this quickly.  Thanks!

Resolving patch:
diff --git a/src/cfnlint/rules/resources/stepfunctions/StateMachine.py b/src/cfnlint/rules/resources/stepfunctions/StateMachine.py
--- a/src/cfnlint/rules/resources/stepfunctions/StateMachine.py
+++ b/src/cfnlint/rules/resources/stepfunctions/StateMachine.py
@@ -122,15 +122,19 @@ def _check_definition_json(self, def_json, path):
             matches.extend(self._check_state_json(state_value, state_name, path))
         return matches
 
-    def check_value(self, value, path):
+    def check_value(self, value, path, fail_on_loads=True):
         """Check Definition Value"""
         matches = []
         try:
             def_json = json.loads(value)
         # pylint: disable=W0703
         except Exception as err:
-            message = 'State Machine Definition needs to be formatted as JSON. Error %s' % err
-            matches.append(RuleMatch(path, message))
+            if fail_on_loads:
+                message = 'State Machine Definition needs to be formatted as JSON. Error %s' % err
+                matches.append(RuleMatch(path, message))
+                return matches
+
+            self.logger.debug('State Machine definition could not be parsed. Skipping')
             return matches
 
         matches.extend(self._check_definition_json(def_json, path))
@@ -140,9 +144,9 @@ def check_sub(self, value, path):
         """Check Sub Object"""
         matches = []
         if isinstance(value, list):
-            matches.extend(self.check_value(value[0], path))
+            matches.extend(self.check_value(value[0], path, False))
         elif isinstance(value, six.string_types):
-            matches.extend(self.check_value(value, path))
+            matches.extend(self.check_value(value, path, False))
 
         return matches
 


Test patch:
diff --git a/test/fixtures/templates/good/resources/stepfunctions/state_machine.yaml b/test/fixtures/templates/good/resources/stepfunctions/state_machine.yaml
--- a/test/fixtures/templates/good/resources/stepfunctions/state_machine.yaml
+++ b/test/fixtures/templates/good/resources/stepfunctions/state_machine.yaml
@@ -1,5 +1,8 @@
 AWSTemplateFormatVersion: '2010-09-09'
 Description: An example template for a Step Functions state machine.
+Parameters:
+  timeout:
+    Type: Number
 Resources:
   MyStateMachine:
     Type: AWS::StepFunctions::StateMachine
@@ -30,3 +33,41 @@ Resources:
           }
         }
       RoleArn: arn:aws:iam::111122223333:role/service-role/StatesExecutionRole-us-east-1
+  # doesn't fail on sub that can't be parsed
+  MyStateMachine2:
+    Type: AWS::StepFunctions::StateMachine
+    Properties:
+      StateMachineName: HelloWorld-StateMachine
+      DefinitionString:
+        Fn::Sub:
+        - |
+          {
+            "StartAt": "HelloWorld",
+            "States": {
+              "HelloWorld": {
+                "Type": "Task",
+                "Resource": "arn:aws:lambda:us-east-1:111122223333:function:HelloFunction",
+                "Next": "CreatePublishedRequest"
+              },
+              "CreatePublishedRequest": {
+                "Type": "Task",
+                "Resource": "{$createPublishedRequest}",
+                "ResultPath":"$.publishedRequest",
+                "OutputPath":"$.publishedRequest",
+                "Next": "PutRequest"
+              },
+              "Sleep": {
+                "Type": "Wait",
+                "Seconds": ${TestParam},
+                "Next": "Stop"
+              },
+              "PutRequest": {
+                "Type": "Task",
+                "Resource": "{$updateKey}",
+                "ResultPath":"$.response",
+                "End": true
+              }
+            }
+          }
+        - TestParam: !Ref timeout
+      RoleArn: arn:aws:iam::111122223333:role/service-role/StatesExecutionRole-us-east-1