2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

Purge keys implementation

On each keymgr run, we now also check if key files can be removed.
The 'purge-keys' interval determines how long keys should be retained
after they have become completely hidden.

Key files should not be removed if it has a state that is set to
something else then HIDDEN, if purge-keys is 0 (disabled), if
the key goal is set to OMNIPRESENT, or if the key is unused (a key is
unused if no timing metadata set, and no states are set or if set,
they are set to HIDDEN).

If the last changed timing metadata plus the purge-keys interval is
in the past, the key files may be removed.

Add a dst_key_t variable 'purge' to signal that the key file should
not be written to file again.
This commit is contained in:
Matthijs Mekking
2021-02-08 15:15:57 +01:00
parent 313de3a7e2
commit 8c526cb67f
3 changed files with 116 additions and 2 deletions

View File

@@ -14,6 +14,7 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <isc/buffer.h>
#include <isc/dir.h>
@@ -1823,6 +1824,94 @@ 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 ksk = false;
bool zsk = false;
dst_key_state_t hidden[NUM_KEYSTATES] = { HIDDEN, NA, NA, NA };
isc_stdtime_t lastchange = 0;
char keystr[DST_KEY_FORMATSIZE];
dst_key_format(key, keystr, sizeof(keystr));
/* If 'purge-keys' is disabled, always retain keys. */
if (after == 0) {
return (false);
}
/* Don't purge keys with goal OMNIPRESENT */
if (dst_key_goal(key) == OMNIPRESENT) {
return (false);
}
/* Don't purge unused keys. */
if (dst_key_is_unused(key)) {
return (false);
}
/* If this key is completely HIDDEN it may be purged. */
(void)dst_key_getbool(key, DST_BOOL_KSK, &ksk);
(void)dst_key_getbool(key, DST_BOOL_ZSK, &zsk);
if (ksk) {
hidden[DST_KEY_KRRSIG] = HIDDEN;
hidden[DST_KEY_DS] = HIDDEN;
}
if (zsk) {
hidden[DST_KEY_ZRRSIG] = HIDDEN;
}
if (!keymgr_key_match_state(key, key, 0, NA, hidden)) {
return (false);
}
/*
* Check 'purge-keys' interval. If the interval has passed since
* the last key change, it may be purged.
*/
for (int i = 0; i < NUM_KEYSTATES; i++) {
isc_stdtime_t change = 0;
(void)dst_key_gettime(key, keystatetimes[i], &change);
if (change > lastchange) {
lastchange = change;
}
}
return ((lastchange + after) < now);
}
static void
keymgr_purge_keyfile(dst_key_t *key, const char *dir, int type) {
isc_result_t ret;
isc_buffer_t fileb;
char filename[NAME_MAX];
/*
* Make the filename.
*/
isc_buffer_init(&fileb, filename, sizeof(filename));
ret = dst_key_buildfilename(key, type, dir, &fileb);
if (ret != ISC_R_SUCCESS) {
char keystr[DST_KEY_FORMATSIZE];
dst_key_format(key, keystr, sizeof(keystr));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
"keymgr: failed to purge DNSKEY %s (%s): cannot "
"build filename (%s)",
keystr, keymgr_keyrole(key),
isc_result_totext(ret));
return;
}
if (unlink(filename) < 0) {
char keystr[DST_KEY_FORMATSIZE];
dst_key_format(key, keystr, sizeof(keystr));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
"keymgr: failed to purge DNSKEY %s (%s): unlink "
"'%s' failed",
keystr, keymgr_keyrole(key), filename);
}
}
/*
* Examine 'keys' and match 'kasp' policy.
*
@@ -1901,6 +1990,27 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
if (!found_match) {
keymgr_key_retire(dkey, kasp, now);
}
/* Check purge-keys interval. */
if (keymgr_key_may_be_purged(dkey->key,
dns_kasp_purgekeys(kasp), now)) {
dst_key_format(dkey->key, keystr, sizeof(keystr));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
"keymgr: purge DNSKEY %s (%s) according "
"to policy %s",
keystr, keymgr_keyrole(dkey->key),
dns_kasp_getname(kasp));
keymgr_purge_keyfile(dkey->key, directory,
DST_TYPE_PUBLIC);
keymgr_purge_keyfile(dkey->key, directory,
DST_TYPE_PRIVATE);
keymgr_purge_keyfile(dkey->key, directory,
DST_TYPE_STATE);
dkey->purge = true;
}
}
/* Create keys according to the policy, if come in short. */
@@ -1993,8 +2103,10 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
dkey = ISC_LIST_NEXT(dkey, link))
{
dns_dnssec_get_hints(dkey, now);
RETERR(dst_key_tofile(dkey->key, options, directory));
if (!dkey->purge) {
dns_dnssec_get_hints(dkey, now);
RETERR(dst_key_tofile(dkey->key, options, directory));
}
}
result = ISC_R_SUCCESS;