mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
dnssec-ksr keygen -o to create KSKs
Add an option to dnssec-ksr keygen, -o, to create KSKs instead of ZSKs.
This way, we can create a set of KSKS for a given period too.
For KSKs we also need to set timing metadata, including "SyncPublish"
and "SyncDelete". This functionality already exists in keymgr.c so
let's make the function accessible.
Replace dnssec-keygen calls with dnssec-ksr keygen for KSK in the
ksr system test and check keys for created KSKs as well. This requires
a slight modification of the check_keys function to take into account
KSK timings and metadata.
(cherry picked from commit 680aedb595
)
This commit is contained in:
committed by
Mark Andrews
parent
1adcb2945e
commit
a92fb659d3
@@ -25,6 +25,7 @@
|
|||||||
#include <dns/callbacks.h>
|
#include <dns/callbacks.h>
|
||||||
#include <dns/dnssec.h>
|
#include <dns/dnssec.h>
|
||||||
#include <dns/fixedname.h>
|
#include <dns/fixedname.h>
|
||||||
|
#include <dns/keymgr.h>
|
||||||
#include <dns/keyvalues.h>
|
#include <dns/keyvalues.h>
|
||||||
#include <dns/rdataclass.h>
|
#include <dns/rdataclass.h>
|
||||||
#include <dns/rdatalist.h>
|
#include <dns/rdatalist.h>
|
||||||
@@ -63,16 +64,19 @@ struct ksr_ctx {
|
|||||||
bool setstart;
|
bool setstart;
|
||||||
bool setend;
|
bool setend;
|
||||||
/* keygen */
|
/* keygen */
|
||||||
|
bool ksk;
|
||||||
dns_ttl_t ttl;
|
dns_ttl_t ttl;
|
||||||
dns_secalg_t alg;
|
dns_secalg_t alg;
|
||||||
int size;
|
int size;
|
||||||
time_t lifetime;
|
time_t lifetime;
|
||||||
|
time_t parentpropagation;
|
||||||
time_t propagation;
|
time_t propagation;
|
||||||
time_t publishsafety;
|
time_t publishsafety;
|
||||||
time_t retiresafety;
|
time_t retiresafety;
|
||||||
time_t sigrefresh;
|
time_t sigrefresh;
|
||||||
time_t sigvalidity;
|
time_t sigvalidity;
|
||||||
time_t signdelay;
|
time_t signdelay;
|
||||||
|
time_t ttlds;
|
||||||
time_t ttlsig;
|
time_t ttlsig;
|
||||||
};
|
};
|
||||||
typedef struct ksr_ctx ksr_ctx_t;
|
typedef struct ksr_ctx ksr_ctx_t;
|
||||||
@@ -243,6 +247,7 @@ get_dnskeys(ksr_ctx_t *ksr, dns_dnsseckeylist_t *keys) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
setcontext(ksr_ctx_t *ksr, dns_kasp_t *kasp) {
|
setcontext(ksr_ctx_t *ksr, dns_kasp_t *kasp) {
|
||||||
|
ksr->parentpropagation = dns_kasp_parentpropagationdelay(kasp);
|
||||||
ksr->propagation = dns_kasp_zonepropagationdelay(kasp);
|
ksr->propagation = dns_kasp_zonepropagationdelay(kasp);
|
||||||
ksr->publishsafety = dns_kasp_publishsafety(kasp);
|
ksr->publishsafety = dns_kasp_publishsafety(kasp);
|
||||||
ksr->retiresafety = dns_kasp_retiresafety(kasp);
|
ksr->retiresafety = dns_kasp_retiresafety(kasp);
|
||||||
@@ -250,6 +255,7 @@ setcontext(ksr_ctx_t *ksr, dns_kasp_t *kasp) {
|
|||||||
ksr->sigrefresh = dns_kasp_sigrefresh(kasp);
|
ksr->sigrefresh = dns_kasp_sigrefresh(kasp);
|
||||||
ksr->signdelay = dns_kasp_signdelay(kasp);
|
ksr->signdelay = dns_kasp_signdelay(kasp);
|
||||||
ksr->ttl = dns_kasp_dnskeyttl(kasp);
|
ksr->ttl = dns_kasp_dnskeyttl(kasp);
|
||||||
|
ksr->ttlds = dns_kasp_dsttl(kasp);
|
||||||
ksr->ttlsig = dns_kasp_zonemaxttl(kasp, true);
|
ksr->ttlsig = dns_kasp_zonemaxttl(kasp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,12 +323,13 @@ freerrset(dns_rdataset_t *rdataset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_zsk(ksr_ctx_t *ksr, dns_kasp_key_t *kaspkey, dns_dnsseckeylist_t *keys,
|
create_key(ksr_ctx_t *ksr, dns_kasp_t *kasp, dns_kasp_key_t *kaspkey,
|
||||||
isc_stdtime_t inception, isc_stdtime_t active,
|
dns_dnsseckeylist_t *keys, isc_stdtime_t inception,
|
||||||
isc_stdtime_t *expiration) {
|
isc_stdtime_t active, isc_stdtime_t *expiration) {
|
||||||
bool conflict = false;
|
bool conflict = false;
|
||||||
bool freekey = false;
|
bool freekey = false;
|
||||||
bool show_progress = true;
|
bool show_progress = true;
|
||||||
|
bool first = true;
|
||||||
char algstr[DNS_SECALG_FORMATSIZE];
|
char algstr[DNS_SECALG_FORMATSIZE];
|
||||||
char filename[PATH_MAX + 1];
|
char filename[PATH_MAX + 1];
|
||||||
char timestr[26]; /* Minimal buf as per ctime_r() spec. */
|
char timestr[26]; /* Minimal buf as per ctime_r() spec. */
|
||||||
@@ -331,9 +338,15 @@ create_zsk(ksr_ctx_t *ksr, dns_kasp_key_t *kaspkey, dns_dnsseckeylist_t *keys,
|
|||||||
isc_buffer_t buf;
|
isc_buffer_t buf;
|
||||||
isc_result_t ret;
|
isc_result_t ret;
|
||||||
isc_stdtime_t prepub;
|
isc_stdtime_t prepub;
|
||||||
|
uint16_t flags = DNS_KEYOWNER_ZONE;
|
||||||
|
|
||||||
isc_stdtime_tostring(inception, timestr, sizeof(timestr));
|
isc_stdtime_tostring(inception, timestr, sizeof(timestr));
|
||||||
|
|
||||||
|
/* ZSK or KSK? */
|
||||||
|
if (ksr->ksk) {
|
||||||
|
flags |= DNS_KEYFLAG_KSK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check algorithm and size. */
|
/* Check algorithm and size. */
|
||||||
dns_secalg_format(ksr->alg, algstr, sizeof(algstr));
|
dns_secalg_format(ksr->alg, algstr, sizeof(algstr));
|
||||||
if (!dst_algorithm_supported(ksr->alg)) {
|
if (!dst_algorithm_supported(ksr->alg)) {
|
||||||
@@ -407,6 +420,7 @@ create_zsk(ksr_ctx_t *ksr, dns_kasp_key_t *kaspkey, dns_dnsseckeylist_t *keys,
|
|||||||
"Selecting key pair for bundle %s: ", timestr);
|
"Selecting key pair for bundle %s: ", timestr);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
first = false;
|
||||||
key = dk->key;
|
key = dk->key;
|
||||||
*expiration = inact;
|
*expiration = inact;
|
||||||
goto output;
|
goto output;
|
||||||
@@ -424,18 +438,18 @@ create_zsk(ksr_ctx_t *ksr, dns_kasp_key_t *kaspkey, dns_dnsseckeylist_t *keys,
|
|||||||
ret = dns_keystore_keygen(
|
ret = dns_keystore_keygen(
|
||||||
ksr->keystore, name, ksr->policy,
|
ksr->keystore, name, ksr->policy,
|
||||||
dns_rdataclass_in, mctx, ksr->alg, ksr->size,
|
dns_rdataclass_in, mctx, ksr->alg, ksr->size,
|
||||||
DNS_KEYOWNER_ZONE, &key);
|
flags, &key);
|
||||||
} else if (show_progress) {
|
} else if (show_progress) {
|
||||||
ret = dst_key_generate(
|
ret = dst_key_generate(name, ksr->alg, ksr->size, 0,
|
||||||
name, ksr->alg, ksr->size, 0, DNS_KEYOWNER_ZONE,
|
flags, DNS_KEYPROTO_DNSSEC,
|
||||||
DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, NULL,
|
dns_rdataclass_in, NULL, mctx,
|
||||||
mctx, &key, &progress);
|
&key, &progress);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
} else {
|
} else {
|
||||||
ret = dst_key_generate(
|
ret = dst_key_generate(name, ksr->alg, ksr->size, 0,
|
||||||
name, ksr->alg, ksr->size, 0, DNS_KEYOWNER_ZONE,
|
flags, DNS_KEYPROTO_DNSSEC,
|
||||||
DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, NULL,
|
dns_rdataclass_in, NULL, mctx,
|
||||||
mctx, &key, NULL);
|
&key, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != ISC_R_SUCCESS) {
|
if (ret != ISC_R_SUCCESS) {
|
||||||
@@ -472,15 +486,27 @@ create_zsk(ksr_ctx_t *ksr, dns_kasp_key_t *kaspkey, dns_dnsseckeylist_t *keys,
|
|||||||
prepub = ksr->ttl + ksr->publishsafety + ksr->propagation;
|
prepub = ksr->ttl + ksr->publishsafety + ksr->propagation;
|
||||||
dst_key_setttl(key, ksr->ttl);
|
dst_key_setttl(key, ksr->ttl);
|
||||||
dst_key_setnum(key, DST_NUM_LIFETIME, ksr->lifetime);
|
dst_key_setnum(key, DST_NUM_LIFETIME, ksr->lifetime);
|
||||||
dst_key_setbool(key, DST_BOOL_KSK, false);
|
dst_key_setbool(key, DST_BOOL_KSK, ksr->ksk);
|
||||||
dst_key_setbool(key, DST_BOOL_ZSK, true);
|
dst_key_setbool(key, DST_BOOL_ZSK, !ksr->ksk);
|
||||||
dst_key_settime(key, DST_TIME_CREATED, ksr->now);
|
dst_key_settime(key, DST_TIME_CREATED, ksr->now);
|
||||||
dst_key_settime(key, DST_TIME_PUBLISH, (active - prepub));
|
dst_key_settime(key, DST_TIME_PUBLISH, (active - prepub));
|
||||||
dst_key_settime(key, DST_TIME_ACTIVATE, active);
|
dst_key_settime(key, DST_TIME_ACTIVATE, active);
|
||||||
|
if (ksr->ksk) {
|
||||||
|
dns_keymgr_settime_syncpublish(key, kasp, first);
|
||||||
|
}
|
||||||
|
|
||||||
if (ksr->lifetime > 0) {
|
if (ksr->lifetime > 0) {
|
||||||
isc_stdtime_t inactive = (active + ksr->lifetime);
|
isc_stdtime_t inactive = (active + ksr->lifetime);
|
||||||
isc_stdtime_t remove = ksr->ttlsig + ksr->propagation +
|
isc_stdtime_t remove;
|
||||||
|
|
||||||
|
if (ksr->ksk) {
|
||||||
|
remove = ksr->ttlds + ksr->parentpropagation +
|
||||||
|
ksr->retiresafety;
|
||||||
|
dst_key_settime(key, DST_TIME_SYNCDELETE, inactive);
|
||||||
|
} else {
|
||||||
|
remove = ksr->ttlsig + ksr->propagation +
|
||||||
ksr->retiresafety + ksr->signdelay;
|
ksr->retiresafety + ksr->signdelay;
|
||||||
|
}
|
||||||
dst_key_settime(key, DST_TIME_INACTIVE, inactive);
|
dst_key_settime(key, DST_TIME_INACTIVE, inactive);
|
||||||
dst_key_settime(key, DST_TIME_DELETE, (inactive + remove));
|
dst_key_settime(key, DST_TIME_DELETE, (inactive + remove));
|
||||||
*expiration = inactive;
|
*expiration = inactive;
|
||||||
@@ -496,6 +522,8 @@ create_zsk(ksr_ctx_t *ksr, dns_kasp_key_t *kaspkey, dns_dnsseckeylist_t *keys,
|
|||||||
isc_result_totext(ret));
|
isc_result_totext(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
|
||||||
output:
|
output:
|
||||||
isc_buffer_clear(&buf);
|
isc_buffer_clear(&buf);
|
||||||
ret = dst_key_buildfilename(key, 0, NULL, &buf);
|
ret = dst_key_buildfilename(key, 0, NULL, &buf);
|
||||||
@@ -911,9 +939,12 @@ keygen(ksr_ctx_t *ksr) {
|
|||||||
for (dns_kasp_key_t *kk = ISC_LIST_HEAD(dns_kasp_keys(kasp));
|
for (dns_kasp_key_t *kk = ISC_LIST_HEAD(dns_kasp_keys(kasp));
|
||||||
kk != NULL; kk = ISC_LIST_NEXT(kk, link))
|
kk != NULL; kk = ISC_LIST_NEXT(kk, link))
|
||||||
{
|
{
|
||||||
if (dns_kasp_key_ksk(kk)) {
|
if (dns_kasp_key_ksk(kk) && !ksr->ksk) {
|
||||||
/* only ZSKs allowed */
|
/* only ZSKs allowed */
|
||||||
continue;
|
continue;
|
||||||
|
} else if (dns_kasp_key_zsk(kk) && ksr->ksk) {
|
||||||
|
/* only KSKs allowed */
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
ksr->alg = dns_kasp_key_algorithm(kk);
|
ksr->alg = dns_kasp_key_algorithm(kk);
|
||||||
ksr->lifetime = dns_kasp_key_lifetime(kk);
|
ksr->lifetime = dns_kasp_key_lifetime(kk);
|
||||||
@@ -924,7 +955,7 @@ keygen(ksr_ctx_t *ksr) {
|
|||||||
for (isc_stdtime_t inception = ksr->start, act = ksr->start;
|
for (isc_stdtime_t inception = ksr->start, act = ksr->start;
|
||||||
inception < ksr->end; inception += ksr->lifetime)
|
inception < ksr->end; inception += ksr->lifetime)
|
||||||
{
|
{
|
||||||
create_zsk(ksr, kk, &keys, inception, act, &act);
|
create_key(ksr, kasp, kk, &keys, inception, act, &act);
|
||||||
if (ksr->lifetime == 0) {
|
if (ksr->lifetime == 0) {
|
||||||
/* unlimited lifetime, but not infinite loop */
|
/* unlimited lifetime, but not infinite loop */
|
||||||
break;
|
break;
|
||||||
@@ -932,7 +963,7 @@ keygen(ksr_ctx_t *ksr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (noop) {
|
if (noop) {
|
||||||
fatal("policy '%s' has no zsks", ksr->policy);
|
fatal("no keys created for policy '%s'", ksr->policy);
|
||||||
}
|
}
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
cleanup(&keys, kasp);
|
cleanup(&keys, kasp);
|
||||||
@@ -1216,7 +1247,7 @@ main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
isc_commandline_errprint = false;
|
isc_commandline_errprint = false;
|
||||||
|
|
||||||
#define OPTIONS "E:e:Ff:hi:K:k:l:v:V"
|
#define OPTIONS "E:e:Ff:hi:K:k:l:ov:V"
|
||||||
while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) {
|
while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'E':
|
case 'E':
|
||||||
@@ -1253,6 +1284,9 @@ main(int argc, char *argv[]) {
|
|||||||
case 'l':
|
case 'l':
|
||||||
ksr.configfile = isc_commandline_argument;
|
ksr.configfile = isc_commandline_argument;
|
||||||
break;
|
break;
|
||||||
|
case 'o':
|
||||||
|
ksr.ksk = true;
|
||||||
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
version(program);
|
version(program);
|
||||||
break;
|
break;
|
||||||
|
@@ -21,7 +21,7 @@ dnssec-ksr - Create signed key response (SKR) files for offline KSK setups
|
|||||||
Synopsis
|
Synopsis
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
:program:`dnssec-ksr` [**-E** engine] [**-e** date/offset] [**-F**] [**-f** file] [**-h**] [**-i** date/offset] [**-K** directory] [**-k** policy] [**-l** file] [**-V**] [**-v** level] {command} {zone}
|
:program:`dnssec-ksr` [**-E** engine] [**-e** date/offset] [**-F**] [**-f** file] [**-h**] [**-i** date/offset] [**-K** directory] [**-k** policy] [**-l** file] [**-o**] [**-V**] [**-v** level] {command} {zone}
|
||||||
|
|
||||||
Description
|
Description
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
@@ -88,6 +88,11 @@ Options
|
|||||||
This option provides a configuration file that contains a ``dnssec-policy``
|
This option provides a configuration file that contains a ``dnssec-policy``
|
||||||
statement (matching the policy set with :option:`-k`).
|
statement (matching the policy set with :option:`-k`).
|
||||||
|
|
||||||
|
.. option:: -o
|
||||||
|
|
||||||
|
Normally when pregenerating keys, ZSKs are created. When this option is
|
||||||
|
set, create KSKs instead.
|
||||||
|
|
||||||
.. option:: -V
|
.. option:: -V
|
||||||
|
|
||||||
This option prints version information.
|
This option prints version information.
|
||||||
@@ -110,9 +115,8 @@ Commands
|
|||||||
|
|
||||||
.. option:: keygen
|
.. option:: keygen
|
||||||
|
|
||||||
Pregenerate a number of zone signing keys (ZSKs), given a DNSSEC policy and
|
Pregenerate a number of keys, given a DNSSEC policy and an interval. The
|
||||||
an interval. The number of generated keys depends on the interval and the
|
number of generated keys depends on the interval and the key lifetime.
|
||||||
ZSK lifetime.
|
|
||||||
|
|
||||||
.. option:: request
|
.. option:: request
|
||||||
|
|
||||||
@@ -135,7 +139,7 @@ occurred.
|
|||||||
Examples
|
Examples
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
When you need to generate keys for the zone "example.com" for the next year,
|
When you need to generate ZSKs for the zone "example.com" for the next year,
|
||||||
given a ``dnssec-policy`` named "mypolicy":
|
given a ``dnssec-policy`` named "mypolicy":
|
||||||
|
|
||||||
::
|
::
|
||||||
@@ -148,7 +152,8 @@ Creating a KSR for the same zone and period can be done with:
|
|||||||
|
|
||||||
dnssec-ksr -i now -e +1y -k mypolicy -l named.conf request example.com > ksr.txt
|
dnssec-ksr -i now -e +1y -k mypolicy -l named.conf request example.com > ksr.txt
|
||||||
|
|
||||||
Typically you would now transfer the KSR to the system that has access to the KSK.
|
Typically you would now transfer the KSR to the system that has access to
|
||||||
|
the KSK.
|
||||||
|
|
||||||
Signing the KSR created above can be done with:
|
Signing the KSR created above can be done with:
|
||||||
|
|
||||||
@@ -156,7 +161,8 @@ Signing the KSR created above can be done with:
|
|||||||
|
|
||||||
dnssec-ksr -i now -e +1y -k kskpolicy -l named.conf -f ksr.txt sign example.com
|
dnssec-ksr -i now -e +1y -k kskpolicy -l named.conf -f ksr.txt sign example.com
|
||||||
|
|
||||||
Make sure that the DNSSEC parameters in ``kskpolicy`` match those in ``mypolicy``.
|
Make sure that the DNSSEC parameters in ``kskpolicy`` match those
|
||||||
|
in ``mypolicy``.
|
||||||
|
|
||||||
See Also
|
See Also
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
@@ -55,28 +55,6 @@ def keystr_to_keylist(keystr: str, keydir: Optional[str] = None) -> List[Key]:
|
|||||||
return [Key(name, keydir) for name in keystr.split()]
|
return [Key(name, keydir) for name in keystr.split()]
|
||||||
|
|
||||||
|
|
||||||
def keygen(zone, policy, keydir, when="now"):
|
|
||||||
keygen_command = [
|
|
||||||
os.environ.get("KEYGEN"),
|
|
||||||
"-l",
|
|
||||||
"ns1/named.conf",
|
|
||||||
"-fK",
|
|
||||||
"-K",
|
|
||||||
keydir,
|
|
||||||
"-k",
|
|
||||||
policy,
|
|
||||||
"-P",
|
|
||||||
when,
|
|
||||||
"-A",
|
|
||||||
when,
|
|
||||||
"-P",
|
|
||||||
"sync",
|
|
||||||
when,
|
|
||||||
zone,
|
|
||||||
]
|
|
||||||
return isctest.run.cmd(keygen_command, log_stdout=True).stdout.decode("utf-8")
|
|
||||||
|
|
||||||
|
|
||||||
def ksr(zone, policy, action, options="", raise_on_exception=True):
|
def ksr(zone, policy, action, options="", raise_on_exception=True):
|
||||||
ksr_command = [
|
ksr_command = [
|
||||||
os.environ.get("KSR"),
|
os.environ.get("KSR"),
|
||||||
@@ -123,12 +101,22 @@ def check_keys(
|
|||||||
# retired: zsk-lifetime
|
# retired: zsk-lifetime
|
||||||
if lifetime is not None:
|
if lifetime is not None:
|
||||||
retired = active + lifetime
|
retired = active + lifetime
|
||||||
|
|
||||||
|
if key.is_ksk():
|
||||||
|
# removed: ttlds + retire-safety + parent-propagation
|
||||||
|
removed = retired + timedelta(days=1, hours=2)
|
||||||
|
else:
|
||||||
# removed: ttlsig + retire-safety + sign-delay + propagation
|
# removed: ttlsig + retire-safety + sign-delay + propagation
|
||||||
removed = retired + timedelta(days=10, hours=1, minutes=5)
|
removed = retired + timedelta(days=10, hours=1, minutes=5)
|
||||||
else:
|
else:
|
||||||
retired = None
|
retired = None
|
||||||
removed = None
|
removed = None
|
||||||
|
|
||||||
|
goal = "hidden"
|
||||||
|
state_dnskey = "hidden"
|
||||||
|
state_zrrsig = "hidden"
|
||||||
|
state_krrsig = "hidden"
|
||||||
|
state_ds = "hidden"
|
||||||
if retired is None or between(now, published, retired):
|
if retired is None or between(now, published, retired):
|
||||||
goal = "omnipresent"
|
goal = "omnipresent"
|
||||||
pubdelay = published + timedelta(hours=2, minutes=5)
|
pubdelay = published + timedelta(hours=2, minutes=5)
|
||||||
@@ -136,24 +124,34 @@ def check_keys(
|
|||||||
|
|
||||||
if between(now, published, pubdelay):
|
if between(now, published, pubdelay):
|
||||||
state_dnskey = "rumoured"
|
state_dnskey = "rumoured"
|
||||||
|
state_krrsig = "rumoured"
|
||||||
else:
|
else:
|
||||||
state_dnskey = "omnipresent"
|
state_dnskey = "omnipresent"
|
||||||
|
state_krrsig = "omnipresent"
|
||||||
|
|
||||||
|
if key.is_ksk():
|
||||||
|
state_ds = "hidden"
|
||||||
|
else:
|
||||||
if between(now, active, signdelay):
|
if between(now, active, signdelay):
|
||||||
state_zrrsig = "rumoured"
|
state_zrrsig = "rumoured"
|
||||||
else:
|
else:
|
||||||
state_zrrsig = "omnipresent"
|
state_zrrsig = "omnipresent"
|
||||||
else:
|
|
||||||
goal = "hidden"
|
|
||||||
state_dnskey = "hidden"
|
|
||||||
state_zrrsig = "hidden"
|
|
||||||
|
|
||||||
with open(key.statefile, "r", encoding="utf-8") as file:
|
with open(key.statefile, "r", encoding="utf-8") as file:
|
||||||
metadata = file.read()
|
metadata = file.read()
|
||||||
assert f"Algorithm: {alg}" in metadata
|
assert f"Algorithm: {alg}" in metadata
|
||||||
assert f"Length: {size}" in metadata
|
assert f"Length: {size}" in metadata
|
||||||
|
|
||||||
|
if key.is_ksk():
|
||||||
|
assert "KSK: yes" in metadata
|
||||||
|
else:
|
||||||
assert "KSK: no" in metadata
|
assert "KSK: no" in metadata
|
||||||
|
|
||||||
|
if key.is_zsk():
|
||||||
assert "ZSK: yes" in metadata
|
assert "ZSK: yes" in metadata
|
||||||
|
else:
|
||||||
|
assert "ZSK: no" in metadata
|
||||||
|
|
||||||
assert f"Published: {published}" in metadata
|
assert f"Published: {published}" in metadata
|
||||||
assert f"Active: {active}" in metadata
|
assert f"Active: {active}" in metadata
|
||||||
|
|
||||||
@@ -169,10 +167,19 @@ def check_keys(
|
|||||||
if with_state:
|
if with_state:
|
||||||
assert f"GoalState: {goal}" in metadata
|
assert f"GoalState: {goal}" in metadata
|
||||||
assert f"DNSKEYState: {state_dnskey}" in metadata
|
assert f"DNSKEYState: {state_dnskey}" in metadata
|
||||||
assert f"ZRRSIGState: {state_zrrsig}" in metadata
|
|
||||||
|
if key.is_ksk():
|
||||||
|
assert f"KRRSIGState: {state_krrsig}" in metadata
|
||||||
|
assert f"DSState: {state_ds}" in metadata
|
||||||
|
else:
|
||||||
assert "KRRSIGState:" not in metadata
|
assert "KRRSIGState:" not in metadata
|
||||||
assert "DSState:" not in metadata
|
assert "DSState:" not in metadata
|
||||||
|
|
||||||
|
if key.is_zsk():
|
||||||
|
assert f"ZRRSIGState: {state_zrrsig}" in metadata
|
||||||
|
else:
|
||||||
|
assert "ZRRSIGState:" not in metadata
|
||||||
|
|
||||||
num += 1
|
num += 1
|
||||||
|
|
||||||
|
|
||||||
@@ -264,6 +271,9 @@ def check_signedkeyresponse(
|
|||||||
# expect ksks
|
# expect ksks
|
||||||
for key in sorted(ksks):
|
for key in sorted(ksks):
|
||||||
published = key.get_timing("Publish")
|
published = key.get_timing("Publish")
|
||||||
|
if between(published, inception, next_bundle):
|
||||||
|
next_bundle = published
|
||||||
|
|
||||||
removed = key.get_timing("Delete", must_exist=False)
|
removed = key.get_timing("Delete", must_exist=False)
|
||||||
|
|
||||||
if published > inception:
|
if published > inception:
|
||||||
@@ -271,6 +281,9 @@ def check_signedkeyresponse(
|
|||||||
if removed is not None and inception >= removed:
|
if removed is not None and inception >= removed:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if between(removed, inception, next_bundle):
|
||||||
|
next_bundle = removed
|
||||||
|
|
||||||
# this ksk must be in the ksr
|
# this ksk must be in the ksr
|
||||||
assert key.dnskey_equals(lines[line_no])
|
assert key.dnskey_equals(lines[line_no])
|
||||||
line_no += 1
|
line_no += 1
|
||||||
@@ -399,7 +412,7 @@ def test_ksr_errors():
|
|||||||
_, err = ksr(
|
_, err = ksr(
|
||||||
"csk.test", "csk", "keygen", options="-K ns1 -e +2y", raise_on_exception=False
|
"csk.test", "csk", "keygen", options="-K ns1 -e +2y", raise_on_exception=False
|
||||||
)
|
)
|
||||||
assert "dnssec-ksr: fatal: policy 'csk' has no zsks" in err
|
assert "dnssec-ksr: fatal: no keys created for policy 'csk'" in err
|
||||||
|
|
||||||
# check that 'dnssec-ksr request' errors on missing end date
|
# check that 'dnssec-ksr request' errors on missing end date
|
||||||
_, err = ksr("common.test", "common", "request", raise_on_exception=False)
|
_, err = ksr("common.test", "common", "request", raise_on_exception=False)
|
||||||
@@ -424,10 +437,12 @@ def test_ksr_common(servers):
|
|||||||
|
|
||||||
# create ksk
|
# create ksk
|
||||||
kskdir = "ns1/offline"
|
kskdir = "ns1/offline"
|
||||||
out = keygen(zone, policy, kskdir)
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +1y -o")
|
||||||
ksks = keystr_to_keylist(out, kskdir)
|
ksks = keystr_to_keylist(out, kskdir)
|
||||||
assert len(ksks) == 1
|
assert len(ksks) == 1
|
||||||
|
|
||||||
|
check_keys(ksks, None)
|
||||||
|
|
||||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||||
out, _ = ksr(zone, policy, "keygen", options="-i now -e +1y")
|
out, _ = ksr(zone, policy, "keygen", options="-i now -e +1y")
|
||||||
zsks = keystr_to_keylist(out)
|
zsks = keystr_to_keylist(out)
|
||||||
@@ -611,13 +626,13 @@ def test_ksr_lastbundle(servers):
|
|||||||
|
|
||||||
# create ksk
|
# create ksk
|
||||||
kskdir = "ns1/offline"
|
kskdir = "ns1/offline"
|
||||||
now = KeyTimingMetadata.now()
|
|
||||||
offset = -timedelta(days=365)
|
offset = -timedelta(days=365)
|
||||||
when = now + offset - timedelta(days=1)
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i -1y -e +1d -o")
|
||||||
out = keygen(zone, policy, kskdir, when=str(when))
|
|
||||||
ksks = keystr_to_keylist(out, kskdir)
|
ksks = keystr_to_keylist(out, kskdir)
|
||||||
assert len(ksks) == 1
|
assert len(ksks) == 1
|
||||||
|
|
||||||
|
check_keys(ksks, None, offset=offset)
|
||||||
|
|
||||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||||
zskdir = "ns1"
|
zskdir = "ns1"
|
||||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i -1y -e +1d")
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i -1y -e +1d")
|
||||||
@@ -690,13 +705,13 @@ def test_ksr_inthemiddle(servers):
|
|||||||
|
|
||||||
# create ksk
|
# create ksk
|
||||||
kskdir = "ns1/offline"
|
kskdir = "ns1/offline"
|
||||||
now = KeyTimingMetadata.now()
|
|
||||||
offset = -timedelta(days=365)
|
offset = -timedelta(days=365)
|
||||||
when = now + offset - timedelta(days=1)
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i -1y -e +1y -o")
|
||||||
out = keygen(zone, policy, kskdir, when=str(when))
|
|
||||||
ksks = keystr_to_keylist(out, kskdir)
|
ksks = keystr_to_keylist(out, kskdir)
|
||||||
assert len(ksks) == 1
|
assert len(ksks) == 1
|
||||||
|
|
||||||
|
check_keys(ksks, None, offset=offset)
|
||||||
|
|
||||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||||
zskdir = "ns1"
|
zskdir = "ns1"
|
||||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i -1y -e +1y")
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i -1y -e +1y")
|
||||||
@@ -771,7 +786,7 @@ def check_ksr_rekey_logs_error(server, zone, policy, offset, end):
|
|||||||
now = KeyTimingMetadata.now()
|
now = KeyTimingMetadata.now()
|
||||||
then = now + offset
|
then = now + offset
|
||||||
until = now + end
|
until = now + end
|
||||||
out = keygen(zone, policy, kskdir, when=str(then))
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i {then} -e {until} -o")
|
||||||
ksks = keystr_to_keylist(out, kskdir)
|
ksks = keystr_to_keylist(out, kskdir)
|
||||||
assert len(ksks) == 1
|
assert len(ksks) == 1
|
||||||
|
|
||||||
@@ -844,10 +859,12 @@ def test_ksr_unlimited(servers):
|
|||||||
|
|
||||||
# create ksk
|
# create ksk
|
||||||
kskdir = "ns1/offline"
|
kskdir = "ns1/offline"
|
||||||
out = keygen(zone, policy, kskdir)
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +2y -o")
|
||||||
ksks = keystr_to_keylist(out, kskdir)
|
ksks = keystr_to_keylist(out, kskdir)
|
||||||
assert len(ksks) == 1
|
assert len(ksks) == 1
|
||||||
|
|
||||||
|
check_keys(ksks, None)
|
||||||
|
|
||||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||||
zskdir = "ns1"
|
zskdir = "ns1"
|
||||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +2y")
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +2y")
|
||||||
@@ -959,10 +976,28 @@ def test_ksr_twotone(servers):
|
|||||||
|
|
||||||
# create ksk
|
# create ksk
|
||||||
kskdir = "ns1/offline"
|
kskdir = "ns1/offline"
|
||||||
out = keygen(zone, policy, kskdir)
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +1y -o")
|
||||||
ksks = keystr_to_keylist(out, kskdir)
|
ksks = keystr_to_keylist(out, kskdir)
|
||||||
assert len(ksks) == 2
|
assert len(ksks) == 2
|
||||||
|
|
||||||
|
ksks_defalg = []
|
||||||
|
ksks_altalg = []
|
||||||
|
for ksk in ksks:
|
||||||
|
alg = ksk.get_metadata("Algorithm")
|
||||||
|
if alg == os.environ.get("DEFAULT_ALGORITHM_NUMBER"):
|
||||||
|
ksks_defalg.append(ksk)
|
||||||
|
elif alg == os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER"):
|
||||||
|
ksks_altalg.append(ksk)
|
||||||
|
|
||||||
|
assert len(ksks_defalg) == 1
|
||||||
|
assert len(ksks_altalg) == 1
|
||||||
|
|
||||||
|
check_keys(ksks_defalg, None)
|
||||||
|
|
||||||
|
alg = os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER")
|
||||||
|
size = os.environ.get("ALTERNATIVE_BITS")
|
||||||
|
check_keys(ksks_altalg, None, alg, size)
|
||||||
|
|
||||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||||
zskdir = "ns1"
|
zskdir = "ns1"
|
||||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +1y")
|
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +1y")
|
||||||
|
@@ -24,6 +24,17 @@
|
|||||||
|
|
||||||
ISC_LANG_BEGINDECLS
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_keymgr_settime_syncpublish(dst_key_t *key, dns_kasp_t *kasp, bool first);
|
||||||
|
/*%<
|
||||||
|
* Set the SyncPublish time (when the DS may be submitted to the parent).
|
||||||
|
* If 'first' is true, also make sure that the zone signatures are omnipresent.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
*\li 'key' is a valid DNSSEC key.
|
||||||
|
*\li 'kasp' is a valid DNSSEC policy.
|
||||||
|
*/
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
|
dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
|
||||||
isc_mem_t *mctx, dns_dnsseckeylist_t *keyring,
|
isc_mem_t *mctx, dns_dnsseckeylist_t *keyring,
|
||||||
|
@@ -164,26 +164,25 @@ keymgr_settime_remove(dns_dnsseckey_t *key, dns_kasp_t *kasp) {
|
|||||||
* Set the SyncPublish time (when the DS may be submitted to the parent).
|
* Set the SyncPublish time (when the DS may be submitted to the parent).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
keymgr_settime_syncpublish(dns_dnsseckey_t *key, dns_kasp_t *kasp, bool first) {
|
dns_keymgr_settime_syncpublish(dst_key_t *key, dns_kasp_t *kasp, bool first) {
|
||||||
isc_stdtime_t published, syncpublish;
|
isc_stdtime_t published, syncpublish;
|
||||||
bool ksk = false;
|
bool ksk = false;
|
||||||
isc_result_t ret;
|
isc_result_t ret;
|
||||||
|
|
||||||
REQUIRE(key != NULL);
|
REQUIRE(key != NULL);
|
||||||
REQUIRE(key->key != NULL);
|
|
||||||
|
|
||||||
ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &published);
|
ret = dst_key_gettime(key, DST_TIME_PUBLISH, &published);
|
||||||
if (ret != ISC_R_SUCCESS) {
|
if (ret != ISC_R_SUCCESS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk);
|
ret = dst_key_getbool(key, DST_BOOL_KSK, &ksk);
|
||||||
if (ret != ISC_R_SUCCESS || !ksk) {
|
if (ret != ISC_R_SUCCESS || !ksk) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
syncpublish = published + dst_key_getttl(key->key) +
|
syncpublish = published + dst_key_getttl(key) +
|
||||||
dns_kasp_zonepropagationdelay(kasp) +
|
dns_kasp_zonepropagationdelay(kasp) +
|
||||||
dns_kasp_publishsafety(kasp);
|
dns_kasp_publishsafety(kasp);
|
||||||
if (first) {
|
if (first) {
|
||||||
@@ -197,7 +196,7 @@ keymgr_settime_syncpublish(dns_dnsseckey_t *key, dns_kasp_t *kasp, bool first) {
|
|||||||
syncpublish = zrrsig_present;
|
syncpublish = zrrsig_present;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dst_key_settime(key->key, DST_TIME_SYNCPUBLISH, syncpublish);
|
dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncpublish);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1863,7 +1862,7 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
|
|||||||
*/
|
*/
|
||||||
dst_key_settime(new_key->key, DST_TIME_PUBLISH, now);
|
dst_key_settime(new_key->key, DST_TIME_PUBLISH, now);
|
||||||
dst_key_settime(new_key->key, DST_TIME_ACTIVATE, now);
|
dst_key_settime(new_key->key, DST_TIME_ACTIVATE, now);
|
||||||
keymgr_settime_syncpublish(new_key, kasp, true);
|
dns_keymgr_settime_syncpublish(new_key->key, kasp, true);
|
||||||
active = now;
|
active = now;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@@ -1895,7 +1894,7 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
|
|||||||
}
|
}
|
||||||
dst_key_settime(new_key->key, DST_TIME_PUBLISH, prepub);
|
dst_key_settime(new_key->key, DST_TIME_PUBLISH, prepub);
|
||||||
dst_key_settime(new_key->key, DST_TIME_ACTIVATE, active);
|
dst_key_settime(new_key->key, DST_TIME_ACTIVATE, active);
|
||||||
keymgr_settime_syncpublish(new_key, kasp, false);
|
dns_keymgr_settime_syncpublish(new_key->key, kasp, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retire predecessor.
|
* Retire predecessor.
|
||||||
|
Reference in New Issue
Block a user