Commit 88d2b6df authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

tests-extra: add NSEC tree update test

parent 319511c6
#!/usr/bin/env python3
'''Test for NSEC and NSEC3 fix after zone update'''
from dnstest.utils import *
from dnstest.test import Test
import random
t = Test()
master = t.server("knot")
slave = t.server("knot")
zones = t.zone_rnd(5, dnssec=False, records=50) + t.zone("records.")
t.link(zones, master, slave)
master.disable_notify = True
slave.disable_notify = True
for zone in zones:
master.dnssec(zone).enable = True
master.dnssec(zone).nsec3 = random.choice([True, False])
master.dnssec(zone).nsec3_iters = 2
master.dnssec(zone).nsec3_salt_len = 8
t.start()
master.zones_wait(zones)
slave.zones_wait(zones)
# initial convenience check
t.xfr_diff(master, slave, zones)
# update master
master.flush()
t.sleep(2)
for zone in zones:
master.random_ddns(zone)
t.sleep(4)
# sync slave with current master's state
slave.ctl("zone-refresh")
t.sleep(5)
# resign master and check that the resign made nothing
master.ctl("zone-sign")
master.zones_wait(zones)
t.xfr_diff(master, slave, zones, no_rrsig_rdata=True)
t.end()
...@@ -694,6 +694,13 @@ class Server(object): ...@@ -694,6 +694,13 @@ class Server(object):
else: else:
self.zones[zone.name].zfile.upd_file(storage=storage, version=version) self.zones[zone.name].zfile.upd_file(storage=storage, version=version)
def random_ddns(self, zone):
zone = zone_arg_check(zone)
up = self.update(zone)
self.zones[zone.name].zfile.gen_rnd_ddns(up)
up.send("NOERROR")
def add_module(self, zone, module): def add_module(self, zone, module):
zone = zone_arg_check(zone) zone = zone_arg_check(zone)
......
...@@ -330,7 +330,7 @@ class Test(object): ...@@ -330,7 +330,7 @@ class Test(object):
return item_owner_split[0].lower() + " " + item_data return item_owner_split[0].lower() + " " + item_data
def _axfr_records(self, resp, zone): def _axfr_records(self, resp, zone, no_rrsig_rdata):
unique = set() unique = set()
records = list() records = list()
...@@ -342,7 +342,18 @@ class Test(object): ...@@ -342,7 +342,18 @@ class Test(object):
for rr in rrs: for rr in rrs:
item_lower = self._canonize_record(rrset.rdtype, rr.strip()) item_lower = self._canonize_record(rrset.rdtype, rr.strip())
if item_lower in unique and rrset.rdtype != dns.rdatatype.SOA: if no_rrsig_rdata and rrset.rdtype == dns.rdatatype.SOA:
# Reset SOA serial.
soa_split = item_lower.split()
soa_split[6] = "0"
item_lower = " ".join(soa_split)
if no_rrsig_rdata and rrset.rdtype == dns.rdatatype.RRSIG:
# Trim RRSIG signature part.
rrsig_split = item_lower.split(None, 5)
item_lower = " ".join(rrsig_split[:5])
elif item_lower in unique and rrset.rdtype != dns.rdatatype.SOA:
detail_log("!Duplicate record server='%s':" % server.name) detail_log("!Duplicate record server='%s':" % server.name)
detail_log(" %s" % item_lower) detail_log(" %s" % item_lower)
continue continue
...@@ -367,9 +378,9 @@ class Test(object): ...@@ -367,9 +378,9 @@ class Test(object):
for record in diff2: for record in diff2:
detail_log(" %s" % record) detail_log(" %s" % record)
def _axfr_diff(self, server1, server2, zone): def _axfr_diff(self, server1, server2, zone, no_rrsig_rdata):
unique1, rrsets1 = self._axfr_records(server1.dig(zone.name, "AXFR", log_no_sep=True), zone) unique1, rrsets1 = self._axfr_records(server1.dig(zone.name, "AXFR", log_no_sep=True), zone, no_rrsig_rdata)
unique2, rrsets2 = self._axfr_records(server2.dig(zone.name, "AXFR", log_no_sep=True), zone) unique2, rrsets2 = self._axfr_records(server2.dig(zone.name, "AXFR", log_no_sep=True), zone, no_rrsig_rdata)
self._axfr_diff_resp(unique1, rrsets1, unique2, rrsets2, server1, server2) self._axfr_diff_resp(unique1, rrsets1, unique2, rrsets2, server1, server2)
...@@ -527,20 +538,22 @@ class Test(object): ...@@ -527,20 +538,22 @@ class Test(object):
for change1, change2 in zip(changes1, changes2): for change1, change2 in zip(changes1, changes2):
change1.cmp(change2) change1.cmp(change2)
def xfr_diff(self, server1, server2, zones, serials=None, udp=False): def xfr_diff(self, server1, server2, zones, serials=None, udp=False, no_rrsig_rdata=False):
for zone in zones: for zone in zones:
check_log("CHECK %sXFR DIFF %s %s<->%s" % ("I" if serials else "A", check_log("CHECK %sXFR DIFF %s %s<->%s" % ("I" if serials else "A",
zone.name, server1.name, server2.name)) zone.name, server1.name, server2.name))
if serials: if serials:
if no_rrsig_rdata:
set_err("RRSIG rdata and SOA serial skipping not implemented for IXFR diff")
self._ixfr_diff(server1, server2, zone, serials[zone.name], udp) self._ixfr_diff(server1, server2, zone, serials[zone.name], udp)
else: else:
self._axfr_diff(server1, server2, zone) self._axfr_diff(server1, server2, zone, no_rrsig_rdata)
detail_log(SEP) detail_log(SEP)
def axfr_diff_resp(self, resp1, resp2, server1, server2, zone): def axfr_diff_resp(self, resp1, resp2, server1, server2, zone, no_rrsig_rdata=False):
unique1, rrsets1 = self._axfr_records(resp1, zone) unique1, rrsets1 = self._axfr_records(resp1, zone, no_rrsig_rdata)
unique2, rrsets2 = self._axfr_records(resp2, zone) unique2, rrsets2 = self._axfr_records(resp2, zone, no_rrsig_rdata)
self._axfr_diff_resp(unique1, rrsets1, unique2, rrsets2, server1, server2) self._axfr_diff_resp(unique1, rrsets1, unique2, rrsets2, server1, server2)
......
...@@ -7,6 +7,7 @@ import shutil ...@@ -7,6 +7,7 @@ import shutil
import zone_generate import zone_generate
import glob import glob
import distutils.dir_util import distutils.dir_util
import dns.name
from subprocess import DEVNULL, PIPE, Popen from subprocess import DEVNULL, PIPE, Popen
from dnstest.utils import * from dnstest.utils import *
...@@ -245,6 +246,22 @@ class ZoneFile(object): ...@@ -245,6 +246,22 @@ class ZoneFile(object):
file.write("%s IN AAAA dead:beef:dead:beef:dead:beef:%04x:%04x\n" % file.write("%s IN AAAA dead:beef:dead:beef:dead:beef:%04x:%04x\n" %
(owner, rnd1, rnd2)) (owner, rnd1, rnd2))
def gen_rnd_ddns(self, ddns):
'''Walk zonefile, randomly mark some records to be removed by ddns and some added'''
with open(self.path, 'r') as file:
for fline in file:
line = fline.split(None, 3)
if line[0] not in [";;"] and line[2] not in ["SOA", "RRSIG", "DNSKEY", "DS", "CDS", "CDNSKEY", "NSEC", "NSEC3", "NSEC3PARAM"]:
try:
if random.randint(1, 20) in [4, 5]:
ddns.delete(line[0], line[2])
if random.randint(1, 20) in [2, 3] and line[2] not in ["DNAME"]:
ddns.add("xyz."+line[0], line[1], line[2], line[3])
except (dns.rdatatype.UnknownRdatatype, dns.name.LabelTooLong, dns.name.NameTooLong):
# problems - simply skip. This is completely stochastic anyway.
pass
def remove(self): def remove(self):
'''Remove zone file.''' '''Remove zone file.'''
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment