Repository: aws-cloudformation/cfn-lint

Issue:
Alert when doing a split on a dynamic reference
You can dynamic reference a `StringList` but it is read in as a comma delimited singular string. [Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-ssm)

You cannot put it back into a list by doing `!Split [',', '{{resolve:ssm:/vpc/subnets/private}}']` because the split is done prior to the dynamic reference.  This will result in a singular string that is comma delimited. 

As a reference `!Split [':', '{{resolve:ssm:/vpc/subnets/private}}']` will split this string into a list of 3 strings.


Discussion:

Resolving patch:
diff --git a/src/cfnlint/helpers.py b/src/cfnlint/helpers.py
--- a/src/cfnlint/helpers.py
+++ b/src/cfnlint/helpers.py
@@ -77,9 +77,9 @@
     re.I | re.S,
 )
 REGEX_DYN_REF = re.compile(r"^.*{{resolve:.+}}.*$")
-REGEX_DYN_REF_SSM = re.compile(r"^.*{{resolve:ssm:[a-zA-Z0-9_\.\-/]+:\d+}}.*$")
+REGEX_DYN_REF_SSM = re.compile(r"^.*{{resolve:ssm:[a-zA-Z0-9_\.\-/]+(:\d+)?}}.*$")
 REGEX_DYN_REF_SSM_SECURE = re.compile(
-    r"^.*{{resolve:ssm-secure:[a-zA-Z0-9_\.\-/]+:\d+}}.*$"
+    r"^.*{{resolve:ssm-secure:[a-zA-Z0-9_\.\-/]+(:\d+)?}}.*$"
 )
 
 
diff --git a/src/cfnlint/rules/functions/Split.py b/src/cfnlint/rules/functions/Split.py
--- a/src/cfnlint/rules/functions/Split.py
+++ b/src/cfnlint/rules/functions/Split.py
@@ -2,6 +2,11 @@
 Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 SPDX-License-Identifier: MIT-0
 """
+import json
+
+import regex as re
+
+from cfnlint.helpers import REGEX_DYN_REF_SSM
 from cfnlint.rules import CloudFormationLintRule, RuleMatch
 
 
@@ -34,8 +39,19 @@ def _test_delimiter(self, delimiter, path):
             matches.append(RuleMatch(path, message.format("/".join(map(str, path)))))
         return matches
 
+    def _check_dyn_ref_value(self, value, path):
+        """Chec item type"""
+        matches = []
+        if isinstance(value, str):
+            if re.match(REGEX_DYN_REF_SSM, value):
+                message = f'Fn::Split does not support dynamic references at {"/".join(map(str, path[:]))}'
+                matches.append(RuleMatch(path[:], message))
+
+        return matches
+
     def _test_string(self, s, path):
         matches = []
+        matches.extend(self._check_dyn_ref_value(json.dumps(s), path[:]))
         if isinstance(s, dict):
             if len(s) == 1:
                 for key, _ in s.items():


Test patch:
diff --git a/test/fixtures/templates/bad/functions_split.yaml b/test/fixtures/templates/bad/functions_split.yaml
--- a/test/fixtures/templates/bad/functions_split.yaml
+++ b/test/fixtures/templates/bad/functions_split.yaml
@@ -31,3 +31,10 @@ Resources:
       AvailabilityZone: !Select
       - 0
       - Fn::Split: {Ref: AWS::Region}
+  myInstance4:
+    Type: AWS::EC2::Instance
+    Properties:
+      ImageId: String
+      AvailabilityZone: !Select
+      - 0
+      - !Split [":", "{{resolve:ssm:/vpc/subnets/private}}"]
diff --git a/test/unit/rules/functions/test_split.py b/test/unit/rules/functions/test_split.py
--- a/test/unit/rules/functions/test_split.py
+++ b/test/unit/rules/functions/test_split.py
@@ -21,7 +21,7 @@ def test_file_positive(self):
 
     def test_file_negative(self):
         """Test failure"""
-        self.helper_file_negative("test/fixtures/templates/bad/functions_split.yaml", 3)
+        self.helper_file_negative("test/fixtures/templates/bad/functions_split.yaml", 4)
 
     def test_split_parts(self):
         rule = Split()