Repository: aws-cloudformation/cfn-lint

Issue:
Handle SSM parameters in E2505
The check E2505 fails when reading the CIDR from SSM using the following code:

```
  VpcCidr:
    Description: 'VPC CIDR Block'
    Type: AWS::SSM::Parameter::Value<String>
    Default: /Infra/VpcCidr
```

The message is misleading, too. It is about security groups and not cidr ranges.

https://github.com/awslabs/cfn-python-lint/blob/3b785df6b262b733bedcaa8c8de9a2c65ac161b8/src/cfnlint/rules/resources/ectwo/Vpc.py#L92


Discussion:

Resolving patch:
diff --git a/src/cfnlint/rules/parameters/Cidr.py b/src/cfnlint/rules/parameters/Cidr.py
--- a/src/cfnlint/rules/parameters/Cidr.py
+++ b/src/cfnlint/rules/parameters/Cidr.py
@@ -62,14 +62,16 @@ def check_cidr_ref(self, value, path, parameters, resources):
 
         if value in parameters:
             parameter = parameters.get(value, {})
+            parameter_type = parameter.get('Type')
             allowed_pattern = parameter.get('AllowedPattern', None)
             allowed_values = parameter.get('AllowedValues', None)
-            if not allowed_pattern and not allowed_values:
-                param_path = ['Parameters', value]
-                full_param_path = '/'.join(param_path)
-                message = 'AllowedPattern and/or AllowedValues for Parameter should be specified at {1}. ' \
-                          'Example for AllowedPattern: "{0}"'
-                matches.append(RuleMatch(param_path, message.format(REGEX_CIDR.pattern, full_param_path)))
+            if parameter_type not in ['AWS::SSM::Parameter::Value<String>']:
+                if not allowed_pattern and not allowed_values:
+                    param_path = ['Parameters', value]
+                    full_param_path = '/'.join(param_path)
+                    message = 'AllowedPattern and/or AllowedValues for Parameter should be specified at {1}. ' \
+                              'Example for AllowedPattern: "{0}"'
+                    matches.append(RuleMatch(param_path, message.format(REGEX_CIDR.pattern, full_param_path)))
 
         return matches
 
diff --git a/src/cfnlint/rules/resources/ectwo/Vpc.py b/src/cfnlint/rules/resources/ectwo/Vpc.py
--- a/src/cfnlint/rules/resources/ectwo/Vpc.py
+++ b/src/cfnlint/rules/resources/ectwo/Vpc.py
@@ -25,7 +25,8 @@ class Vpc(CloudFormationLintRule):
     """Check if EC2 VPC Resource Properties"""
     id = 'E2505'
     shortdesc = 'Resource EC2 VPC Properties'
-    description = 'See if EC2 VPC Properties are set correctly'
+    description = 'Check if the default tenancy is default or dedicated and ' \
+                  'that CidrBlock is a valid CIDR range.'
     source_url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html'
     tags = ['properties', 'vpc']
 
@@ -42,7 +43,8 @@ def check_vpc_ref(self, value, path, parameters, resources):
         """Check ref for VPC"""
         matches = []
         allowed_types = [
-            'String'
+            'String',
+            'AWS::SSM::Parameter::Value<String>',
         ]
         if value in resources:
             message = 'DefaultTenancy can\'t use a Ref to a resource for {0}'
@@ -52,7 +54,7 @@ def check_vpc_ref(self, value, path, parameters, resources):
             parameter_type = parameter.get('Type', None)
             if parameter_type not in allowed_types:
                 path_error = ['Parameters', value, 'Type']
-                message = 'Security Group Id Parameter should be of type [{0}] for {1}'
+                message = 'DefaultTenancy parameter should be of type [{0}] for {1}'
                 matches.append(
                     RuleMatch(
                         path_error,
@@ -75,7 +77,8 @@ def check_cidr_ref(self, value, path, parameters, resources):
         matches = []
 
         allowed_types = [
-            'String'
+            'String',
+            'AWS::SSM::Parameter::Value<String>',
         ]
         if value in resources:
             resource_obj = resources.get(value, {})
@@ -89,7 +92,7 @@ def check_cidr_ref(self, value, path, parameters, resources):
             parameter_type = parameter.get('Type', None)
             if parameter_type not in allowed_types:
                 path_error = ['Parameters', value, 'Type']
-                message = 'Security Group Id Parameter should be of type [{0}] for {1}'
+                message = 'CidrBlock parameter should be of type [{0}] for {1}'
                 matches.append(
                     RuleMatch(
                         path_error,


Test patch:
diff --git a/test/fixtures/templates/good/properties_ec2_vpc.yaml b/test/fixtures/templates/good/properties_ec2_vpc.yaml
--- a/test/fixtures/templates/good/properties_ec2_vpc.yaml
+++ b/test/fixtures/templates/good/properties_ec2_vpc.yaml
@@ -17,6 +17,9 @@ Parameters:
     AllowedValues:
       - '127.0.0.1/32'
       - '8.8.8.8/32'
+  cidrBlockSsm:
+    Type: AWS::SSM::Parameter::Value<String>
+    Default: /Infra/VpcCidr
   vpcTenancy:
     Type: String
     AllowedValues:
@@ -43,6 +46,11 @@ Resources:
     Properties:
       InstanceTenancy: !Ref vpcTenancy
       CidrBlock: !Ref cidrBlockAllowedPatternValues
+  myVpc5:
+    Type: AWS::EC2::VPC
+    Properties:
+      InstanceTenancy: dedicated
+      CidrBlock: !Ref cidrBlockSsm
   mySubnet21:
     Type: AWS::EC2::Subnet
     Properties:
diff --git a/test/rules/parameters/test_cidr.py b/test/rules/parameters/test_cidr.py
--- a/test/rules/parameters/test_cidr.py
+++ b/test/rules/parameters/test_cidr.py
@@ -27,6 +27,7 @@ def setUp(self):
 
     success_templates = [
         'test/fixtures/templates/good/functions_cidr.yaml',
+        'test/fixtures/templates/good/properties_ec2_vpc.yaml',
     ]
 
     def test_file_positive(self):