+5515. [func] Add 'rndc dnssec -rollover' command to trigger a
+ manual rollover for a specific key. [GL #1749]
+
5514. [bug] Fix KASP expected key size for Ed25519 and Ed448.
[GL #2171]
dns_kasp_t *kasp = NULL;
dns_dnsseckeylist_t keys;
dns_dnsseckey_t *key;
- char *ptr;
+ char *ptr, *zonetext = NULL;
const char *msg = NULL;
/* variables for -checkds */
- bool checkds = false, dspublish = false, use_keyid = false;
+ bool checkds = false, dspublish = false;
+ /* variables for -rollover */
+ bool rollover = false;
+ /* variables for -key */
+ bool use_keyid = false;
dns_keytag_t keyid = 0;
uint8_t algorithm = 0;
/* variables for -status */
if (strcasecmp(ptr, "-status") == 0) {
status = true;
+ } else if (strcasecmp(ptr, "-rollover") == 0) {
+ rollover = true;
} else if (strcasecmp(ptr, "-checkds") == 0) {
checkds = true;
+ } else {
+ CHECK(DNS_R_SYNTAX);
+ }
+ if (rollover || checkds) {
/* Check for options */
for (;;) {
ptr = next_token(lex, text);
} else if (ptr[0] == '-') {
msg = "Unknown option";
CHECK(DNS_R_SYNTAX);
- } else {
+ } else if (checkds) {
/*
* No arguments provided, so we must be
* parsing "published|withdrawn".
} else if (strcasecmp(ptr, "withdrawn") != 0) {
CHECK(DNS_R_SYNTAX);
}
+ } else if (rollover) {
+ /*
+ * No arguments provided, so we must be
+ * parsing the zone.
+ */
+ zonetext = ptr;
}
break;
}
+ if (rollover && !use_keyid) {
+ msg = "Key id is required when scheduling rollover";
+ CHECK(DNS_R_SYNTAX);
+ }
+
if (algorithm > 0 && !use_keyid) {
msg = "Key id is required when setting algorithm";
CHECK(DNS_R_SYNTAX);
}
- } else {
- CHECK(DNS_R_SYNTAX);
}
/* Get zone. */
- CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false));
+ CHECK(zone_from_args(server, lex, zonetext, &zone, NULL, text, false));
if (zone == NULL) {
msg = "Zone not found";
CHECK(ISC_R_UNEXPECTEDEND);
LOCK(&kasp->lock);
if (use_keyid) {
- result = dns_keymgr_checkds_id(kasp, &keys, dir, when,
- dspublish, keyid,
+ result = dns_keymgr_checkds_id(kasp, &keys, dir, now,
+ when, dspublish, keyid,
(unsigned int)algorithm);
} else {
- result = dns_keymgr_checkds(kasp, &keys, dir, when,
+ result = dns_keymgr_checkds(kasp, &keys, dir, now, when,
dspublish);
}
UNLOCK(&kasp->lock);
CHECK(putstr(text, "Error executing checkds command"));
break;
}
+ } else if (rollover) {
+ /*
+ * Manually rollover a key.
+ */
+ char whenbuf[80];
+ isc_time_set(&timewhen, when, 0);
+ isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf));
+
+ LOCK(&kasp->lock);
+ result = dns_keymgr_rollover(kasp, &keys, dir, now, when, keyid,
+ (unsigned int)algorithm);
+ UNLOCK(&kasp->lock);
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ if (use_keyid) {
+ char tagbuf[6];
+ snprintf(tagbuf, sizeof(tagbuf), "%u", keyid);
+ CHECK(putstr(text, "Key "));
+ CHECK(putstr(text, tagbuf));
+ CHECK(putstr(text, ": "));
+ }
+ CHECK(putstr(text, "Rollover scheduled on "));
+ CHECK(putstr(text, whenbuf));
+ break;
+ case ISC_R_NOTFOUND:
+ CHECK(putstr(text, "No matching keyfound"));
+ break;
+ case ISC_R_FAILURE:
+ CHECK(putstr(text,
+ "Error: multiple possible keys found, "
+ "retry command with -alg algorithm"));
+ break;
+ case ISC_R_UNEXPECTED:
+ CHECK(putstr(text,
+ "Error: key is not active and cannot "
+ "be rolled at this time"));
+ break;
+ default:
+ CHECK(putstr(text, "Error executing rollover command"));
+ break;
+ }
}
CHECK(putnull(text));
specific key by providing the keytag with -key id and\n\
optionally the key's algorithm with -alg algorithm.\n\
Requires the zone to have a dnssec-policy.\n\
+ dnssec -rollover -key id [-alg algorithm] [-when time] zone [class [view]]\n\
+ Rollover key with id of the given zone. Requires the zone\n\
+ to have a dnssec-policy.\n\
dnssec -status zone [class [view]]\n\
Show the DNSSEC signing state for the specified zone.\n\
Requires the zone to have a dnssec-policy.\n\
See also ``rndc addzone`` and ``rndc modzone``.
-``dnssec`` ( **-status** | **-checkds** [**-key** *id* [**-alg** *algorithm*]] [**-when** *time*] ( *published* | *withdrawn* )) *zone* [*class* [*view*]]
+``dnssec`` ( **-status** |
+ **-rollover** **-key** id [**-alg** *algorithm*] [**-when** *time*] |
+ **-checkds** [**-key** *id* [**-alg** *algorithm*]] [**-when** *time*] ( *published* | *withdrawn* )
+ ) *zone* [*class* [*view*]]
This command allows you to interact with the "dnssec-policy" of a given
zone.
``rndc dnssec -status`` show the DNSSEC signing state for the specified
zone.
+ ``rndc dnssec -rollover`` allows you to schedule key rollover for a
+ specific key (overriding the original key lifetime).
+
``rndc dnssec -checkds`` will let ``named`` know that the DS for the given
key has been seen published into or withdrawn from the parent. This is
required in order to complete a KSK rollover. If the ``-key id`` argument
dnssec-policy "unlimited";
};
+/* Manual rollover. */
+zone "manual-rollover.kasp" {
+ type primary;
+ file "manual-rollover.kasp.db";
+ dnssec-policy "manual-rollover";
+};
+
/* A master zone with dnssec-policy, no keys created. */
zone "rsasha1.kasp" {
type primary;
};
};
+dnssec-policy "manual-rollover" {
+ dnskey-ttl 3600;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm 13;
+ zsk key-directory lifetime unlimited algorithm 13;
+ };
+};
+
dnssec-policy "rsasha1" {
dnskey-ttl 1234;
for zn in default rsasha1 dnssec-keygen some-keys legacy-keys pregenerated \
rumoured rsasha1-nsec3 rsasha256 rsasha512 ecdsa256 ecdsa384 \
dynamic dynamic-inline-signing inline-signing \
- checkds-ksk checkds-doubleksk checkds-csk inherit unlimited
+ checkds-ksk checkds-doubleksk checkds-csk inherit unlimited \
+ manual-rollover
do
setup "${zn}.kasp"
cp template.db.in "$zonefile"
# Set up zones that are already signed.
#
+# Zone to test manual rollover.
+setup manual-rollover.kasp
+T="now-1d"
+ksktimes="-P $T -A $T -P sync $T"
+zsktimes="-P $T -A $T"
+KSK=$($KEYGEN -a ECDSAP256SHA256 -L 3600 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a ECDSAP256SHA256 -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone 13 "$KSK" >> "$infile"
+private_type_record $zone 13 "$ZSK" >> "$infile"
+$SIGNER -PS -x -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
+
# These signatures are set to expire long in the past, update immediately.
setup expired-sigs.autosign
T="now-6mo"
}
#
-# rndc dnssec -checkds
+# Utility to call after 'rndc dnssec -checkds|-rollover'.
#
_loadkeys_on() {
_server=$1
_loadkeys_on $_server $_dir $_zone || log_error "loadkeys zone ${_zone} failed ($n)"
}
+# Tell named to schedule a key rollover.
+rndc_rollover() {
+ _server=$1
+ _dir=$2
+ _keyid=$3
+ _when=$4
+ _zone=$5
+ _view=$6
+
+ n=$((n+1))
+ echo_i "calling rndc dnssec -rollover key ${_keyid} zone ${_zone} ($n)"
+ ret=0
+
+ if [ "${_when}" = "now" ]; then
+ rndccmd $_server dnssec -rollover -key $_keyid $_zone in $_view > rndc.dnssec.rollover.out.$_zone.$n || log_error "rndc dnssec -rollover (key ${_keyid} when ${_when}) zone ${_zone} failed"
+ else
+ rndccmd $_server dnssec -rollover -key $_keyid -when $_when $_zone in $_view > rndc.dnssec.rollover.out.$_zone.$n || log_error "rndc dnssec -rollover (key ${_keyid} when ${_when}) zone ${_zone} failed"
+ fi
+
+ _loadkeys_on $_server $_dir $_zone || log_error "loadkeys zone ${_zone} failed ($n)"
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
#
# Zone: default.kasp.
#
# Clear TSIG.
TSIG=""
+#
+# Testing manual rollover.
+#
+set_zone "manual-rollover.kasp"
+set_policy "manual-rollover" "2" "3600"
+set_server "ns3" "10.53.0.3"
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+# Key properties.
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "0"
+set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+# During set up everything was set to OMNIPRESENT.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# The first keys were published and activated a day ago.
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -86400
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -86400
+set_addkeytime "KEY1" "ACTIVE" "${created}" -86400
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -86400
+set_addkeytime "KEY2" "ACTIVE" "${created}" -86400
+# Key lifetimes are unlimited, so not setting RETIRED and REMOVED.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Schedule KSK rollover in six months (15552000 seconds).
+active=$(key_get KEY1 ACTIVE)
+set_addkeytime "KEY1" "RETIRED" "${active}" 15552000
+retired=$(key_get KEY1 RETIRED)
+rndc_rollover "$SERVER" "$DIR" $(key_get KEY1 ID) "${retired}" "$ZONE"
+# Rollover starts in six months, but lifetime is set to six months plus
+# prepublication duration = 15552000 + 7500 = 15559500 seconds.
+set_keylifetime "KEY1" "15559500"
+set_addkeytime "KEY1" "RETIRED" "${active}" 15559500
+retired=$(key_get KEY1 RETIRED)
+# Retire interval of this policy is 26h (93600 seconds).
+set_addkeytime "KEY1" "REMOVED" "${retired}" 93600
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Schedule KSK rollover now.
+set_policy "manual-rollover" "3" "3600"
+set_keystate "KEY1" "GOAL" "hidden"
+# This key was activated one day agao, so lifetime is set to 1d plus
+# prepublication duration (7500 seconds) = 93900 seconds.
+set_keylifetime "KEY1" "93900"
+created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "RETIRED" "${created}"
+rndc_rollover "$SERVER" "$DIR" $(key_get KEY1 ID) "${created}" "$ZONE"
+# New key is introduced.
+set_keyrole "KEY3" "ksk"
+set_keylifetime "KEY3" "0"
+set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY3" "yes"
+set_zonesigning "KEY3" "no"
+
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY3" "STATE_DS" "hidden"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Schedule ZSK rollover now.
+set_policy "manual-rollover" "4" "3600"
+set_keystate "KEY2" "GOAL" "hidden"
+# This key was activated one day agao, so lifetime is set to 1d plus
+# prepublication duration (7500 seconds) = 93900 seconds.
+set_keylifetime "KEY2" "93900"
+created=$(key_get KEY2 CREATED)
+set_keytime "KEY2" "RETIRED" "${created}"
+rndc_rollover "$SERVER" "$DIR" $(key_get KEY2 ID) "${created}" "$ZONE"
+# New key is introduced.
+set_keyrole "KEY4" "zsk"
+set_keylifetime "KEY4" "0"
+set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY4" "no"
+set_zonesigning "KEY4" "no" # not yet, first prepublish DNSKEY.
+
+set_keystate "KEY4" "GOAL" "omnipresent"
+set_keystate "KEY4" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY4" "STATE_ZRRSIG" "hidden"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
#
# Testing DNSSEC introduction.
#
.sp
See also \fBrndc addzone\fP and \fBrndc modzone\fP\&.
.TP
-\fBdnssec\fP ( \fB\-status\fP | \fB\-checkds\fP [\fB\-key\fP \fIid\fP [\fB\-alg\fP \fIalgorithm\fP]] [\fB\-when\fP \fItime\fP] ( \fIpublished\fP | \fIwithdrawn\fP )) \fIzone\fP [\fIclass\fP [\fIview\fP]]
+\fBdnssec\fP ( \fB\-status\fP |
+.INDENT 7.0
+.INDENT 3.5
+.INDENT 0.0
+.INDENT 3.5
+\fB\-rollover\fP \fB\-key\fP id [\fB\-alg\fP \fIalgorithm\fP] [\fB\-when\fP \fItime\fP] |
+\fB\-checkds\fP [\fB\-key\fP \fIid\fP [\fB\-alg\fP \fIalgorithm\fP]] [\fB\-when\fP \fItime\fP] ( \fIpublished\fP | \fIwithdrawn\fP )
+.UNINDENT
+.UNINDENT
+.sp
+) \fIzone\fP [\fIclass\fP [\fIview\fP]]
+.UNINDENT
+.UNINDENT
+.sp
This command allows you to interact with the "dnssec\-policy" of a given
zone.
.sp
\fBrndc dnssec \-status\fP show the DNSSEC signing state for the specified
zone.
.sp
+\fBrndc dnssec \-rollover\fP allows you to schedule key rollover for a
+specific key (overriding the original key lifetime).
+.sp
\fBrndc dnssec \-checkds\fP will let \fBnamed\fP know that the DS for the given
key has been seen published into or withdrawn from the parent. This is
required in order to complete a KSK rollover. If the \fB\-key id\fP argument
- None.
+- Add a new ``rndc`` command, ``rndc dnssec -rollover``, which triggers
+ a manual rollover for a specific key. [GL #1749]
+
- New ``rndc`` command ``rndc dumpdb -expired`` that dumps the cache database
to the dump-file including expired RRsets that are awaiting cleanup, for
diagnostic purposes. [GL #1870]
- None.
+
Feature Changes
~~~~~~~~~~~~~~~