Repository: aws-cloudformation/cfn-lint

Issue:
Not recognizing '*' in a domain name in Route53 record set.
cfn-lint version: 0.20.2 (latest version at time of writing)

Description of issue:
Is not recognizing valid Route53 use of * in a recordset. The record set deploys and works correctly. Sample code seen below.

```
Resources:
  startest30prdnuskinioRoute53pubRecordSet:
    Type: AWS::Route53::RecordSetGroup
    Properties: 
      Comment: '*.test30 prod'
      HostedZoneId: !Ref PrdNuskinIoPublicZone 
      RecordSets:
      - Name: '*.test30.prd.nuskin.io.'
        SetIdentifier: 'usw2'
        ResourceRecords:
          - '*.test30.prd.usw2.nuskin.io.'   <------ gives "does not contain a valid domain name" error
        TTL: '300'
        Type: CNAME
        Weight: 100
```



Discussion:
I'll take a look. The check in cname (regex) is pretty basic already, but I will check. Maybe a stupid question, but that is a valid cname? ;)
Just tried to (manually) add a recordset with that value, but even the Console says it is incorrect:

![image](https://user-images.githubusercontent.com/35613489/57853314-b76b7600-77e5-11e9-98a1-65268eb3daeb.png)

Can you check if the example you've given is valid? 
@nsecws I’m going to close this for now. We can reopen it if needed. 
Sorry for the long response time. It seems to have removed the '*' when I pasted the script. The record should read *.30.isi.usw2.nuskin.io. which is a valid record. I've fixed the formatting in the original post.

![Screen Shot 2019-06-19 at 2 10 16 PM](https://user-images.githubusercontent.com/22325230/59797048-0486b000-929c-11e9-9af5-d5a85faf9f8c.png)


Resolving patch:
diff --git a/src/cfnlint/rules/resources/route53/RecordSet.py b/src/cfnlint/rules/resources/route53/RecordSet.py
--- a/src/cfnlint/rules/resources/route53/RecordSet.py
+++ b/src/cfnlint/rules/resources/route53/RecordSet.py
@@ -28,7 +28,8 @@ class RecordSet(CloudFormationLintRule):
     source_url = 'https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html'
     tags = ['resources', 'route53', 'record_set']
 
-    REGEX_DOMAINNAME = re.compile(r'^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])(.)$')
+    # Regex generated from https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DomainNameFormat.html
+    REGEX_DOMAINNAME = re.compile(r'^[a-zA-Z0-9\!\"\#\$\%\&\'\(\)\*\+\,-\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~\.]+$')
     REGEX_TXT = re.compile(r'^("[^"]{1,255}" *)*"[^"]{1,255}"$')
     REGEX_CNAME_VALIDATIONS = re.compile(r'^.*\.acm-validations\.aws\.?$')
 


Test patch:
diff --git a/test/fixtures/templates/bad/route53.yaml b/test/fixtures/templates/bad/route53.yaml
--- a/test/fixtures/templates/bad/route53.yaml
+++ b/test/fixtures/templates/bad/route53.yaml
@@ -97,26 +97,6 @@ Resources:
       ResourceRecords:
         - "127.0.0.1"
         - "10 my domain"
-  MyNSRecordSet:
-    Type: "AWS::Route53::RecordSet"
-    Properties:
-      Comment: "A valid NS Record"
-      HostedZoneId: !Ref "MyHostedZone"
-      Name: "www.example.com"
-      Type: "NS"
-      TTL: "300"
-      ResourceRecords:
-        - "127.0.0.1"
-  MyPTRRecordSet:
-    Type: "AWS::Route53::RecordSet"
-    Properties:
-      Comment: "A valid NS Record"
-      HostedZoneId: !Ref "MyHostedZone"
-      Name: "www.example.com"
-      Type: "PTR"
-      TTL: "300"
-      ResourceRecords:
-        - "127.0.0.1"
   MyRecordSetGroup:
     Type: "AWS::Route53::RecordSetGroup"
     Properties:
@@ -170,16 +150,6 @@ Resources:
           ResourceRecords:
             - "mx1.example.com"
             - "65536 mx2.example.com"
-  MySecondRecordSetGroup:
-    Type: "AWS::Route53::RecordSetGroup"
-    Properties:
-      HostedZoneId: !Ref "MyHostedZone"
-      RecordSets:
-        - Name: "z.example.com"
-          Type: "TXT"
-          TTL: "300"
-          ResourceRecords:
-            - "\"henk\""
   PoorlyConfiguredRoute53:
     Type: "AWS::Route53::RecordSetGroup"
     Properties:
diff --git a/test/fixtures/templates/good/route53.yaml b/test/fixtures/templates/good/route53.yaml
--- a/test/fixtures/templates/good/route53.yaml
+++ b/test/fixtures/templates/good/route53.yaml
@@ -81,6 +81,16 @@ Resources:
       TTL: "300"
       ResourceRecords:
         - "hostname.example.com"
+  MyCNAMERecordSpecialCharactersSet:
+    Type: "AWS::Route53::RecordSet"
+    Properties:
+      Comment: "A valid CNAME Record"
+      HostedZoneId: !Ref "MyHostedZone"
+      Name: "*test.&.example.com-"
+      Type: "CNAME"
+      TTL: "300"
+      ResourceRecords:
+        - "hostname.example.com"
   MyCNAME2RecordSet:
     Type: "AWS::Route53::RecordSet"
     Properties:
diff --git a/test/rules/resources/route53/test_recordsets.py b/test/rules/resources/route53/test_recordsets.py
--- a/test/rules/resources/route53/test_recordsets.py
+++ b/test/rules/resources/route53/test_recordsets.py
@@ -34,4 +34,4 @@ def test_file_positive(self):
 
     def test_file_negative(self):
         """Test failure"""
-        self.helper_file_negative('test/fixtures/templates/bad/route53.yaml', 32)
+        self.helper_file_negative('test/fixtures/templates/bad/route53.yaml', 30)