diff --git a/doc/man/knot.conf.5in b/doc/man/knot.conf.5in index fe72a9af9d0f3c41b938a91ca8baa6fbf7e8c175..ca403a36afe14e82f50e0d1a4a0784fd7578dd5d 100644 --- a/doc/man/knot.conf.5in +++ b/doc/man/knot.conf.5in @@ -1220,6 +1220,7 @@ policy: zone\-max\-ttl: TIME ksk\-lifetime: TIME zsk\-lifetime: TIME + delete\-delay: TIME propagation\-delay: TIME rrsig\-lifetime: TIME rrsig\-refresh: TIME @@ -1399,6 +1400,14 @@ Zero (aka infinity) value causes no ZSK rollover as a result. .UNINDENT .sp \fIDefault:\fP 30 days +.SS delete\-delay +.sp +Once a key (KSK or ZSK) is rolled\-over and removed from the zone, +keep it in the KASP database for at least this period before deleting it completely. +This might be useful in some troubleshooting cases when resurrection +is needed. +.sp +\fIDefault:\fP 0 .SS propagation\-delay .sp An extra delay added for each key rollover step. This value should be high diff --git a/doc/reference.rst b/doc/reference.rst index 9eddc5ed516d45fa658aa1630d7fe0486f47bc39..14249b4495c822948ccb1e4e71aa4846a045088c 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -1314,6 +1314,7 @@ DNSSEC policy configuration. zone-max-ttl: TIME ksk-lifetime: TIME zsk-lifetime: TIME + delete-delay: TIME propagation-delay: TIME rrsig-lifetime: TIME rrsig-refresh: TIME @@ -1497,6 +1498,18 @@ A period between ZSK activation and the next rollover initiation. *Default:* 30 days +.. _policy_delete-delay: + +delete-delay +------------ + +Once a key (KSK or ZSK) is rolled-over and removed from the zone, +keep it in the KASP database for at least this period before deleting it completely. +This might be useful in some troubleshooting cases when resurrection +is needed. + +*Default:* 0 + .. _policy_propagation-delay: propagation-delay diff --git a/src/knot/conf/schema.c b/src/knot/conf/schema.c index a03c82baea2271190f1f26ae42baec8bff024a91..e2c3ddba1ac2a48c454a1003a857e64534a2a3a9 100644 --- a/src/knot/conf/schema.c +++ b/src/knot/conf/schema.c @@ -358,6 +358,7 @@ static const yp_item_t desc_policy[] = { CONF_IO_FRLD_ZONES }, { C_ZSK_LIFETIME, YP_TINT, YP_VINT = { 0, UINT32_MAX, DAYS(30), YP_STIME }, CONF_IO_FRLD_ZONES }, + { C_DELETE_DELAY, YP_TINT, YP_VINT = { 0, UINT32_MAX, 0, YP_STIME } }, { C_PROPAG_DELAY, YP_TINT, YP_VINT = { 0, UINT32_MAX, HOURS(1), YP_STIME }, CONF_IO_FRLD_ZONES }, { C_RRSIG_LIFETIME, YP_TINT, YP_VINT = { 1, UINT32_MAX, DAYS(14), YP_STIME }, diff --git a/src/knot/conf/schema.h b/src/knot/conf/schema.h index 29ae47c395347dddeb3349c2bf35a8122723f63f..ac590655a9a72d247479cdb1ae2bffbded1dce40 100644 --- a/src/knot/conf/schema.h +++ b/src/knot/conf/schema.h @@ -66,6 +66,7 @@ #define C_JOURNAL_MAX_USAGE "\x11""journal-max-usage" #define C_KASP_DB "\x07""kasp-db" #define C_KASP_DB_MAX_SIZE "\x10""kasp-db-max-size" +#define C_DELETE_DELAY "\x0C""delete-delay" #define C_KEY "\x03""key" #define C_KEYSTORE "\x08""keystore" #define C_KSK_LIFETIME "\x0C""ksk-lifetime" diff --git a/src/knot/dnssec/context.c b/src/knot/dnssec/context.c index f3a1572cc1465b5d2ecdbb5df0e55bb77d2d1f36..f43af7f13617aa3cfe1c63db3143f541311c4212 100644 --- a/src/knot/dnssec/context.c +++ b/src/knot/dnssec/context.c @@ -69,6 +69,9 @@ static void policy_load(knot_kasp_policy_t *policy, conf_t *conf, conf_val_t *id val = conf_id_get(conf, C_POLICY, C_KSK_LIFETIME, id); policy->ksk_lifetime = conf_int(&val); + val = conf_id_get(conf, C_POLICY, C_DELETE_DELAY, id); + policy->delete_delay = conf_int(&val); + val = conf_id_get(conf, C_POLICY, C_PROPAG_DELAY, id); policy->propagation_delay = conf_int(&val); diff --git a/src/knot/dnssec/kasp/policy.h b/src/knot/dnssec/kasp/policy.h index 2590b7650c77efa75d7cacd29f818dcc343645d2..fcc38e146af419df93e4458ef38215247c2c3ca9 100644 --- a/src/knot/dnssec/kasp/policy.h +++ b/src/knot/dnssec/kasp/policy.h @@ -97,6 +97,7 @@ typedef struct { uint32_t dnskey_ttl; uint32_t zsk_lifetime; // like knot_time_t uint32_t ksk_lifetime; // like knot_time_t + uint32_t delete_delay; // like knot_timediff_t bool ksk_shared; bool single_type_signing; bool sts_default; // single-type-signing was set to default value diff --git a/src/knot/dnssec/key-events.c b/src/knot/dnssec/key-events.c index 932e54310c5de7b3e3f314e4677e1d62ed6a7f5c..0c40b3fb68af44cd217184ea11f2b3dcf4aee160 100644 --- a/src/knot/dnssec/key-events.c +++ b/src/knot/dnssec/key-events.c @@ -354,7 +354,7 @@ static knot_time_t ksk_really_remove_time(knot_time_t remove_time, const kdnssec if (ctx->keep_deleted_keys) { return 0; } - return knot_time_add(remove_time, ctx->policy->ksk_lifetime); + return knot_time_add(remove_time, ctx->policy->delete_delay); } static knot_time_t zsk_really_remove_time(knot_time_t remove_time, const kdnssec_ctx_t *ctx) @@ -362,7 +362,7 @@ static knot_time_t zsk_really_remove_time(knot_time_t remove_time, const kdnssec if (ctx->keep_deleted_keys) { return 0; } - return knot_time_add(remove_time, ctx->policy->zsk_lifetime); + return knot_time_add(remove_time, ctx->policy->delete_delay); } // algorithm rollover related timers must be the same for KSK and ZSK diff --git a/tests-extra/tests/dnssec/key_rollovers/test.py b/tests-extra/tests/dnssec/key_rollovers/test.py index 65b1bbaebbfd8be9c3c96a059b7c75585529475b..12f891f042e53b9120e34a89a4aa17cf0652f558 100644 --- a/tests-extra/tests/dnssec/key_rollovers/test.py +++ b/tests-extra/tests/dnssec/key_rollovers/test.py @@ -20,11 +20,12 @@ PUB_ONLY_SCENARIO = random.choice([0, 1, 2]) PUB_ONLY_KEYS = 1 if PUB_ONLY_SCENARIO > 0 else 0 PUB_ONLY_CDS = 1 if PUB_ONLY_SCENARIO > 1 else 0 PUB_ONLY_KEYID = "" +DELETE_DELAY = random.choice([0, 2, 7, 17, 117]) DOUBLE_DS = random.choice([True, False]) CDS_DT = random.choice(["sha256", "sha384"]) -check_log("DOUBLE DS %s, cds dt %s, PUB_ONLY_KEYS %d, PUB_ONLY_CDS %d" % \ - (str(DOUBLE_DS), CDS_DT, PUB_ONLY_KEYS, PUB_ONLY_CDS)) +check_log("DOUBLE DS %s, cds dt %s, PUB_ONLY_KEYS %d, PUB_ONLY_CDS %d DELETE_DELAY %d" % \ + (str(DOUBLE_DS), CDS_DT, PUB_ONLY_KEYS, PUB_ONLY_CDS, DELETE_DELAY)) def generate_public_only(server, zone, alg): global PUB_ONLY_KEYID @@ -270,6 +271,7 @@ child.dnssec(child_zone).alg = "ECDSAP384SHA384" 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).delete_delay = DELETE_DELAY child.dnssec(child_zone).propagation_delay = 11 child.dnssec(child_zone).ksk_sbm_check = [ parent ] child.dnssec(child_zone).ksk_sbm_check_interval = 2 diff --git a/tests-extra/tools/dnstest/server.py b/tests-extra/tools/dnstest/server.py index bc42ab0229e97bec04f78411d0ba3ceade678f5a..a9b92331c24ce4d5deb4034c7e3e266ea60ab2ee 100644 --- a/tests-extra/tools/dnstest/server.py +++ b/tests-extra/tools/dnstest/server.py @@ -50,6 +50,7 @@ class ZoneDnssec(object): self.zone_max_ttl = None self.ksk_lifetime = None self.zsk_lifetime = None + self.delete_delay = None self.propagation_delay = None self.rrsig_lifetime = None self.rrsig_refresh = None @@ -1393,6 +1394,7 @@ class Knot(Server): self._str(s, "zone-max-ttl", z.dnssec.zone_max_ttl) self._str(s, "ksk-lifetime", z.dnssec.ksk_lifetime) self._str(s, "zsk-lifetime", z.dnssec.zsk_lifetime) + self._str(s, "delete-delay", z.dnssec.delete_delay) self._str(s, "propagation-delay", z.dnssec.propagation_delay) self._str(s, "rrsig-lifetime", z.dnssec.rrsig_lifetime) self._str(s, "rrsig-refresh", z.dnssec.rrsig_refresh)