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)",
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;
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) {
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;
}
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));
"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. */
-/* 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
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;
/*!
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;
/*!
--- /dev/null
+#!/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()