From 2a4daaedca0f5e24d362acf1e12c1710489e9a86 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 31 Jan 2024 16:52:32 +0100 Subject: [PATCH 1/6] Add signatures-jitter option Add an option to speficy signatures jitter. --- bin/named/config.c | 1 + bin/tests/system/checkconf/good-kasp.conf | 1 + bin/tests/system/checkconf/good.conf.in | 1 + doc/arm/reference.rst | 10 +++++++++ doc/misc/dnssec-policy.default.conf | 1 + doc/misc/options | 1 + lib/dns/include/dns/kasp.h | 26 +++++++++++++++++++++++ lib/dns/kasp.c | 16 ++++++++++++++ lib/isccfg/kaspconf.c | 6 +++++- lib/isccfg/namedconf.c | 1 + 10 files changed, 63 insertions(+), 1 deletion(-) diff --git a/bin/named/config.c b/bin/named/config.c index b1d6c04b3f..56e58d285a 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -298,6 +298,7 @@ dnssec-policy \"default\" {\n\ publish-safety " DNS_KASP_PUBLISH_SAFETY "; \n\ retire-safety " DNS_KASP_RETIRE_SAFETY "; \n\ purge-keys " DNS_KASP_PURGE_KEYS "; \n\ + signatures-jitter " DNS_KASP_SIG_JITTER "; \n\ signatures-refresh " DNS_KASP_SIG_REFRESH "; \n\ signatures-validity " DNS_KASP_SIG_VALIDITY "; \n\ signatures-validity-dnskey " DNS_KASP_SIG_VALIDITY_DNSKEY "; \n\ diff --git a/bin/tests/system/checkconf/good-kasp.conf b/bin/tests/system/checkconf/good-kasp.conf index 95ba817b3b..42e2478f96 100644 --- a/bin/tests/system/checkconf/good-kasp.conf +++ b/bin/tests/system/checkconf/good-kasp.conf @@ -34,6 +34,7 @@ dnssec-policy "test" { parent-propagation-delay PT1H; publish-safety PT3600S; retire-safety PT3600S; + signatures-jitter PT12H; signatures-refresh P3D; signatures-validity P2W; signatures-validity-dnskey P14D; diff --git a/bin/tests/system/checkconf/good.conf.in b/bin/tests/system/checkconf/good.conf.in index 2fde415a40..076ecc432d 100644 --- a/bin/tests/system/checkconf/good.conf.in +++ b/bin/tests/system/checkconf/good.conf.in @@ -34,6 +34,7 @@ dnssec-policy "test" { publish-safety PT3600S; purge-keys P90D; retire-safety PT3600S; + signatures-jitter PT12H; signatures-refresh P3D; signatures-validity P2W; signatures-validity-dnskey P14D; diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index df24019828..e9341671cd 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -6479,6 +6479,16 @@ The following options can be specified in a :any:`dnssec-policy` statement: unforeseen events. This increases the time a key remains published after it is no longer active. The default is ``PT1H`` (1 hour). +.. namedconf:statement:: signatures-jitter + :tags: dnssec + :short: Specifies a range for signatures expirations. + + To prevent all signatures from expiring at the same moment, BIND 9 may + vary the validity interval of individual signatures. The validity of a + newly generated signatures is in range between :any:`signatures-validity` + (maximum) and :any:`signatures-validity` minus :any:`signatures-jitter` + (minimum). The default jitter is 12 hours. + .. namedconf:statement:: signatures-refresh :tags: dnssec :short: Specifies how frequently an RRSIG record is refreshed. diff --git a/doc/misc/dnssec-policy.default.conf b/doc/misc/dnssec-policy.default.conf index cd033c1760..a6f526c743 100644 --- a/doc/misc/dnssec-policy.default.conf +++ b/doc/misc/dnssec-policy.default.conf @@ -26,6 +26,7 @@ dnssec-policy "default" { purge-keys P90D; // Signature timings + signatures-jitter 12h; signatures-refresh 5d; signatures-validity 14d; signatures-validity-dnskey 14d; diff --git a/doc/misc/options b/doc/misc/options index 1142bb6f18..7c94dcd180 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -23,6 +23,7 @@ dnssec-policy { publish-safety ; purge-keys ; retire-safety ; + signatures-jitter ; signatures-refresh ; signatures-validity ; signatures-validity-dnskey ; diff --git a/lib/dns/include/dns/kasp.h b/lib/dns/include/dns/kasp.h index 42fe126396..3b8c68e0f2 100644 --- a/lib/dns/include/dns/kasp.h +++ b/lib/dns/include/dns/kasp.h @@ -83,6 +83,7 @@ struct dns_kasp { ISC_LINK(struct dns_kasp) link; /* Configuration: signatures */ + uint32_t signatures_jitter; uint32_t signatures_refresh; uint32_t signatures_validity; uint32_t signatures_validity_dnskey; @@ -116,6 +117,7 @@ struct dns_kasp { #define DNS_KASP_VALID(kasp) ISC_MAGIC_VALID(kasp, DNS_KASP_MAGIC) /* Defaults */ +#define DNS_KASP_SIG_JITTER "PT12H" #define DNS_KASP_SIG_REFRESH "P5D" #define DNS_KASP_SIG_VALIDITY "P14D" #define DNS_KASP_SIG_VALIDITY_DNSKEY "P14D" @@ -244,6 +246,30 @@ dns_kasp_signdelay(dns_kasp_t *kasp); *\li signature refresh interval. */ +uint32_t +dns_kasp_sigjitter(dns_kasp_t *kasp); +/*%< + * Get signature jitter value. + * + * Requires: + * + *\li 'kasp' is a valid, frozen kasp. + * + * Returns: + * + *\li signature jitter value. + */ + +void +dns_kasp_setsigjitter(dns_kasp_t *kasp, uint32_t value); +/*%< + * Set signature jitter value. + * + * Requires: + * + *\li 'kasp' is a valid, thawed kasp. + */ + uint32_t dns_kasp_sigrefresh(dns_kasp_t *kasp); /*%< diff --git a/lib/dns/kasp.c b/lib/dns/kasp.c index 8658fd629c..b6a54a1074 100644 --- a/lib/dns/kasp.c +++ b/lib/dns/kasp.c @@ -138,6 +138,22 @@ dns_kasp_signdelay(dns_kasp_t *kasp) { return (kasp->signatures_validity - kasp->signatures_refresh); } +uint32_t +dns_kasp_sigjitter(dns_kasp_t *kasp) { + REQUIRE(DNS_KASP_VALID(kasp)); + REQUIRE(kasp->frozen); + + return (kasp->signatures_jitter); +} + +void +dns_kasp_setsigjitter(dns_kasp_t *kasp, uint32_t value) { + REQUIRE(DNS_KASP_VALID(kasp)); + REQUIRE(!kasp->frozen); + + kasp->signatures_jitter = value; +} + uint32_t dns_kasp_sigrefresh(dns_kasp_t *kasp) { REQUIRE(DNS_KASP_VALID(kasp)); diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index f756ed97da..9b65b63608 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -412,7 +412,7 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp, const char *kaspname = NULL; dns_kasp_t *kasp = NULL; size_t i = 0; - uint32_t sigrefresh = 0, sigvalidity = 0; + uint32_t sigjitter = 0, sigrefresh = 0, sigvalidity = 0; uint32_t dnskeyttl = 0, dsttl = 0, maxttl = 0; uint32_t publishsafety = 0, retiresafety = 0; uint32_t zonepropdelay = 0, parentpropdelay = 0; @@ -460,6 +460,10 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp, maps[i] = NULL; /* Configuration: Signatures */ + sigjitter = get_duration(maps, "signatures-jitter", + DNS_KASP_SIG_JITTER); + dns_kasp_setsigjitter(kasp, sigjitter); + sigrefresh = get_duration(maps, "signatures-refresh", DNS_KASP_SIG_REFRESH); dns_kasp_setsigrefresh(kasp, sigrefresh); diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 5c50c586f1..70bf565f19 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -2281,6 +2281,7 @@ static cfg_clausedef_t dnssecpolicy_clauses[] = { { "publish-safety", &cfg_type_duration, 0 }, { "purge-keys", &cfg_type_duration, 0 }, { "retire-safety", &cfg_type_duration, 0 }, + { "signatures-jitter", &cfg_type_duration, 0 }, { "signatures-refresh", &cfg_type_duration, 0 }, { "signatures-validity", &cfg_type_duration, 0 }, { "signatures-validity-dnskey", &cfg_type_duration, 0 }, From 50bd729019c5ac30f3bfef6cbd153537f9520782 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 1 Feb 2024 16:33:21 +0100 Subject: [PATCH 2/6] Update autosign test to use signatures-jitter Now that we have an option to configure jitter, use it in system tests that test jitter. --- bin/tests/system/autosign/ns3/named.conf.in | 1 + bin/tests/system/autosign/tests.sh | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/tests/system/autosign/ns3/named.conf.in b/bin/tests/system/autosign/ns3/named.conf.in index 9bc5d655e1..2316de2932 100644 --- a/bin/tests/system/autosign/ns3/named.conf.in +++ b/bin/tests/system/autosign/ns3/named.conf.in @@ -87,6 +87,7 @@ dnssec-policy "jitter" { signatures-validity P10D; signatures-validity-dnskey P10D; signatures-refresh P2D; + signatures-jitter P8D; }; # Jitter, NSEC3 diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh index 1839738966..3b7613226d 100755 --- a/bin/tests/system/autosign/tests.sh +++ b/bin/tests/system/autosign/tests.sh @@ -91,10 +91,10 @@ checkjitter() { _count=0 # Check if we have at least 4 days - # This number has been tuned for `signatures-validity 10d; signatures-refresh 2d`, as - # 1 signature expiration dates should be spread out across at most 8 (10-2) days - # 2. we remove first and last day to remove frequency outlier, we are left with 6 (8-2) days - # 3. we subtract two more days to allow test pass on day boundaries, etc. leaving us with 4 (6-2) + # This number has been tuned for `signatures-validity 10d; signatures-jitter 8d`, as + # 1. signature expiration dates should be spread out across at most 8 days + # 2. we remove first and last day to remove frequency outlier, we are left with 6 days + # 3. we subtract two more days to allow test pass on day boundaries, etc. leaving us with 4 days for _num in $_expiretimes; do _count=$((_count + 1)) done From 0438d3655bca9d6aeea41746a01d82e5252eba64 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 31 Jan 2024 17:31:16 +0100 Subject: [PATCH 3/6] Refactor code that calculates signature validity There are three code blocks that are (almost) similar, refactor it to one function. --- lib/dns/zone.c | 132 ++++++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 83 deletions(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index cf09283221..c444709917 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -6911,6 +6911,49 @@ failure: return (result); } +static void +calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now, + isc_stdtime_t *inception, isc_stdtime_t *soaexpire, + isc_stdtime_t *expire, isc_stdtime_t *fullexpire) { + REQUIRE(inception != NULL); + REQUIRE(soaexpire != NULL); + /* expire and fullexpire are optional */ + + isc_stdtime_t sigvalidityinterval = + dns_zone_getsigvalidityinterval(zone); + isc_stdtime_t expiryinterval = dns_zone_getsigresigninginterval(zone); + isc_stdtime_t normaljitter = 0, fulljitter = 0; + + *inception = now - 3600; /* Allow for clock skew. */ + *soaexpire = now + sigvalidityinterval; + if (expiryinterval > sigvalidityinterval) { + expiryinterval = sigvalidityinterval; + } else { + expiryinterval = sigvalidityinterval - expiryinterval; + } + + /* + * Spread out signatures over time if they happen to be + * clumped. We don't do this for each add_sigs() call as + * we still want some clustering to occur. In normal operations + * the records should be re-signed as they fall due and they should + * already be spread out. However if the server is off for a + * period we need to ensure that the clusters don't become + * synchronised by using the full jitter range. + */ + if (sigvalidityinterval >= 3600U) { + if (sigvalidityinterval > 7200U) { + normaljitter = isc_random_uniform(3600); + fulljitter = isc_random_uniform(expiryinterval); + } else { + normaljitter = fulljitter = isc_random_uniform(1200); + } + } + + SET_IF_NOT_NULL(expire, *soaexpire - normaljitter - 1); + SET_IF_NOT_NULL(fullexpire, *soaexpire - fulljitter - 1); +} + static void zone_resigninc(dns_zone_t *zone) { dns_db_t *db = NULL; @@ -6924,7 +6967,6 @@ zone_resigninc(dns_zone_t *zone) { dst_key_t *zone_keys[DNS_MAXZONEKEYS]; isc_result_t result; isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop; - uint32_t sigvalidityinterval, expiryinterval; unsigned int i; unsigned int nkeys = 0; unsigned int resign; @@ -6972,38 +7014,9 @@ zone_resigninc(dns_zone_t *zone) { goto failure; } - sigvalidityinterval = dns_zone_getsigvalidityinterval(zone); - inception = now - 3600; /* Allow for clock skew. */ - soaexpire = now + sigvalidityinterval; - expiryinterval = dns_zone_getsigresigninginterval(zone); - if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } + calculate_rrsig_validity(zone, now, &inception, &soaexpire, &expire, + &fullexpire); - /* - * Spread out signatures over time if they happen to be - * clumped. We don't do this for each add_sigs() call as - * we still want some clustering to occur. In normal operations - * the records should be re-signed as they fall due and they should - * already be spread out. However if the server is off for a - * period we need to ensure that the clusters don't become - * synchronised by using the full jitter range. - */ - if (sigvalidityinterval >= 3600U) { - uint32_t normaljitter, fulljitter; - if (sigvalidityinterval > 7200U) { - normaljitter = isc_random_uniform(3600); - fulljitter = isc_random_uniform(expiryinterval); - } else { - normaljitter = fulljitter = isc_random_uniform(1200); - } - expire = soaexpire - normaljitter - 1; - fullexpire = soaexpire - fulljitter - 1; - } else { - expire = fullexpire = soaexpire - 1; - } stop = now + 5; name = dns_fixedname_initname(&fixed); @@ -8138,7 +8151,6 @@ zone_nsec3chain(dns_zone_t *zone) { bool first; isc_result_t result; isc_stdtime_t now, inception, soaexpire, expire; - uint32_t jitter, sigvalidityinterval, expiryinterval; unsigned int i; unsigned int nkeys = 0; uint32_t nodes; @@ -8207,31 +8219,8 @@ zone_nsec3chain(dns_zone_t *zone) { goto failure; } - sigvalidityinterval = dns_zone_getsigvalidityinterval(zone); - inception = now - 3600; /* Allow for clock skew. */ - soaexpire = now + sigvalidityinterval; - expiryinterval = dns_zone_getsigresigninginterval(zone); - if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } - - /* - * Spread out signatures over time if they happen to be - * clumped. We don't do this for each add_sigs() call as - * we still want some clustering to occur. - */ - if (sigvalidityinterval >= 3600U) { - if (sigvalidityinterval > 7200U) { - jitter = isc_random_uniform(expiryinterval); - } else { - jitter = isc_random_uniform(1200); - } - expire = soaexpire - jitter - 1; - } else { - expire = soaexpire - 1; - } + calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL, + &expire); /* * We keep pulling nodes off each iterator in turn until @@ -9240,7 +9229,6 @@ zone_sign(dns_zone_t *zone) { bool first; isc_result_t result; isc_stdtime_t now, inception, soaexpire, expire; - uint32_t jitter, sigvalidityinterval, expiryinterval; unsigned int i, j; unsigned int nkeys = 0; uint32_t nodes; @@ -9293,31 +9281,9 @@ zone_sign(dns_zone_t *zone) { } kasp = zone->kasp; - sigvalidityinterval = dns_zone_getsigvalidityinterval(zone); - inception = now - 3600; /* Allow for clock skew. */ - soaexpire = now + sigvalidityinterval; - expiryinterval = dns_zone_getsigresigninginterval(zone); - if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } - /* - * Spread out signatures over time if they happen to be - * clumped. We don't do this for each add_sigs() call as - * we still want some clustering to occur. - */ - if (sigvalidityinterval >= 3600U) { - if (sigvalidityinterval > 7200U) { - jitter = isc_random_uniform(expiryinterval); - } else { - jitter = isc_random_uniform(1200); - } - expire = soaexpire - jitter - 1; - } else { - expire = soaexpire - 1; - } + calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL, + &expire); /* * We keep pulling nodes off each iterator in turn until From 67f403a42371f943751a28411ded61949ca83fdf Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 1 Feb 2024 09:34:33 +0100 Subject: [PATCH 4/6] Implement signature jitter When calculating the RRSIG validity, jitter is now derived from the config option rather than from the refresh value. --- lib/dns/include/dns/kasp.h | 1 + lib/dns/update.c | 33 +++++++++++++++++---------------- lib/dns/zone.c | 31 +++++++++++++++---------------- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/dns/include/dns/kasp.h b/lib/dns/include/dns/kasp.h index 3b8c68e0f2..cd8a5bd13f 100644 --- a/lib/dns/include/dns/kasp.h +++ b/lib/dns/include/dns/kasp.h @@ -117,6 +117,7 @@ struct dns_kasp { #define DNS_KASP_VALID(kasp) ISC_MAGIC_VALID(kasp, DNS_KASP_MAGIC) /* Defaults */ +#define DEFAULT_JITTER (12 * 3600) #define DNS_KASP_SIG_JITTER "PT12H" #define DNS_KASP_SIG_REFRESH "P5D" #define DNS_KASP_SIG_VALIDITY "P14D" diff --git a/lib/dns/update.c b/lib/dns/update.c index cbcbe1c139..1302bb4dba 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -1477,23 +1477,25 @@ struct dns_update_state { }; static uint32_t -dns__jitter_expire(dns_zone_t *zone, uint32_t sigvalidityinterval) { +dns__jitter_expire(dns_zone_t *zone) { /* Spread out signatures over time */ - if (sigvalidityinterval >= 3600U) { - uint32_t expiryinterval = - dns_zone_getsigresigninginterval(zone); + isc_stdtime_t jitter = DEFAULT_JITTER; + isc_stdtime_t sigvalidity = dns_zone_getsigvalidityinterval(zone); + dns_kasp_t *kasp = dns_zone_getkasp(zone); - if (sigvalidityinterval < 7200U) { - expiryinterval = 1200; - } else if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } - uint32_t jitter = isc_random_uniform(expiryinterval); - sigvalidityinterval -= jitter; + if (kasp != NULL) { + jitter = dns_kasp_sigjitter(kasp); + sigvalidity = dns_kasp_sigvalidity(kasp); } - return (sigvalidityinterval); + + if (sigvalidity >= 3600U) { + if (sigvalidity > 7200U) { + sigvalidity -= isc_random_uniform(jitter); + } else { + sigvalidity -= isc_random_uniform(1200); + } + } + return (sigvalidity); } isc_result_t @@ -1549,8 +1551,7 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, state->now = isc_stdtime_now(); state->inception = state->now - 3600; /* Allow for some clock skew. */ - state->expire = state->now + - dns__jitter_expire(zone, sigvalidityinterval); + state->expire = state->now + dns__jitter_expire(zone); state->soaexpire = state->now + sigvalidityinterval; state->keyexpire = dns_zone_getkeyvalidityinterval(zone); if (state->keyexpire == 0) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index c444709917..5d6a2428ae 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -6919,18 +6919,17 @@ calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now, REQUIRE(soaexpire != NULL); /* expire and fullexpire are optional */ - isc_stdtime_t sigvalidityinterval = - dns_zone_getsigvalidityinterval(zone); - isc_stdtime_t expiryinterval = dns_zone_getsigresigninginterval(zone); - isc_stdtime_t normaljitter = 0, fulljitter = 0; + isc_stdtime_t jitter = DEFAULT_JITTER; + isc_stdtime_t sigvalidity = dns_zone_getsigvalidityinterval(zone); + isc_stdtime_t shortjitter = 0, fulljitter = 0; + + if (zone->kasp != NULL) { + jitter = dns_kasp_sigjitter(zone->kasp); + sigvalidity = dns_kasp_sigvalidity(zone->kasp); + } *inception = now - 3600; /* Allow for clock skew. */ - *soaexpire = now + sigvalidityinterval; - if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } + *soaexpire = now + sigvalidity; /* * Spread out signatures over time if they happen to be @@ -6941,16 +6940,16 @@ calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now, * period we need to ensure that the clusters don't become * synchronised by using the full jitter range. */ - if (sigvalidityinterval >= 3600U) { - if (sigvalidityinterval > 7200U) { - normaljitter = isc_random_uniform(3600); - fulljitter = isc_random_uniform(expiryinterval); + if (sigvalidity >= 3600U) { + if (sigvalidity > 7200U) { + shortjitter = isc_random_uniform(3600); + fulljitter = isc_random_uniform(jitter); } else { - normaljitter = fulljitter = isc_random_uniform(1200); + shortjitter = fulljitter = isc_random_uniform(1200); } } - SET_IF_NOT_NULL(expire, *soaexpire - normaljitter - 1); + SET_IF_NOT_NULL(expire, *soaexpire - shortjitter - 1); SET_IF_NOT_NULL(fullexpire, *soaexpire - fulljitter - 1); } From 8b7785bc237997342647c4ef47d996e9cab55b91 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 1 Feb 2024 09:50:40 +0100 Subject: [PATCH 5/6] Add release notes and CHANGES for #4554 Mention the new signature jitter option. --- CHANGES | 2 ++ doc/notes/notes-current.rst | 3 +++ 2 files changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index ffd0749d42..dcf18af4a0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +6372. [func] Implement signature jitter for dnssec-policy. [GL #4554] + 6371. [bug] Access to the trust bytes in the ncache data needed to be made thread safe. [GL #4475] diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index 5fbe33da5c..9812b77e46 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -22,6 +22,9 @@ New Features - None. +- A new option :any:`signatures-jitter` is added to :any:`dnssec-policy` to + spread out signature expiration times over a period of time. :gl:`#4554` + Removed Features ~~~~~~~~~~~~~~~~ From c3d8932f79907bf55580bc0ff86f38343a785914 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Tue, 16 Apr 2024 15:49:13 +0200 Subject: [PATCH 6/6] Add checkconf check for signatures-jitter Having a value higher than signatures-validity does not make sense and should be treated as a configuration error. --- .../system/checkconf/bad-kasp-jitter.conf | 27 +++++++++++++++++++ doc/arm/reference.rst | 4 ++- lib/dns/update.c | 5 ++++ lib/dns/zone.c | 5 ++++ lib/isccfg/kaspconf.c | 18 +++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 bin/tests/system/checkconf/bad-kasp-jitter.conf diff --git a/bin/tests/system/checkconf/bad-kasp-jitter.conf b/bin/tests/system/checkconf/bad-kasp-jitter.conf new file mode 100644 index 0000000000..e358957437 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-jitter.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The dnssec-policy jitter is more than signatures-validity, + * which is not allowed. + */ +dnssec-policy high-jitter { + signatures-jitter P8DT1S; + signatures-validity P8D; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy high-jitter; +}; diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index e9341671cd..aab79e9064 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -6487,7 +6487,9 @@ The following options can be specified in a :any:`dnssec-policy` statement: vary the validity interval of individual signatures. The validity of a newly generated signatures is in range between :any:`signatures-validity` (maximum) and :any:`signatures-validity` minus :any:`signatures-jitter` - (minimum). The default jitter is 12 hours. + (minimum). The default jitter is 12 hours and the configured value must + be lower than :any:`signatures-validity` and + :any:`signatures-validity-dnskey`. .. namedconf:statement:: signatures-refresh :tags: dnssec diff --git a/lib/dns/update.c b/lib/dns/update.c index 1302bb4dba..a6b8f2adf4 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -1486,6 +1486,11 @@ dns__jitter_expire(dns_zone_t *zone) { if (kasp != NULL) { jitter = dns_kasp_sigjitter(kasp); sigvalidity = dns_kasp_sigvalidity(kasp); + INSIST(jitter <= sigvalidity); + } + + if (jitter > sigvalidity) { + jitter = sigvalidity; } if (sigvalidity >= 3600U) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 5d6a2428ae..c70579e0af 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -6926,6 +6926,11 @@ calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now, if (zone->kasp != NULL) { jitter = dns_kasp_sigjitter(zone->kasp); sigvalidity = dns_kasp_sigvalidity(zone->kasp); + INSIST(jitter <= sigvalidity); + } + + if (jitter > sigvalidity) { + jitter = sigvalidity; } *inception = now - 3600; /* Allow for clock skew. */ diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index 9b65b63608..419818f257 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -480,6 +480,15 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp, } dns_kasp_setsigvalidity_dnskey(kasp, sigvalidity); + if (sigjitter > sigvalidity) { + cfg_obj_log( + config, logctx, ISC_LOG_ERROR, + "dnssec-policy: policy '%s' signatures-jitter cannot " + "be larger than signatures-validity-dnskey", + kaspname); + result = ISC_R_FAILURE; + } + sigvalidity = get_duration(maps, "signatures-validity", DNS_KASP_SIG_VALIDITY); if (sigrefresh >= (sigvalidity * 0.9)) { @@ -492,6 +501,15 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp, } dns_kasp_setsigvalidity(kasp, sigvalidity); + if (sigjitter > sigvalidity) { + cfg_obj_log( + config, logctx, ISC_LOG_ERROR, + "dnssec-policy: policy '%s' signatures-jitter cannot " + "be larger than signatures-validity", + kaspname); + result = ISC_R_FAILURE; + } + if (result != ISC_R_SUCCESS) { goto cleanup; }