2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 14:07:59 +00:00

fix: usr: Fix purge-keys bug when using views

Previously, when a DNSSEC key was purged by one zone view, other zone views would return an error about missing key files. This has been fixed.

Closes #5315

Merge branch '5315-fix-spurious-some-key-files-are-missing' into 'main'

See merge request isc-projects/bind9!10550
This commit is contained in:
Matthijs Mekking 2025-06-19 06:52:05 +00:00
commit 29c69d26d9
10 changed files with 141 additions and 11 deletions

View File

@ -13,6 +13,8 @@
// NS4
include "purgekeys.conf";
key rndc_key {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
@ -154,6 +156,12 @@ view "example1" {
inline-signing no;
file "example1.db";
};
zone "purgekeys.kasp" {
type primary;
file "purgekeys.kasp.example1.db";
dnssec-policy "purgekeys";
};
};
view "example2" {
@ -163,6 +171,12 @@ view "example2" {
type primary;
file "example2.db";
};
zone "purgekeys.kasp" {
type primary;
file "purgekeys.kasp.example2.db";
dnssec-policy "purgekeys";
};
};
view "example3" {

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
dnssec-policy "purgekeys" {
keys {
ksk key-directory lifetime 0 algorithm 13;
zsk key-directory lifetime P30D algorithm 13;
};
/*
* Initially set to 0, so no keys are purged. Keys that are no longer
* in use will still be in the zone's keyring, one per view. After
* reconfig the purge-keys value is set to 7 days, at least one key
* will be eligible for purging, and should be purged from both
* keyrings without issues.
*/
purge-keys 0;
//purge-keys P7D;
};

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
dnssec-policy "purgekeys" {
keys {
ksk key-directory lifetime 0 algorithm 13;
zsk key-directory lifetime P30D algorithm 13;
};
//purge-keys 0;
purge-keys P7D;
};

View File

@ -30,3 +30,22 @@ done
cp example1.db.in example1.db
cp example2.db.in example2.db
# Regression test for GL #5315
cp purgekeys1.conf purgekeys.conf
cp example1.db.in purgekeys.kasp.example1.db
cp example2.db.in purgekeys.kasp.example2.db
zone="purgekeys.kasp"
H="HIDDEN"
O="OMNIPRESENT"
T="now-9mo"
# KSK omnipresent
KSK=$($KEYGEN -fk -a 13 -L 3600 $zone 2>keygen.out.$zone.1)
$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1
# ZSK omnipresent
ZSK1=$($KEYGEN -a 13 -L 3600 $zone 2>keygen.out.$zone.2)
$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK1" >settime.out.$zone.2 2>&1
# ZSK hidden (may be purged)
ZSK2=$($KEYGEN -a 13 -L 3600 $zone 2>keygen.out.$zone.2)
$SETTIME -s -g $H -k $H $T -z $H $T "$ZSK2" >settime.out.$zone.2 2>&1

View File

@ -78,6 +78,8 @@ pytestmark = pytest.mark.extra_artifacts(
"ns*/policies/*.conf",
"ns3/legacy-keys.*",
"ns3/dynamic-signed-inline-signing.kasp.db.signed.signed",
"ns4/purgekeys.conf",
"ns4/purgekeys2.conf",
]
)
@ -1566,6 +1568,33 @@ def test_kasp_zsk_retired(servers):
server.log.prohibit(msg)
def test_kasp_purge_keys(servers):
zone = "purgekeys.kasp"
server = servers["ns4"]
tsig1 = (
f"{os.environ['DEFAULT_HMAC']}:keyforview1:{KASP_INHERIT_TSIG_SECRET['view1']}"
)
tsig2 = (
f"{os.environ['DEFAULT_HMAC']}:keyforview2:{KASP_INHERIT_TSIG_SECRET['view2']}"
)
isctest.kasp.check_dnssec_verify(server, zone, tsig=tsig1)
isctest.kasp.check_dnssec_verify(server, zone, tsig=tsig2)
# Reconfig, make sure the purged key is not an issue when verifying keys.
shutil.copyfile("ns4/purgekeys2.conf", "ns4/purgekeys.conf")
with server.watch_log_from_here() as watcher:
server.rndc("reconfig", log=False)
watcher.wait_for_line(f"keymgr: {zone} done")
msg = f"zone {zone}/IN/example1 (signed): zone_rekey:zone_verifykeys failed: some key files are missing"
server.log.prohibit(msg)
msg = f"zone {zone}/IN/example2 (signed): zone_rekey:zone_verifykeys failed: some key files are missing"
server.log.prohibit(msg)
def test_kasp_reload_restart(servers):
server = servers["ns6"]
zone = "example"

View File

@ -2296,7 +2296,7 @@ dst_key_tkeytoken(const dst_key_t *key) {
*
*/
bool
dst_key_is_unused(dst_key_t *key) {
dst_key_is_unused(const dst_key_t *key) {
isc_stdtime_t val;
dst_key_state_t st;
int state_type;
@ -2598,7 +2598,7 @@ dst_key_is_removed(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *remove) {
}
dst_key_state_t
dst_key_goal(dst_key_t *key) {
dst_key_goal(const dst_key_t *key) {
dst_key_state_t state;
isc_result_t result;

View File

@ -158,3 +158,16 @@ dns_keymgr_status(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
*\li Printable status in 'out'.
*
*/
bool
dns_keymgr_key_may_be_purged(const dst_key_t *key, uint32_t after,
isc_stdtime_t now);
/*%<
* Checks if the key files for 'key' may be removed from disk.
*
* Requires:
*\li 'key' is a valid key.
*
* Returns:
*\li true if the key files may be purged, false otherwise.
*/

View File

@ -1081,7 +1081,7 @@ dst_key_haskasp(dst_key_t *key);
*/
bool
dst_key_is_unused(dst_key_t *key);
dst_key_is_unused(const dst_key_t *key);
/*%<
* Check if this key is unused.
*
@ -1138,7 +1138,7 @@ dst_key_is_removed(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *remove);
*/
dst_key_state_t
dst_key_goal(dst_key_t *key);
dst_key_goal(const dst_key_t *key);
/*%<
* Get the key goal. Should be OMNIPRESENT or HIDDEN.
* This can be used to determine if the key is being introduced or

View File

@ -605,7 +605,7 @@ keymgr_desiredstate(dns_dnsseckey_t *key, dst_key_state_t state) {
*
*/
static bool
keymgr_key_match_state(dst_key_t *key, dst_key_t *subject, int type,
keymgr_key_match_state(const dst_key_t *key, const dst_key_t *subject, int type,
dst_key_state_t next_state,
dst_key_state_t states[NUM_KEYSTATES]) {
REQUIRE(key != NULL);
@ -1930,8 +1930,9 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
return ISC_R_SUCCESS;
}
static bool
keymgr_key_may_be_purged(dst_key_t *key, uint32_t after, isc_stdtime_t now) {
bool
dns_keymgr_key_may_be_purged(const dst_key_t *key, uint32_t after,
isc_stdtime_t now) {
bool ksk = false;
bool zsk = false;
dst_key_state_t hidden[NUM_KEYSTATES] = { HIDDEN, NA, NA, NA };
@ -2106,8 +2107,8 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
}
/* Check purge-keys interval. */
if (keymgr_key_may_be_purged(dkey->key,
dns_kasp_purgekeys(kasp), now))
if (dns_keymgr_key_may_be_purged(dkey->key,
dns_kasp_purgekeys(kasp), now))
{
dst_key_format(dkey->key, keystr, sizeof(keystr));
isc_log_write(DNS_LOGCATEGORY_DNSSEC,

View File

@ -21974,7 +21974,8 @@ update_ttl(dns_rdataset_t *rdataset, dns_name_t *name, dns_ttl_t ttl,
}
static isc_result_t
zone_verifykeys(dns_zone_t *zone, dns_dnsseckeylist_t *newkeys) {
zone_verifykeys(dns_zone_t *zone, dns_dnsseckeylist_t *newkeys,
uint32_t purgeval, isc_stdtime_t now) {
/*
* Make sure that the existing keys are also present in the new keylist.
*/
@ -21984,6 +21985,9 @@ zone_verifykeys(dns_zone_t *zone, dns_dnsseckeylist_t *newkeys) {
if (dst_key_is_unused(key1->key)) {
continue;
}
if (dns_keymgr_key_may_be_purged(key1->key, purgeval, now)) {
continue;
}
if (key1->purge) {
continue;
}
@ -22271,7 +22275,8 @@ zone_rekey(dns_zone_t *zone) {
if (kasp != NULL && !offlineksk) {
/* Verify new keys. */
isc_result_t ret = zone_verifykeys(zone, &keys);
isc_result_t ret = zone_verifykeys(
zone, &keys, dns_kasp_purgekeys(kasp), now);
if (ret != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
"zone_rekey:zone_verifykeys failed: "