Commit 8bce04ce authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

tests: dnssec: ultimate rollover test incl all CSK rollovers

parent 2aacfe72
$ORIGIN com.
$TTL 1200
@ SOA ns admin 20110100 7 7 16 600
ns AAAA ::0
#!/usr/bin/env python3
"""
Check of automatic algorithm rollover scenario.
"""
import collections
import os
import shutil
import datetime
import subprocess
from subprocess import check_call
from dnstest.utils import *
from dnstest.keys import Keymgr
from dnstest.test import Test
# check zone if keys are present and used for signing
def check_zone(server, zone, dnskeys, dnskey_rrsigs, cdnskeys, soa_rrsigs, msg):
qdnskeys = server.dig("example.com", "DNSKEY", bufsize=4096)
found_dnskeys = qdnskeys.count("DNSKEY")
qdnskeyrrsig = server.dig("example.com", "DNSKEY", dnssec=True, bufsize=4096)
found_rrsigs = qdnskeyrrsig.count("RRSIG")
qcdnskey = server.dig("example.com", "CDNSKEY", bufsize=4096)
found_cdnskeys = qcdnskey.count("CDNSKEY")
qsoa = server.dig("example.com", "SOA", dnssec=True, bufsize=4096)
found_soa_rrsigs = qsoa.count("RRSIG")
check_log("DNSKEYs: %d (expected %d)" % (found_dnskeys, dnskeys));
check_log("RRSIGs: %d (expected %d)" % (found_soa_rrsigs, soa_rrsigs));
check_log("DNSKEY-RRSIGs: %d (expected %d)" % (found_rrsigs, dnskey_rrsigs));
check_log("CDNSKEYs: %d (expected %d)" % (found_cdnskeys, cdnskeys));
if found_dnskeys != dnskeys:
set_err("BAD DNSKEY COUNT: " + msg)
detail_log("!DNSKEYs not published and activated as expected: " + msg)
if found_soa_rrsigs != soa_rrsigs:
set_err("BAD RRSIG COUNT: " + msg)
detail_log("!RRSIGs not published and activated as expected: " + msg)
if found_rrsigs != dnskey_rrsigs:
set_err("BAD DNSKEY RRSIG COUNT: " + msg)
detail_log("!RRSIGs not published and activated as expected: " + msg)
if found_cdnskeys != cdnskeys:
set_err("BAD CDNSKEY COUNT: " + msg)
detail_log("!CDNSKEYs not published and activated as expected: " + msg)
detail_log(SEP)
# Valgrind delay breaks the timing!
if not server.valgrind:
server.zone_backup(zone, flush=True)
server.zone_verify(zone)
def wait_for_rrsig_count(t, server, rrtype, rrsig_count, timeout):
rtime = 0
while True:
qdnskeyrrsig = server.dig("example.com", rrtype, dnssec=True, bufsize=4096)
found_rrsigs = qdnskeyrrsig.count("RRSIG")
if found_rrsigs == rrsig_count:
break
rtime = rtime + 1
t.sleep(1)
if rtime > timeout:
break
def wait_for_dnskey_count(t, server, dnskey_count, timeout):
rtime = 0
while True:
qdnskeyrrsig = server.dig("example.com", "DNSKEY", dnssec=True, bufsize=4096)
found_dnskeys = qdnskeyrrsig.count("DNSKEY")
if found_dnskeys == dnskey_count:
break
rtime = rtime + 1
t.sleep(1)
if rtime > timeout:
break
def watch_alg_rollover(t, server, zone, before_keys, after_keys, desc, set_alg, set_stss, submission_cb):
check_zone(server, zone, before_keys, 1, 1, 1, desc + ": initial keys")
server.dnssec(zone).single_type_signing = set_stss
server.dnssec(zone).alg = set_alg
server.gen_confile()
server.reload()
wait_for_rrsig_count(t, server, "SOA", 2, 20)
check_zone(server, zone, before_keys, 1 if after_keys > 1 else 2, 1, 2, desc + ": pre active")
wait_for_dnskey_count(t, server, before_keys + after_keys, 20)
check_zone(server, zone, before_keys + after_keys, 2, 1, 2, desc + ": both algorithms active")
# wait for any change in CDS records
CDS1 = str(server.dig(ZONE, "CDS").resp.answer[0].to_rdataset())
t.sleep(3)
while CDS1 == str(server.dig(ZONE, "CDS").resp.answer[0].to_rdataset()):
t.sleep(1)
check_zone(server, zone, before_keys + after_keys, 2, 1, 2, desc + ": new KSK ready")
submission_cb()
t.sleep(4)
check_zone(server, zone, before_keys + after_keys, 2, 1, 2, desc + ": both still active")
wait_for_dnskey_count(t, server, after_keys, 20)
check_zone(server, zone, after_keys, 1 if before_keys > 1 else 2, 1, 2, desc + ": post active")
wait_for_rrsig_count(t, server, "SOA", 1, 20)
check_zone(server, zone, after_keys, 1, 1, 1, desc + ": old alg removed")
def watch_ksk_rollover(t, server, zone, before_keys, after_keys, total_keys, desc, set_stss, set_ksk_lifetime, submission_cb):
check_zone(server, zone, before_keys, 1, 1, 1, desc + ": initial keys")
orig_ksk_lifetime = server.dnssec(zone).ksk_lifetime
server.dnssec(zone).single_type_signing = set_stss
server.dnssec(zone).ksk_lifetime = set_ksk_lifetime if set_ksk_lifetime > 0 else orig_ksk_lifetime
server.gen_confile()
server.reload()
wait_for_dnskey_count(t, server, total_keys, 20)
t.sleep(3)
check_zone(server, zone, total_keys, 1, 1, 1, desc + ": published new")
wait_for_rrsig_count(t, server, "DNSKEY", 2, 20)
check_zone(server, zone, total_keys, 2, 1, 1 if before_keys > 1 and after_keys > 1 else 2, desc + ": new KSK ready")
server.dnssec(zone).ksk_lifetime = orig_ksk_lifetime
server.gen_confile()
server.reload()
submission_cb()
t.sleep(4)
check_zone(server, zone, total_keys, 2, 1, 1 if before_keys > 1 else 2, desc + ": both still active")
wait_for_rrsig_count(t, server, "DNSKEY", 1, 20)
if before_keys < 2 or after_keys > 1:
check_zone(server, zone, total_keys, 1, 1, 1, desc + ": old key retired")
# else skip the test as we have no control on KSK and ZSK retiring asynchronously
wait_for_dnskey_count(t, server, after_keys, 20)
check_zone(server, zone, after_keys, 1, 1, 1, desc + ": old key removed")
t = Test()
parent = t.server("knot")
parent_zone = t.zone("com.", storage=".")
t.link(parent_zone, parent)
child = t.server("knot")
child_zone = t.zone("example.com.")
t.link(child_zone, child)
def cds_submission():
cds = child.dig(ZONE, "CDS")
cds_rdata = cds.resp.answer[0].to_rdataset()[0].to_text()
up = parent.update(parent_zone)
up.add(ZONE, 3600, "DS", cds_rdata)
up.send("NOERROR")
child.zonefile_sync = 24 * 60 * 60
child.dnssec(child_zone).enable = True
child.dnssec(child_zone).manual = False
child.dnssec(child_zone).alg = "RSASHA512"
child.dnssec(child_zone).dnskey_ttl = 2
child.dnssec(child_zone).zsk_lifetime = 99999
child.dnssec(child_zone).ksk_lifetime = 300 # this can be possibly left also infinity
child.dnssec(child_zone).propagation_delay = 11
child.dnssec(child_zone).ksk_sbm_check = [ parent ]
child.dnssec(child_zone).ksk_sbm_check_interval = 2
# parameters
ZONE = "example.com."
t.start()
child.zone_wait(child_zone)
watch_alg_rollover(t, child, child_zone, 2, 1, "KZSK to CSK alg", "RSASHA256", True, cds_submission)
watch_ksk_rollover(t, child, child_zone, 1, 1, 2, "CSK rollover", True, 27, cds_submission)
watch_ksk_rollover(t, child, child_zone, 1, 2, 3, "CSK to KZSK", False, 0, cds_submission)
watch_ksk_rollover(t, child, child_zone, 2, 2, 3, "KSK rollover", False, 27, cds_submission)
watch_ksk_rollover(t, child, child_zone, 2, 1, 3, "KZSK to CSK", True, 0, cds_submission)
watch_alg_rollover(t, child, child_zone, 1, 1, "CSK to CSK alg", "RSASHA512", True, cds_submission)
watch_alg_rollover(t, child, child_zone, 1, 2, "CSK to KZSK alg", "RSASHA256", False, cds_submission)
t.end()
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