diff --git a/doc/man_knotc.rst b/doc/man_knotc.rst index 33368f36a..39e75e9c5 100644 --- a/doc/man_knotc.rst +++ b/doc/man_knotc.rst @@ -183,10 +183,12 @@ Actions key management enabled. Note that complete key rollover consists of several steps and the blocking mode relates to the initial one only! (#) -**zone-ksk-submitted** *zone*... +**zone-ksk-submitted** *zone*... [**+ttl** *seconds*] Use when the zone's KSK rollover is in submission phase. By calling this command the user confirms manually that the parent zone contains DS record for the new - KSK in submission phase and the old KSK can be retired. (#) + KSK in submission phase and the old KSK can be retired. The optional **+ttl** + parameter specifies the parent DS's TTL and possibly other delays, with the + effect that the removal of old KSK is postponed by this amount of seconds. (#) **zone-freeze** [*zone*...] Trigger a zone freeze. All running events will be finished and all new and pending diff --git a/python/libknot/README.md b/python/libknot/README.md index 181693bd8..bf0ec5bc4 100644 --- a/python/libknot/README.md +++ b/python/libknot/README.md @@ -137,7 +137,9 @@ The following commands apply to all zones if `ZONE` is left empty. * `zone-validate([ZONE], [FLAGS="B"])` * `zone-keys-load([ZONE], [FLAGS="B"])` * `zone-key-rollover([ZONE], TYPE="ksk"|"zsk", [FLAGS="B"])` -* `zone-ksk-submitted([ZONE], [FLAGS="B"])` +* `zone-ksk-submitted([ZONE], [FILTERS="t", DATA], [FLAGS="B"])` + + the **t**tl filter commands that removal of old KSK is postponed by the amount of seconds + stored in the `DATA` section * `zone-freeze([ZONE], [FLAGS="B"])` * `zone-thaw([ZONE], [FLAGS="B"])` * `zone-xfr-freeze([ZONE], [FLAGS="B"])` diff --git a/src/knot/ctl/commands.c b/src/knot/ctl/commands.c index 392f0664a..7614a2511 100644 --- a/src/knot/ctl/commands.c +++ b/src/knot/ctl/commands.c @@ -845,12 +845,23 @@ static int zone_ksk_sbm_confirm(zone_t *zone, _unused_ ctl_args_t *args) { kdnssec_ctx_t ctx = { 0 }; - int ret = kdnssec_ctx_init(conf(), &ctx, zone->name, zone_kaspdb(zone), NULL); + int ret = KNOT_EOK; + + uint32_t ds_ttl = 0; + const char *ds_ttl_s = args->data[KNOT_CTL_IDX_DATA]; + if (MATCH_AND_FILTER(args, CTL_FILTER_KSK_SBM_TTL) && ds_ttl_s != NULL) { + ret = str_to_u32(ds_ttl_s, &ds_ttl); + if (ret != KNOT_EOK) { + return ret; + } + } + + ret = kdnssec_ctx_init(conf(), &ctx, zone->name, zone_kaspdb(zone), NULL); if (ret != KNOT_EOK) { return ret; } - ret = knot_dnssec_ksk_sbm_confirm(&ctx, 0); + ret = knot_dnssec_ksk_sbm_confirm(&ctx, ds_ttl); kdnssec_ctx_deinit(&ctx); conf_val_t val = conf_zone_get(conf(), C_DNSSEC_SIGNING, zone->name); diff --git a/src/knot/ctl/commands.h b/src/knot/ctl/commands.h index 25b893514..0e4351927 100644 --- a/src/knot/ctl/commands.h +++ b/src/knot/ctl/commands.h @@ -20,6 +20,8 @@ #define CTL_FILTER_FLUSH_OUTDIR "d" +#define CTL_FILTER_KSK_SBM_TTL "t" + #define CTL_FILTER_STATUS_LOADING "l" #define CTL_FILTER_STATUS_ROLE "r" diff --git a/src/utils/knotc/commands.c b/src/utils/knotc/commands.c index 3e78ba307..a8af19b10 100644 --- a/src/utils/knotc/commands.c +++ b/src/utils/knotc/commands.c @@ -652,6 +652,11 @@ const filter_desc_t zone_flush_filters[] = { { NULL }, }; +const filter_desc_t zone_ksk_sbm_filters[] = { + { "+ttl", CTL_FILTER_KSK_SBM_TTL, true }, + { NULL }, +}; + const filter_desc_t zone_backup_filters[] = { { "+backupdir", CTL_FILTER_BACKUP_OUTDIR, true }, // This must be the first. { "+zonefile", CTL_FILTER_BACKUP_ZONEFILE, false }, @@ -706,6 +711,9 @@ static const filter_desc_t *get_filter(ctl_cmd_t cmd, const char *filter_name) case CTL_ZONE_FLUSH: fd = zone_flush_filters; break; + case CTL_ZONE_KSK_SBM: + fd = zone_ksk_sbm_filters; + break; case CTL_ZONE_BACKUP: case CTL_ZONE_RESTORE: fd = zone_backup_filters;