]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
dnssec: BUGFIX sign DNSKEY with all published KSKs...
authorLibor Peltan <libor.peltan@nic.cz>
Fri, 7 May 2021 10:45:29 +0000 (12:45 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Mon, 10 May 2021 18:28:08 +0000 (20:28 +0200)
...automatic KSK roll must ensure that new KSK has been signing
the DNSKEY for dnskey-ttl seconds before submission updates DS

doc/operation.rst
src/knot/dnssec/zone-keys.c
tests-extra/tests/dnssec/key_rollovers/test.py

index 9710d4866353ce9b99a2a1def7b61c8c23ce1377..24eeab5da03eb2bdc4075dc1726346249c7c84b5 100644 (file)
@@ -437,8 +437,8 @@ DNSSEC key states
 =================
 
 During its lifetime, a DNSSEC key finds itself in different states. Most of the time it
-is used for signing the zone and published in the zone. In order to change
-this state, one type of a key rollover is necessary, and during this rollover,
+is used for signing the zone and published in the zone. In order to exchange
+the key, one type of a key rollover is necessary, and during this rollover,
 the key goes through various states with respect to the rollover type and also the
 state of the other key being rolled-over.
 
@@ -447,7 +447,8 @@ First, let's list the states of the key being rolled-in.
 Standard states:
 
 - ``active`` — The key is used for signing.
-- ``published`` — The key is published in the zone, but not used for signing.
+- ``published`` — The key is published in the zone, but not used for signing. If the key is
+  a KSK or CSK, it is used for signing the DNSKEY RRSet.
 - ``ready`` (only for KSK) — The key is published in the zone and used for signing. The
   old key is still active, since we are waiting for the DS records in the parent zone to be
   updated (i.e. "KSK submission").
@@ -465,7 +466,8 @@ Standard states:
 - ``retire-active`` — The key is still used for signing, and is published in the zone, waiting for
   the updated DS records in parent zone to be acked by resolvers (KSK case) or synchronizing
   with KSK during algorithm rollover (ZSK case).
-- ``retired`` — The key is no longer used for signing, but still published in the zone.
+- ``retired`` — The key is no longer used for signing, but still published in the zone. If the key is
+  a KSK or CSK, it is still used for signing the DNSKEY RRSet.
 - ``removed`` — The key is not used in any way (in most cases such keys are deleted immediately).
 
 Special states for algorithm rollover:
@@ -559,7 +561,7 @@ lines of :rfc:`6781#section-4.1.2`::
 
   2019-07-15T20:58:00 info: [example.com.] DNSSEC, signing zone
   2019-07-15T20:58:00 info: [example.com.] DNSSEC, KSK rollover started
-  2019-07-15T20:58:00 info: [example.com.] DNSSEC, key, tag 32925, algorithm ECDSAP256SHA256, KSK, public
+  2019-07-15T20:58:00 info: [example.com.] DNSSEC, key, tag 32925, algorithm ECDSAP256SHA256, KSK, public, active+
   2019-07-15T20:58:00 info: [example.com.] DNSSEC, key, tag 58209, algorithm ECDSAP256SHA256, KSK, public, active
   2019-07-15T20:58:00 info: [example.com.] DNSSEC, key, tag 34273, algorithm ECDSAP256SHA256, public, active
   2019-07-15T20:58:00 info: [example.com.] DNSSEC, signing started
@@ -597,7 +599,7 @@ operator must confirm it manually (using ``knotc zone-ksk-submitted``)::
   ... (parent's DS TTL is 7 seconds) ...
 
   2019-07-15T20:58:23 info: [example.com.] DNSSEC, signing zone
-  2019-07-15T20:58:23 info: [example.com.] DNSSEC, key, tag 58209, algorithm ECDSAP256SHA256, KSK, public
+  2019-07-15T20:58:23 info: [example.com.] DNSSEC, key, tag 58209, algorithm ECDSAP256SHA256, KSK, public, active+
   2019-07-15T20:58:23 info: [example.com.] DNSSEC, key, tag 32925, algorithm ECDSAP256SHA256, KSK, public, active
   2019-07-15T20:58:23 info: [example.com.] DNSSEC, key, tag 34273, algorithm ECDSAP256SHA256, public, active
   2019-07-15T20:58:23 info: [example.com.] DNSSEC, signing started
@@ -667,7 +669,7 @@ Further rollovers::
 
   2019-07-15T21:03:00 info: [example.com.] DNSSEC, signing zone
   2019-07-15T21:03:00 info: [example.com.] DNSSEC, KSK rollover started
-  2019-07-15T21:03:00 info: [example.com.] DNSSEC, key, tag 27452, algorithm ECDSAP256SHA256, KSK, public
+  2019-07-15T21:03:00 info: [example.com.] DNSSEC, key, tag 27452, algorithm ECDSAP256SHA256, KSK, public, active+
   2019-07-15T21:03:00 info: [example.com.] DNSSEC, key, tag 32925, algorithm ECDSAP256SHA256, KSK, public, active
   2019-07-15T21:03:00 info: [example.com.] DNSSEC, key, tag 32841, algorithm ECDSAP256SHA256, public, active
   2019-07-15T21:03:00 info: [example.com.] DNSSEC, signing started
index 4e1c1ceb99d6cc928b6ec1dfb739bf953901ca0d..1beaf2cdc9a602b9602c0ae8a66fa6ed4eda2844 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -319,13 +319,13 @@ static void set_key(knot_kasp_key_t *kasp_key, knot_time_t now,
        zone_key->is_ready = (zone_key->is_ksk && is_ready(timing, now));
        zone_key->is_active = is_active(timing, now);
 
-       zone_key->is_ksk_active_plus = zone_key->is_ready;
+       zone_key->is_ksk_active_plus = zone_key->is_public && zone_key->is_ksk && !zone_key->is_active; // KSK is active+ whenever published
        zone_key->is_zsk_active_plus = zone_key->is_ready && !same_alg_act_zsk;
        if (knot_time_cmp(timing->pre_active, now) <= 0 &&
            knot_time_cmp(timing->ready, now) > 0 &&
            knot_time_cmp(timing->active, now) > 0) {
                zone_key->is_zsk_active_plus = zone_key->is_zsk;
-               zone_key->is_ksk_active_plus = (knot_time_cmp(timing->publish, now) <= 0 && zone_key->is_ksk);
+               // zone_key->is_ksk_active_plus = (knot_time_cmp(timing->publish, now) <= 0 && zone_key->is_ksk); // redundant, but helps understand
        }
        if (knot_time_cmp(timing->retire_active, now) <= 0 &&
            knot_time_cmp(timing->retire, now) > 0) {
index ebcc7c21ebbf742190514e7e3be804e34bfbed46..2da0276bf298d348883a9414beb4b65e4c8319d0 100644 (file)
@@ -109,6 +109,19 @@ def wait_for_count(t, server, rrtype, count, min_time, timeout, msg):
             break
     check_min_time(min_time, msg)
 
+def wait_for_cds_change(t, server, min_time, timeout, msg):
+    rtime = 0
+    CDS1 = str(server.dig(ZONE, "CDS").resp.answer[0].to_rdataset())
+    while True:
+        CDS2 = str(server.dig(ZONE, "CDS").resp.answer[0].to_rdataset())
+        if CDS1 != CDS2:
+            break
+        rtime = rtime + 1
+        t.sleep(1)
+        if rtime > timeout:
+            break
+    check_min_time(min_time, msg)
+
 def wait_after_submission(t, server):
     if DOUBLE_DS:
         wait_for_count(t, server, "CDNSKEY", 1, 0, 10, "after submission")
@@ -170,10 +183,10 @@ def watch_ksk_rollover(t, server, zone, slave, before_keys, after_keys, total_ke
 
     msg = desc + ": published new"
     wait_for_count(t, server, "DNSKEY", total_keys, 0, 20, msg)
-    check_zone(server, zone, slave, total_keys, 1, 1, 1, msg)
+    check_zone(server, zone, slave, total_keys, 2, 1, 1, msg)
 
     msg = desc + ": new KSK ready"
-    wait_for_rrsig_count(t, server, "DNSKEY", 2, 10, 20, msg)
+    wait_for_cds_change(t, server, 10, 20, msg)
     cdnskeys = 2 if DOUBLE_DS else 1
     expect_zone_rrsigs = (2 if before_keys == 1 and after_keys > 1 else 1) # there is an exception for CSK->KZSK rollover that we have double signatures for the zone. Sorry, we don't care...
     check_zone(server, zone, slave, total_keys, 2, cdnskeys, expect_zone_rrsigs, msg)
@@ -186,14 +199,8 @@ def watch_ksk_rollover(t, server, zone, slave, before_keys, after_keys, total_ke
         check_zone(server, zone, slave, total_keys, 2, 1, 1, msg)
     # else skip the test as we have no control on KSK and ZSK retiring asynchronously
 
-    msg = desc + ": old key retired"
-    wait_for_rrsig_count(t, server, "DNSKEY", 1, 5, 20, msg)
-    if before_keys < 2 or after_keys > 1:
-        check_zone(server, zone, slave, total_keys, 1, 1, 1, msg)
-    # else skip the test as we have no control on KSK and ZSK retiring asynchronously
-
     msg = desc + ": old key removed"
-    wait_for_count(t, server, "DNSKEY", after_keys, 14 if before_keys < 2 else 12, 20, msg)
+    wait_for_count(t, server, "DNSKEY", after_keys, 14, 20, msg)
     check_zone(server, zone, slave, after_keys, 1, 1, 1, msg)
 
 t = Test()