diff --git a/bin/tests/system/kasp/ns6/named.conf.in b/bin/tests/system/kasp/ns6/named.conf.in index 41c1157f56..5cecb8c542 100644 --- a/bin/tests/system/kasp/ns6/named.conf.in +++ b/bin/tests/system/kasp/ns6/named.conf.in @@ -36,7 +36,7 @@ controls { inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; }; -/* This is a zone that migrates to dnssec-policy. */ +/* These are zones that migrate to dnssec-policy. */ zone "migrate.kasp" { type master; file "migrate.kasp.db"; @@ -46,6 +46,15 @@ zone "migrate.kasp" { update-check-ksk yes; }; +zone "migrate-nomatch.kasp" { + type master; + file "migrate-nomatch.kasp.db"; + auto-dnssec maintain; + allow-update { any; }; + dnssec-dnskey-kskonly yes; + update-check-ksk yes; +}; + /* These are alorithm rollover test zones. */ zone "step1.algorithm-roll.kasp" { type master; diff --git a/bin/tests/system/kasp/ns6/named2.conf.in b/bin/tests/system/kasp/ns6/named2.conf.in index 6c5a1f3001..0428dcbdf8 100644 --- a/bin/tests/system/kasp/ns6/named2.conf.in +++ b/bin/tests/system/kasp/ns6/named2.conf.in @@ -35,7 +35,7 @@ controls { inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; }; -/* This is a zone that migrates to dnssec-policy. */ +/* These are zones that migrate to dnssec-policy. */ zone "migrate.kasp" { type master; file "migrate.kasp.db"; @@ -43,6 +43,13 @@ zone "migrate.kasp" { dnssec-policy "migrate"; }; +zone "migrate-nomatch.kasp" { + type master; + file "migrate-nomatch.kasp.db"; + allow-update { any; }; + dnssec-policy "migrate-nomatch"; +}; + /* * Zones for testing KSK/ZSK algorithm roll. */ diff --git a/bin/tests/system/kasp/ns6/policies/kasp.conf b/bin/tests/system/kasp/ns6/policies/kasp.conf index a9424ec050..16fb3d60aa 100644 --- a/bin/tests/system/kasp/ns6/policies/kasp.conf +++ b/bin/tests/system/kasp/ns6/policies/kasp.conf @@ -57,3 +57,21 @@ dnssec-policy "migrate" { zsk key-directory lifetime P60D algorithm ECDSAP256SHA256; }; }; + +dnssec-policy "migrate-nomatch" { + dnskey-ttl 300; + + keys { + ksk key-directory lifetime unlimited algorithm rsasha1 2048; + zsk key-directory lifetime P60D algorithm rsasha1 2048; + }; + + // Together 12h + zone-propagation-delay 3600; + max-zone-ttl 11h; + + // Together 24h + parent-registration-delay 21h; + parent-propagation-delay pt1h; + parent-ds-ttl 7200; +}; diff --git a/bin/tests/system/kasp/ns6/setup.sh b/bin/tests/system/kasp/ns6/setup.sh index b22d36d21e..5c489e774f 100644 --- a/bin/tests/system/kasp/ns6/setup.sh +++ b/bin/tests/system/kasp/ns6/setup.sh @@ -51,6 +51,22 @@ private_type_record $zone 5 "$KSK" >> "$infile" private_type_record $zone 5 "$ZSK" >> "$infile" $SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 +# Set up a zone with auto-dnssec maintain to migrate to dnssec-policy, but this +# time the existing keys do not match the policy. +setup migrate-nomatch.kasp +echo "$zone" >> zones +KSK=$($KEYGEN -a RSASHA1 -b 1024 -f KSK -L 300 $zone 2> keygen.out.$zone.1) +ZSK=$($KEYGEN -a RSASHA1 -b 1024 -L 300 $zone 2> keygen.out.$zone.2) +Tds="now-24h" # Time according to dnssec-policy that DS will be OMNIPRESENT +Tkey="now-3900s" # DNSKEY TTL + propagation delay +Tsig="now-12h" # Zone's maximum TTL + propagation delay +$SETTIME -P $Tkey -P sync $Tds -A $Tkey "$KSK" > settime.out.$zone.1 2>&1 +$SETTIME -P $Tsig -A $Tsig "$ZSK" > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile" +private_type_record $zone 5 "$KSK" >> "$infile" +private_type_record $zone 5 "$ZSK" >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 + # # The zones at algorithm-roll.kasp represent the various steps of a ZSK/KSK # algorithm rollover. diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index b403fc2101..ed24aedf58 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -2917,6 +2917,58 @@ dnssec_verify _migrate_ksk=$(key_get KEY1 ID) _migrate_zsk=$(key_get KEY2 ID) +# +# Testing migration with unmatched existing keys. +# +set_zone "migrate-nomatch.kasp" +set_policy "none" "2" "300" +set_server "ns6" "10.53.0.6" + +init_migration_nomatch() { + key_clear "KEY1" + key_set "KEY1" "LEGACY" "yes" + set_keyrole "KEY1" "ksk" + set_keyalgorithm "KEY1" "5" "RSASHA1" "1024" + set_keysigning "KEY1" "yes" + set_zonesigning "KEY1" "no" + + key_clear "KEY2" + key_set "KEY2" "LEGACY" "yes" + set_keyrole "KEY2" "zsk" + set_keyalgorithm "KEY2" "5" "RSASHA1" "1024" + set_keysigning "KEY2" "no" + set_zonesigning "KEY2" "yes" + + key_clear "KEY3" + key_clear "KEY4" + + set_keytime "KEY1" "PUBLISHED" "yes" + set_keytime "KEY1" "ACTIVE" "yes" + set_keytime "KEY1" "RETIRED" "none" + set_keystate "KEY1" "GOAL" "omnipresent" + set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" + set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" + set_keystate "KEY1" "STATE_DS" "omnipresent" + + set_keytime "KEY2" "PUBLISHED" "yes" + set_keytime "KEY2" "ACTIVE" "yes" + set_keytime "KEY2" "RETIRED" "none" + set_keystate "KEY2" "GOAL" "omnipresent" + set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" + set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" +} +init_migration_nomatch + +# Make sure the zone is signed with legacy keys. +check_keys +check_apex +check_subdomain +dnssec_verify + +# Remember legacy key tags. +_migratenomatch_ksk=$(key_get KEY1 ID) +_migratenomatch_zsk=$(key_get KEY2 ID) + # Reconfig dnssec-policy (triggering algorithm roll and other dnssec-policy # changes). echo_i "reconfig dnssec-policy to trigger algorithm rollover" @@ -2980,6 +3032,64 @@ ret=0 [ $_migrate_zsk == $(key_get KEY2 ID) ] || log_error "mismatch zsk tag" status=$((status+ret)) +# Test migration to dnssec-policy, existing keys do not match. +set_zone "migrate-nomatch.kasp" +set_policy "migrate-nomatch" "4" "300" +set_server "ns6" "10.53.0.6" + +# The legacy keys need to be retired, but otherwise stay present until the +# new keys are omnipresent, and can be used to construct a chain of trust. +init_migration_nomatch + +key_set "KEY1" "LEGACY" "no" +set_keytime "KEY1" "RETIRED" "yes" +set_keystate "KEY1" "GOAL" "hidden" + +key_set "KEY2" "LEGACY" "no" +set_keytime "KEY2" "RETIRED" "yes" +set_keystate "KEY2" "GOAL" "hidden" + +set_keyrole "KEY3" "ksk" +set_keylifetime "KEY3" "0" +set_keyalgorithm "KEY3" "5" "RSASHA1" "2048" +set_keysigning "KEY3" "yes" +set_zonesigning "KEY3" "no" + +set_keyrole "KEY4" "zsk" +set_keylifetime "KEY4" "5184000" +set_keyalgorithm "KEY4" "5" "RSASHA1" "2048" +set_keysigning "KEY4" "no" +# This key is not active yet, first the DNSKEY needs to be omnipresent. +set_zonesigning "KEY4" "no" + +set_keytime "KEY3" "PUBLISHED" "yes" +set_keytime "KEY3" "ACTIVE" "yes" +set_keytime "KEY3" "RETIRED" "none" +set_keystate "KEY3" "GOAL" "omnipresent" +set_keystate "KEY3" "STATE_DNSKEY" "rumoured" +set_keystate "KEY3" "STATE_KRRSIG" "rumoured" +set_keystate "KEY3" "STATE_DS" "hidden" + +set_keytime "KEY4" "PUBLISHED" "yes" +set_keytime "KEY4" "ACTIVE" "yes" +set_keytime "KEY4" "RETIRED" "yes" +set_keystate "KEY4" "GOAL" "omnipresent" +set_keystate "KEY4" "STATE_DNSKEY" "rumoured" +set_keystate "KEY4" "STATE_ZRRSIG" "hidden" + +check_keys +check_apex +check_subdomain +dnssec_verify + +# Check key tags, should be the same. +n=$((n+1)) +echo_i "check that of zone ${ZONE} migration to dnssec-policy keeps existing keys ($n)" +ret=0 +[ $_migratenomatch_ksk == $(key_get KEY1 ID) ] || log_error "mismatch ksk tag" +[ $_migratenomatch_zsk == $(key_get KEY2 ID) ] || log_error "mismatch zsk tag" +status=$((status+ret)) + # # Testing KSK/ZSK algorithm rollover. # diff --git a/lib/dns/keymgr.c b/lib/dns/keymgr.c index e5d7f08edd..268db30d2b 100644 --- a/lib/dns/keymgr.c +++ b/lib/dns/keymgr.c @@ -1228,7 +1228,7 @@ transition: * */ static void -keymgr_key_init(dns_dnsseckey_t *key, isc_stdtime_t now) { +keymgr_key_init(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) { bool ksk, zsk; isc_result_t ret; isc_stdtime_t active = 0, pub = 0, syncpub = 0; @@ -1254,15 +1254,34 @@ keymgr_key_init(dns_dnsseckey_t *key, isc_stdtime_t now) { /* Get time metadata. */ ret = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active); if (active <= now && ret == ISC_R_SUCCESS) { - dnskey_state = RUMOURED; + dns_ttl_t key_ttl = dst_key_getttl(key->key); + key_ttl += dns_kasp_zonepropagationdelay(kasp); + if ((active + key_ttl) <= now) { + dnskey_state = OMNIPRESENT; + } else { + dnskey_state = RUMOURED; + } } ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &pub); if (pub <= now && ret == ISC_R_SUCCESS) { - zrrsig_state = RUMOURED; + dns_ttl_t zone_ttl = dns_kasp_zonemaxttl(kasp); + zone_ttl += dns_kasp_zonepropagationdelay(kasp); + if ((pub + zone_ttl) <= now) { + zrrsig_state = OMNIPRESENT; + } else { + zrrsig_state = RUMOURED; + } } ret = dst_key_gettime(key->key, DST_TIME_SYNCPUBLISH, &syncpub); if (syncpub <= now && ret == ISC_R_SUCCESS) { - ds_state = RUMOURED; + dns_ttl_t ds_ttl = dns_kasp_dsttl(kasp); + ds_ttl += dns_kasp_parentregistrationdelay(kasp); + ds_ttl += dns_kasp_parentpropagationdelay(kasp); + if ((syncpub + ds_ttl) <= now) { + ds_state = OMNIPRESENT; + } else { + ds_state = RUMOURED; + } } /* Set key states for all keys that do not have them. */ @@ -1342,7 +1361,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, { bool found_match = false; - keymgr_key_init(dkey, now); + keymgr_key_init(dkey, kasp, now); for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL; kkey = ISC_LIST_NEXT(kkey, link)) @@ -1511,7 +1530,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, dst_key_setttl(dst_key, dns_kasp_dnskeyttl(kasp)); dst_key_settime(dst_key, DST_TIME_CREATED, now); RETERR(dns_dnsseckey_create(mctx, &dst_key, &newkey)); - keymgr_key_init(newkey, now); + keymgr_key_init(newkey, kasp, now); } else { newkey = candidate; dst_key_setnum(newkey->key, DST_NUM_LIFETIME, lifetime);