]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
log/dnssec: warn upon every incremental if full had failed
authorLibor Peltan <libor.peltan@nic.cz>
Thu, 17 Oct 2024 15:18:12 +0000 (17:18 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Fri, 18 Oct 2024 06:18:21 +0000 (08:18 +0200)
src/knot/dnssec/zone-events.c
src/knot/updates/zone-update.c
src/knot/updates/zone-update.h
src/knot/zone/zone.h
tests-extra/tests/dnssec/full_sign_fail/test.py [new file with mode: 0644]

index 543052a19f59b1f4eaf6f22925546d324ce78a2c..811b3dc1469fa53f055bc3b1bc387e438d184e54 100644 (file)
@@ -159,6 +159,8 @@ int knot_dnssec_zone_sign(zone_update_t *update,
        kdnssec_ctx_t ctx = { 0 };
        zone_keyset_t keyset = { 0 };
 
+       zone_unset_flag(update->zone, ZONE_LAST_SIGN_OK);
+
        int result = kdnssec_ctx_init(conf, &ctx, zone_name, zone_kaspdb(update->zone), NULL);
        if (result != KNOT_EOK) {
                log_zone_error(zone_name, "DNSSEC, failed to initialize signing context (%s)",
@@ -316,6 +318,7 @@ done:
                reschedule->next_sign = schedule_next(&ctx, &keyset, ctx.offline_next_time, ctx.stats->expire);
                reschedule->plan_dnskey_sync = ctx.policy->has_dnskey_sync;
                update->new_cont->dnssec_expire = ctx.stats->expire;
+               update->flags |= UPDATE_SIGNED_FULL;
        } else {
                reschedule->next_sign = knot_dnssec_failover_delay(&ctx);
                reschedule->next_rollover = 0;
@@ -442,6 +445,9 @@ int knot_dnssec_sign_update(zone_update_t *update, conf_t *conf)
 
        log_zone_info(zone_name, "DNSSEC, incrementally signed, serial %u, new RRSIGs %zu",
                      zone_contents_serial(update->new_cont), ctx.stats->rrsig_count);
+       if (!zone_get_flag(update->zone, ZONE_LAST_SIGN_OK, false)) {
+               log_zone_warning(zone_name, "DNSSEC, previous signing had failed");
+       }
 
 done:
        if (result == KNOT_EOK) {
index 4b65a2cf37746e81c39efa4250ff34b221ca54da..45c874ebc193a4b9bc3f71179f0f52ac7bae44bb 100644 (file)
@@ -902,7 +902,13 @@ int zone_update_commit(conf_t *conf, zone_update_t *update)
 
        int ret = KNOT_EOK;
 
+       conf_val_t val = conf_zone_get(conf, C_DNSSEC_SIGNING, update->zone->name);
+       bool dnssec = conf_bool(&val);
+
        if ((update->flags & UPDATE_INCREMENTAL) && zone_update_no_change(update)) {
+               if (dnssec && (update->flags & UPDATE_SIGNED_FULL)) {
+                       zone_set_flag(update->zone, ZONE_LAST_SIGN_OK);
+               }
                zone_update_clear(update);
                return KNOT_EOK;
        }
@@ -916,9 +922,6 @@ int zone_update_commit(conf_t *conf, zone_update_t *update)
                return ret;
        }
 
-       conf_val_t val = conf_zone_get(conf, C_DNSSEC_SIGNING, update->zone->name);
-       bool dnssec = conf_bool(&val);
-
        conf_val_t thr = conf_zone_get(conf, C_ADJUST_THR, update->zone->name);
        if ((update->flags & (UPDATE_HYBRID | UPDATE_FULL))) {
                ret = zone_adjust_full(update->new_cont, conf_int(&thr));
@@ -971,6 +974,10 @@ int zone_update_commit(conf_t *conf, zone_update_t *update)
                                         "unable to save lastsigned serial, "
                                         "future transfers might be broken");
                }
+
+               if ((update->flags & UPDATE_SIGNED_FULL)) {
+                       zone_set_flag(update->zone, ZONE_LAST_SIGN_OK);
+               }
        }
 
        /* Switch zone contents. */
index 814d0ec99d323d362120d7415df36e630757da6b..e500e07fcdc21210e6d3685cf4eac8e82c8d611c 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2024 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
@@ -59,6 +59,7 @@ typedef enum {
        UPDATE_EXTRA_CHSET    = 1 << 6, /*!< Extra changeset in use, to store diff btwn zonefile and final contents. */
        UPDATE_CHANGED_NSEC   = 1 << 7, /*!< This incremental update affects NSEC or NSEC3 nodes in zone. */
        UPDATE_NO_CHSET       = 1 << 8, /*!< Avoid using changeset and serialize to journal from diff of bi-nodes. */
+       UPDATE_SIGNED_FULL    = 1 << 9, /*!< Full (non-incremental) zone sign took place during this update. */
 } zone_update_flags_t;
 
 /*!
index a6046de5470e09925f856f18505d1ac4c7d5f9d5..8bb5c0967b0fecc1e41a11b8cd3f3a5b50cbc50b 100644 (file)
@@ -49,6 +49,7 @@ typedef enum {
        ZONE_IS_CAT_MEMBER  = 1 << 6, /*!< This zone exists according to a catalog. */
        ZONE_XFR_FROZEN     = 1 << 7, /*!< Outgoing AXFR/IXFR temporarily disabled. */
        ZONE_USER_FLUSH     = 1 << 8, /*!< User-triggered flush. */
+       ZONE_LAST_SIGN_OK   = 1 << 9, /*!< Last full-sign event finished OK. */
 } zone_flag_t;
 
 /*!
diff --git a/tests-extra/tests/dnssec/full_sign_fail/test.py b/tests-extra/tests/dnssec/full_sign_fail/test.py
new file mode 100644 (file)
index 0000000..b8007d5
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+
+'''Test failed zone sign with incremental still working.'''
+
+from dnstest.test import Test
+from dnstest.utils import *
+
+t = Test()
+
+server = t.server("knot")
+zone = t.zone_rnd(1, records=40, dnssec=False)
+
+t.link(zone, server)
+
+for z in zone:
+    server.dnssec(z).enable = True
+    server.dnssec(z).rrsig_lifetime = 20
+    server.dnssec(z).rrsig_refresh = 10
+    server.dnssec(z).rrsig_prerefresh = 4
+
+server.journal_max_usage = 128*1024
+
+t.start()
+
+server.zone_wait(zone)
+
+for i in range(100):
+    up = server.update(zone)
+    for j in range(10):
+        up.add("abc%dxyz%d" % (i, j), 3600, "A", "1.2.3.4")
+    up.send()
+    t.sleep(0.5)
+    if server.log_search("enough space"):
+        break
+
+up = server.update(zone)
+up.add("final", 3600, "A", "1.2.3.4")
+up.send()
+
+last_fail_logs = server.log_search_count("signing had failed")
+
+if last_fail_logs < 1 or last_fail_logs > 3:
+    set_err("SIGN FAILED WARNING (%d)" % last_fail_logs)
+
+for z in zone:
+    server.zone_verify(z) # this should still pass since rrsig-refresh is comfortably high
+
+t.end()