Fix wildcard NS record

BIND does not allow a NS record having a wildcard name,
e.g. *.example.com.

Change-Id: I358d26a10129305bcfef91f5577c1f6ae08701d2
Closes-Bug: #1533299
This commit is contained in:
James Li 2016-01-14 13:13:19 -06:00
parent caa9cc6abf
commit fe3f7df4df
5 changed files with 106 additions and 0 deletions

View File

@ -32,6 +32,16 @@ class NS(Record):
} }
} }
@classmethod
def get_recordset_schema_changes(cls):
return {
'name': {
'schema': {
'format': 'ns-hostname',
},
},
}
def _to_string(self): def _to_string(self):
return self.nsdname return self.nsdname

View File

@ -102,6 +102,18 @@ def is_hostname(instance):
return True return True
@draft4_format_checker.checks("ns-hostname")
def is_ns_hostname(instance):
if not isinstance(instance, compat.str_types):
return True
# BIND doesn't like *.host.com. see bug #1533299
if not re.match(RE_ZONENAME, instance):
return False
return True
@draft3_format_checker.checks("ip-or-host") @draft3_format_checker.checks("ip-or-host")
@draft4_format_checker.checks("ip-or-host") @draft4_format_checker.checks("ip-or-host")
def is_ip_or_host(instance): def is_ip_or_host(instance):

View File

@ -149,6 +149,76 @@ class SchemaFormatTest(TestCase):
for hostname in invalid_hostnames: for hostname in invalid_hostnames:
self.assertFalse(format.is_hostname(hostname)) self.assertFalse(format.is_hostname(hostname))
def test_is_ns_hostname(self):
valid_ns_hostnames = [
'example.com.',
'www.example.com.',
'12345.example.com.',
'192-0-2-1.example.com.',
'ip192-0-2-1.example.com.',
'www.ip192-0-2-1.example.com.',
'ip192-0-2-1.www.example.com.',
'abc-123.example.com.',
'_tcp.example.com.',
'_service._tcp.example.com.',
('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2'
'.ip6.arpa.'),
'1.1.1.1.in-addr.arpa.',
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.',
('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi.'),
]
invalid_ns_hostnames = [
# Wildcard NS hostname, bug #1533299
'*.example.com.',
'**.example.com.',
'*.*.example.org.',
'a.*.example.org.',
# Exceeds single lable length limit
('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkL'
'.'),
('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkL'
'.'),
# Exceeds total length limit
('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.'
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopq.'),
# Empty label part
'abc..def.',
'..',
# Invalid character
'abc$.def.',
'abc.def$.',
# Labels must not start with a -
'-abc.',
'abc.-def.',
'abc.-def.ghi.',
# Labels must not end with a -
'abc-.',
'abc.def-.',
'abc.def-.ghi.',
# Labels must not start or end with a -
'-abc-.',
'abc.-def-.',
'abc.-def-.ghi.',
# Trailing newline - Bug 1471158
"www.example.com.\n",
]
for hostname in valid_ns_hostnames:
self.assertTrue(format.is_ns_hostname(hostname))
for hostname in invalid_ns_hostnames:
self.assertFalse(format.is_ns_hostname(hostname))
def test_is_zonename(self): def test_is_zonename(self):
valid_zonenames = [ valid_zonenames = [
'example.com.', 'example.com.',

View File

@ -183,6 +183,14 @@ class RecordsetTest(DesignateV2Test):
for m in verify_models: for m in verify_models:
self.assert_dns(m) self.assert_dns(m)
def test_create_wildcard_NS(self):
client = RecordsetClient.as_user('default')
model = datagen.wildcard_ns_recordset(self.zone.name)
self._assert_exception(
exceptions.BadRequest, 'invalid_object', 400,
client.post_recordset, self.zone.id, model)
def test_cname_recordsets_cannot_have_more_than_one_record(self): def test_cname_recordsets_cannot_have_more_than_one_record(self):
post_model = datagen.random_cname_recordset(zone_name=self.zone.name) post_model = datagen.random_cname_recordset(zone_name=self.zone.name)
post_model.records = [ post_model.records = [

View File

@ -221,3 +221,9 @@ def random_tld_data():
"name": random_string(prefix='tld') "name": random_string(prefix='tld')
} }
return TLDModel.from_dict(data) return TLDModel.from_dict(data)
def wildcard_ns_recordset(zone_name):
name = "*.{0}".format(zone_name)
records = ["ns.example.com."]
return random_recordset_data('NS', zone_name, name, records)