Add rndc dnssec -rollover command
This command is similar in arguments as -checkds so refactor the 'named_server_dnssec' function accordingly. The only difference are that: - It does not take a "publish" or "withdrawn" argument. - It requires the key id to be set (add a check to make sure). Add tests that will trigger rollover immediately and one that schedules a test in the future.
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
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]
|
||||
|
||||
|
||||
+70
-9
@@ -14595,10 +14595,14 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
|
||||
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 */
|
||||
@@ -14629,9 +14633,15 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
|
||||
|
||||
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);
|
||||
@@ -14678,7 +14688,7 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
|
||||
} 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".
|
||||
@@ -14688,20 +14698,29 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
|
||||
} 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);
|
||||
@@ -14750,11 +14769,11 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
|
||||
|
||||
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);
|
||||
@@ -14789,6 +14808,48 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
|
||||
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));
|
||||
|
||||
|
||||
@@ -117,6 +117,9 @@ command is one of the following:\n\
|
||||
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\
|
||||
|
||||
+7
-1
@@ -161,13 +161,19 @@ Currently supported commands are:
|
||||
|
||||
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
|
||||
|
||||
@@ -73,6 +73,13 @@ zone "unlimited.kasp" {
|
||||
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;
|
||||
|
||||
@@ -17,6 +17,15 @@ dnssec-policy "unlimited" {
|
||||
};
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@ U="UNRETENTIVE"
|
||||
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"
|
||||
@@ -109,6 +110,20 @@ $SETTIME -s -g $O -k $R $Tpub -z $R $Tpub "$ZSK2" > settime.out.$zo
|
||||
# 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"
|
||||
|
||||
@@ -1201,7 +1201,7 @@ check_cdslog() {
|
||||
}
|
||||
|
||||
#
|
||||
# rndc dnssec -checkds
|
||||
# Utility to call after 'rndc dnssec -checkds|-rollover'.
|
||||
#
|
||||
_loadkeys_on() {
|
||||
_server=$1
|
||||
@@ -1242,6 +1242,31 @@ rndc_checkds() {
|
||||
_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.
|
||||
#
|
||||
@@ -2655,6 +2680,128 @@ status=$((status+ret))
|
||||
# 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.
|
||||
#
|
||||
|
||||
+17
-1
@@ -161,13 +161,29 @@ recreated. To remove it permanently, it must also be removed from
|
||||
.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
|
||||
|
||||
@@ -26,6 +26,9 @@ New Features
|
||||
|
||||
- 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]
|
||||
@@ -35,6 +38,7 @@ Removed Features
|
||||
|
||||
- None.
|
||||
|
||||
|
||||
Feature Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
Reference in New Issue
Block a user