Commit 82b18406 authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

merged key_rollover event into dnssec event

parent d80a4b7b
......@@ -228,7 +228,6 @@ src/knot/events/handlers/notify.c
src/knot/events/handlers/nsec3resalt.c
src/knot/events/handlers/refresh.c
src/knot/events/handlers/update.c
src/knot/events/handlers/key_rollover.c
src/knot/events/handlers/parent_ds_query.c
src/knot/events/log.c
src/knot/events/log.h
......
......@@ -288,7 +288,6 @@ libknotd_la_SOURCES = \
knot/events/handlers/nsec3resalt.c \
knot/events/handlers/refresh.c \
knot/events/handlers/update.c \
knot/events/handlers/key_rollover.c \
knot/events/handlers/parent_ds_query.c \
knot/events/log.c \
knot/events/log.h \
......
......@@ -361,8 +361,11 @@ static int exec_remove_old_key(kdnssec_ctx_t *ctx, knot_kasp_key_t *key)
return kdnssec_delete_key(ctx, key);
}
int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_t *zone, bool *keys_changed, time_t *next_rollover)
int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_sign_reschedule_t *reschedule)
{
if (ctx == NULL || reschedule == NULL) {
return KNOT_EINVAL;
}
if (ctx->policy->manual) {
return KNOT_EOK;
}
......@@ -380,7 +383,7 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_t *zone, bool *keys_change
ret = generate_key(ctx, false, ctx->now);
}
if (ret == KNOT_EOK) {
*keys_changed = true;
reschedule->keys_changed = true;
}
if (ret != KNOT_EOK && ret != KNOT_ESEMCHECK) {
......@@ -389,9 +392,9 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_t *zone, bool *keys_change
roll_action next = next_action(ctx);
*next_rollover = next.time;
reschedule->next_rollover = next.time;
if (!ctx->policy->singe_type_signing && *next_rollover <= ctx->now) {
if (!ctx->policy->singe_type_signing && reschedule->next_rollover <= ctx->now) {
switch (next.type) {
case PUBLISH:
if (next.ksk && ctx->policy->ksk_shared) {
......@@ -402,13 +405,7 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_t *zone, bool *keys_change
break;
case SUBMIT:
ret = submit_key(ctx, next.key);
if (zone == NULL) {
return KNOT_EINVAL;
}
zone_events_schedule_now(zone, ZONE_EVENT_PARENT_DS_Q);
// "now" it won't probably succeed, but it replans itself for proper interval
log_zone_notice(zone->name, "DNSSEC, published CDS, CDNSKEY for submittion");
reschedule->plan_ds_query = true;
break;
case REPLACE:
ret = exec_new_signatures(ctx, next.key);
......@@ -421,15 +418,15 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_t *zone, bool *keys_change
}
if (ret == KNOT_EOK) {
*keys_changed = true;
reschedule->keys_changed = true;
next = next_action(ctx);
*next_rollover = next.time;
reschedule->next_rollover = next.time;
} else {
*next_rollover = time(NULL) + 10; // fail => try in 10seconds #TODO better?
reschedule->next_rollover = time(NULL) + 10; // fail => try in 10seconds #TODO better?
}
}
if (*keys_changed) {
if (reschedule->keys_changed) {
ret = kdnssec_ctx_commit(ctx);
}
return (ret == KNOT_ESEMCHECK ? KNOT_EOK : ret);
......
......@@ -19,6 +19,7 @@
#include <time.h>
#include "knot/dnssec/context.h"
#include "knot/dnssec/zone-events.h"
#include "knot/zone/zone.h"
/*!
......@@ -38,7 +39,7 @@
*
* \return KNOT_E*
*/
int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_t *zone, bool *keys_changed, time_t *next_rollover);
int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_sign_reschedule_t *reschedule);
int knot_dnssec_ksk_submittion_confirm(kdnssec_ctx_t *ctx, uint16_t for_key);
......
......@@ -23,6 +23,7 @@
#include "knot/conf/conf.h"
#include "knot/common/log.h"
#include "knot/dnssec/context.h"
#include "knot/dnssec/key-events.h"
#include "knot/dnssec/policy.h"
#include "knot/dnssec/zone-events.h"
#include "knot/dnssec/zone-keys.h"
......@@ -30,7 +31,8 @@
#include "knot/dnssec/zone-sign.h"
#include "knot/zone/serial.h"
static int sign_init(const zone_contents_t *zone, int flags, kdnssec_ctx_t *ctx)
static int sign_init(const zone_contents_t *zone, int flags, kdnssec_ctx_t *ctx,
zone_sign_reschedule_t *reschedule)
{
assert(zone);
assert(ctx);
......@@ -42,6 +44,15 @@ static int sign_init(const zone_contents_t *zone, int flags, kdnssec_ctx_t *ctx)
return r;
}
// perform key rollover if needed
if (reschedule->allow_rollover) {
r = knot_dnssec_key_rollover(ctx, reschedule);
}
if (r != KNOT_EOK) {
return r;
}
// update policy based on the zone content
update_policy_from_zone(ctx->policy, zone);
......@@ -146,9 +157,9 @@ int knot_dnssec_nsec3resalt(kdnssec_ctx_t *ctx, bool *salt_changed, time_t *when
}
int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
zone_sign_flags_t flags, uint32_t *refresh_at)
zone_sign_flags_t flags, zone_sign_reschedule_t *reschedule)
{
if (!zone || !out_ch || !refresh_at) {
if (!zone || !out_ch || !reschedule) {
return KNOT_EINVAL;
}
......@@ -159,7 +170,7 @@ int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
// signing pipeline
result = sign_init(zone, flags, &ctx);
result = sign_init(zone, flags, &ctx, reschedule);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to initialize (%s)",
knot_strerror(result));
......@@ -211,7 +222,7 @@ int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
done:
if (result == KNOT_EOK) {
*refresh_at = schedule_next(&ctx, &keyset, zone_expire);
reschedule->next_sign = schedule_next(&ctx, &keyset, zone_expire);
}
free_zone_keys(&keyset);
......@@ -223,9 +234,9 @@ done:
int knot_dnssec_sign_changeset(const zone_contents_t *zone,
const changeset_t *in_ch,
changeset_t *out_ch,
uint32_t *refresh_at)
zone_sign_reschedule_t *reschedule)
{
if (zone == NULL || in_ch == NULL || out_ch == NULL || refresh_at == NULL) {
if (zone == NULL || in_ch == NULL || out_ch == NULL || reschedule == NULL) {
return KNOT_EINVAL;
}
......@@ -236,7 +247,7 @@ int knot_dnssec_sign_changeset(const zone_contents_t *zone,
// signing pipeline
result = sign_init(zone, ZONE_SIGN_KEEP_SOA_SERIAL, &ctx);
result = sign_init(zone, ZONE_SIGN_KEEP_SOA_SERIAL, &ctx, reschedule);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to initialize (%s)",
knot_strerror(result));
......@@ -284,8 +295,8 @@ int knot_dnssec_sign_changeset(const zone_contents_t *zone,
// schedule next resigning (only new signatures are made)
*refresh_at = ctx.now + ctx.policy->rrsig_lifetime - ctx.policy->rrsig_refresh_before;
assert(refresh_at > 0);
reschedule->next_sign = ctx.now + ctx.policy->rrsig_lifetime - ctx.policy->rrsig_refresh_before;
assert(reschedule->next_sign > 0);
done:
free_zone_keys(&keyset);
......
......@@ -30,6 +30,14 @@ enum zone_sign_flags {
typedef enum zone_sign_flags zone_sign_flags_t;
typedef struct {
time_t next_sign;
time_t next_rollover;
bool keys_changed;
bool plan_ds_query;
bool allow_rollover; // this one is set by the caller
} zone_sign_reschedule_t;
/*!
* \brief Generate/rollover keys in keystore as needed.
*
......@@ -53,7 +61,7 @@ int knot_dnssec_sign_process_events(const kdnssec_ctx_t *kctx,
* \return Error code, KNOT_EOK if successful.
*/
int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
zone_sign_flags_t flags, uint32_t *refresh_at);
zone_sign_flags_t flags, zone_sign_reschedule_t *reschedule);
/*!
* \brief Sign changeset created by DDNS or zone-diff.
......@@ -68,7 +76,7 @@ int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
int knot_dnssec_sign_changeset(const zone_contents_t *zone,
const changeset_t *in_ch,
changeset_t *out_ch,
uint32_t *refresh_at);
zone_sign_reschedule_t *reschedule);
/*!
* \brief Create new NCES3 salt if the old one is too old, and plan next resalt.
......
......@@ -47,7 +47,6 @@ static const event_info_t EVENT_INFO[] = {
{ ZONE_EVENT_UFREEZE, event_ufreeze, "update freeze" },
{ ZONE_EVENT_UTHAW, event_uthaw, "update thaw" },
{ ZONE_EVENT_NSEC3RESALT, event_nsec3resalt, "NSEC3 resalt" },
{ ZONE_EVENT_KEY_ROLLOVER, event_key_rollover, "KEY rollover" },
{ ZONE_EVENT_PARENT_DS_Q, event_parent_ds_q, "parent DS query" },
{ 0 }
};
......@@ -79,7 +78,6 @@ bool ufreeze_applies(zone_event_type_t type)
case ZONE_EVENT_FLUSH:
case ZONE_EVENT_DNSSEC:
case ZONE_EVENT_NSEC3RESALT:
case ZONE_EVENT_KEY_ROLLOVER:
case ZONE_EVENT_PARENT_DS_Q:
return true;
default:
......
......@@ -40,7 +40,6 @@ typedef enum zone_event_type {
ZONE_EVENT_UFREEZE,
ZONE_EVENT_UTHAW,
ZONE_EVENT_NSEC3RESALT,
ZONE_EVENT_KEY_ROLLOVER,
ZONE_EVENT_PARENT_DS_Q,
// terminator
ZONE_EVENT_COUNT,
......
......@@ -18,6 +18,7 @@
#include "knot/conf/conf.h"
#include "knot/zone/zone.h"
#include "knot/dnssec/zone-events.h" // zone_sign_reschedule_t
/*! \brief Loads or reloads potentially changed zone. */
int event_load(conf_t *conf, zone_t *zone);
......@@ -31,15 +32,16 @@ int event_expire(conf_t *conf, zone_t *zone);
int event_flush(conf_t *conf, zone_t *zone);
/*! \brief Sends notify to slaves. */
int event_notify(conf_t *conf, zone_t *zone);
/*! \brief Signs the zone using its DNSSEC keys. */
/*! \brief Signs the zone using its DNSSEC keys, perform key rollovers. */
int event_dnssec(conf_t *conf, zone_t *zone);
/*! \brief NOT A HANDLER, just a helper function to reschedule based on reschedule_t */
void event_dnssec_reschedule(conf_t *conf, zone_t *zone,
const zone_sign_reschedule_t *refresh, bool zone_changed);
/*! \brief Freeze those events causing zone contents change. */
int event_ufreeze(conf_t *conf, zone_t *zone);
/*! \brief Unfreeze zone updates. */
int event_uthaw(conf_t *conf, zone_t *zone);
/*! \brief Recreates salt for NSEC3 hashing. */
int event_nsec3resalt(conf_t *conf, zone_t *zone);
/*! \brief ZSK rollover related actions (key creation, publishing, deleting...). */
int event_key_rollover(conf_t *conf, zone_t *zone);
/*! \brief When CDS/CDNSKEY published, look for matching DS */
int event_parent_ds_q(conf_t *conf, zone_t *zone);
......@@ -25,18 +25,30 @@
#include "knot/zone/zone.h"
#include "libknot/errcode.h"
static void reschedule(conf_t *conf, zone_t *zone,
time_t dnssec_refresh, bool zone_changed)
void event_dnssec_reschedule(conf_t *conf, zone_t *zone,
const zone_sign_reschedule_t *refresh, bool zone_changed)
{
time_t now = time(NULL);
time_t ignore = -1;
time_t refresh_at = refresh->next_sign;
if (refresh->next_rollover < refresh_at && refresh->next_rollover > 0) {
refresh_at = refresh->next_rollover;
}
conf_val_t val = conf_zone_get(conf, C_ZONEFILE_SYNC, zone->name);
log_dnssec_next(zone->name, refresh_at);
if (refresh->plan_ds_query) {
log_zone_notice(zone->name, "DNSSEC, published CDS, CDNSKEY for submittion");
}
zone_events_schedule_at(zone,
ZONE_EVENT_DNSSEC, dnssec_refresh,
ZONE_EVENT_DNSSEC, refresh_at,
ZONE_EVENT_PARENT_DS_Q, refresh->plan_ds_query ? now : ignore,
ZONE_EVENT_NOTIFY, zone_changed ? now : ignore,
ZONE_EVENT_FLUSH, conf_int(&val) == 0 ? now : ignore
ZONE_EVENT_FLUSH, zone_changed && conf_int(&val) == 0 ? now : ignore
);
}
......@@ -50,7 +62,8 @@ int event_dnssec(conf_t *conf, zone_t *zone)
goto done;
}
uint32_t refresh_at = time(NULL);
zone_sign_reschedule_t resch = { 0 };
resch.allow_rollover = true;
int sign_flags = 0;
if (zone->flags & ZONE_FORCE_RESIGN) {
......@@ -63,7 +76,7 @@ int event_dnssec(conf_t *conf, zone_t *zone)
sign_flags = 0;
}
ret = knot_dnssec_zone_sign(zone->contents, &ch, sign_flags, &refresh_at);
ret = knot_dnssec_zone_sign(zone->contents, &ch, sign_flags, &resch);
if (ret != KNOT_EOK) {
goto done;
}
......@@ -101,8 +114,7 @@ int event_dnssec(conf_t *conf, zone_t *zone)
}
// Schedule dependent events
log_dnssec_next(zone->name, refresh_at);
reschedule(conf, zone, refresh_at, zone_changed);
event_dnssec_reschedule(conf, zone, &resch, zone_changed);
done:
changeset_clear(&ch);
......
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "knot/dnssec/key-events.h"
#include "knot/zone/zone.h"
int event_key_rollover(conf_t *conf, zone_t *zone)
{
bool keys_updated = false;
time_t next_rollover = 0;
kdnssec_ctx_t kctx = { 0 };
int ret = kdnssec_ctx_init(conf, &kctx, zone->name, NULL);
if (ret != KNOT_EOK) {
return ret;
}
ret = knot_dnssec_key_rollover(&kctx, zone, &keys_updated, &next_rollover);
kdnssec_ctx_deinit(&kctx);
if (next_rollover) {
zone_events_schedule_at(zone, ZONE_EVENT_KEY_ROLLOVER, next_rollover);
}
if (ret != KNOT_EOK) {
return ret;
}
if (keys_updated) {
zone_events_schedule_now(zone, ZONE_EVENT_DNSSEC);
}
return KNOT_EOK;
}
......@@ -19,6 +19,7 @@
#include "knot/common/log.h"
#include "knot/conf/conf.h"
#include "knot/dnssec/zone-events.h"
#include "knot/events/handlers.h"
#include "knot/events/log.h"
#include "knot/events/replan.h"
......@@ -32,7 +33,8 @@ int event_load(conf_t *conf, zone_t *zone)
zone_contents_t *contents = NULL;
bool load_from_journal = false;
uint32_t dnssec_refresh = time(NULL);
zone_sign_reschedule_t dnssec_refresh = { 0 };
dnssec_refresh.allow_rollover = true;
/* Take zone file mtime and load it. */
time_t mtime;
......@@ -112,12 +114,10 @@ load_post:
conf_val_t val = conf_zone_get(conf, C_DNSSEC_SIGNING, zone->name);
if (conf_bool(&val)) {
zone_events_schedule_now(zone, ZONE_EVENT_KEY_ROLLOVER);
zone_events_schedule_now(zone, ZONE_EVENT_NSEC3RESALT);
// if nothing to be done NOW for any of those, they will replan themselves for later
log_dnssec_next(zone->name, dnssec_refresh);
zone_events_schedule_at(zone, ZONE_EVENT_DNSSEC, dnssec_refresh);
event_dnssec_reschedule(conf, zone, &dnssec_refresh, false); // false since we handle NOTIFY below
}
// TODO: track serial across restart and avoid unnecessary notify
......
......@@ -210,8 +210,7 @@ int event_parent_ds_q(conf_t *conf, zone_t *zone)
time_t next_check = time(NULL) + ctx.policy->ksk_submittion_check_interval;
zone_events_schedule_at(zone, ZONE_EVENT_PARENT_DS_Q, next_check);
} else {
zone_events_schedule_now(zone, ZONE_EVENT_KEY_ROLLOVER);
zone_events_schedule_now(zone, ZONE_EVENT_DNSSEC); // TODO needed ?
zone_events_schedule_now(zone, ZONE_EVENT_DNSSEC);
}
free_zone_keys(&keyset);
......
......@@ -73,7 +73,6 @@ static void replan_dnssec(conf_t *conf, zone_t *zone)
conf_val_t val = conf_zone_get(conf, C_DNSSEC_SIGNING, zone->name);
if (conf_bool(&val)) {
zone_events_schedule_now(zone, ZONE_EVENT_KEY_ROLLOVER);
zone_events_schedule_now(zone, ZONE_EVENT_NSEC3RESALT);
zone_events_schedule_now(zone, ZONE_EVENT_DNSSEC);
}
......
......@@ -451,9 +451,9 @@ static int get_online_key(dnssec_key_t **key_ptr, knotd_mod_t *mod)
// Force Singe-Type signing scheme.
kctx.policy->singe_type_signing = true;
bool ignore1 = false;
time_t ignore2 = 0;
r = knot_dnssec_key_rollover(&kctx, NULL, &ignore1, &ignore2);
zone_sign_reschedule_t ignore_out = { 0 };
ignore_out.allow_rollover = true;
r = knot_dnssec_key_rollover(&kctx, &ignore_out);
if (r != DNSSEC_EOK) {
goto fail;
}
......
......@@ -400,7 +400,7 @@ static int sign_update(zone_update_t *update,
/* Check if the UPDATE changed DNSKEYs or NSEC3PARAM.
* If so, we have to sign the whole zone. */
int ret = KNOT_EOK;
uint32_t refresh_at = 0;
zone_sign_reschedule_t resch = { 0 };
changeset_t sec_ch;
ret = changeset_init(&sec_ch, update->zone->name);
if (ret != KNOT_EOK) {
......@@ -412,11 +412,11 @@ static int sign_update(zone_update_t *update,
if (full_sign) {
ret = knot_dnssec_zone_sign(new_contents, &sec_ch,
ZONE_SIGN_KEEP_SOA_SERIAL,
&refresh_at);
&resch);
} else {
/* Sign the created changeset */
ret = knot_dnssec_sign_changeset(new_contents, &update->change,
&sec_ch, &refresh_at);
&sec_ch, &resch);
}
if (ret != KNOT_EOK) {
changeset_clear(&sec_ch);
......@@ -441,9 +441,8 @@ static int sign_update(zone_update_t *update,
}
/* Plan next zone resign. */
const time_t resign_time = zone_events_get_time(update->zone, ZONE_EVENT_DNSSEC);
if (refresh_at < resign_time) {
zone_events_schedule_at(update->zone, ZONE_EVENT_DNSSEC, refresh_at);
if (resch.next_sign > 0) {
zone_events_schedule_at(update->zone, ZONE_EVENT_DNSSEC, resch.next_sign);
}
/* We are not calling update_cleanup, as the rollback data are merged
......
......@@ -209,7 +209,7 @@ int zone_load_from_journal(conf_t *conf, zone_t *zone, zone_contents_t **content
}
int zone_load_post(conf_t *conf, zone_t *zone, zone_contents_t *contents,
uint32_t *dnssec_refresh)
zone_sign_reschedule_t *dnssec_refresh)
{
if (conf == NULL || zone == NULL || contents == NULL) {
return KNOT_EINVAL;
......@@ -243,13 +243,6 @@ int zone_load_post(conf_t *conf, zone_t *zone, zone_contents_t *contents,
return ret;
}
ignore1 = false; ignore2 = 0;
ret = knot_dnssec_key_rollover(&kctx, zone, &ignore1, &ignore2);
if (zone_has_key_submittion(&kctx)) {
zone_events_schedule_now(zone, ZONE_EVENT_PARENT_DS_Q);
}
kdnssec_ctx_deinit(&kctx);
if (ret != KNOT_EOK) {
changeset_clear(&change);
......
......@@ -18,6 +18,7 @@
#include "knot/conf/conf.h"
#include "knot/zone/zone.h"
#include "knot/dnssec/zone-events.h" // zone_sign_reschedule_t
/*!
* \brief Load zone contents according to the configuration.
......@@ -63,7 +64,7 @@ int zone_load_from_journal(conf_t *conf, zone_t *zone,
* \return KNOT_EOK or an error
*/
int zone_load_post(conf_t *conf, zone_t *zone, zone_contents_t *contents,
uint32_t *dnssec_refresh);
zone_sign_reschedule_t *dnssec_refresh);
/*!
* \brief Check if zone can be bootstrapped.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment