Commit 512fb4b0 authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'keymgr-upgrade' into 'master'

keymgr: add support for upgrade



See merge request !480
parents 3b1aec02 3e6f017b
......@@ -67,8 +67,12 @@ directory.
.INDENT 0.0
.TP
\fBinit\fP
Initialize new KASP database. This also creates a default policy and default
key store (both named \fIdefault\fP).
Initialize new KASP database or upgrade existing one. The command is
idempotent and therefore it is safe to be run multiple times.
.sp
The command creates a default policy and default key store (both named
\fIdefault\fP). In case of upgrade, existing objects are checked and any missing
attributes are filled in.
.TP
\fBzone\fP ...
Operations with zones in the database. A zone holds assigned signing
......
......@@ -44,8 +44,12 @@ Main commands
.............
**init**
Initialize new KASP database. This also creates a default policy and default
key store (both named *default*).
Initialize new KASP database or upgrade existing one. The command is
idempotent and therefore it is safe to be run multiple times.
The command creates a default policy and default key store (both named
*default*). In case of upgrade, existing objects are checked and any missing
attributes are filled in.
**zone** ...
Operations with zones in the database. A zone holds assigned signing
......
......@@ -177,7 +177,7 @@ int dnssec_kasp_zone_load(dnssec_kasp_t *kasp, const char *name,
* \param kasp KASP instance.
* \param zone Zone to be saved.
*/
int dnssec_kasp_zone_save(dnssec_kasp_t *kasp, dnssec_kasp_zone_t *zone);
int dnssec_kasp_zone_save(dnssec_kasp_t *kasp, const dnssec_kasp_zone_t *zone);
/*!
* Remove zone from KASP.
......@@ -339,7 +339,7 @@ int dnssec_kasp_policy_load(dnssec_kasp_t *kasp, const char *name,
* \param kasp KASP instance.
* \param policy Policy to be saved.
*/
int dnssec_kasp_policy_save(dnssec_kasp_t *kasp, dnssec_kasp_policy_t *policy);
int dnssec_kasp_policy_save(dnssec_kasp_t *kasp, const dnssec_kasp_policy_t *policy);
/*!
* Remove a policy from the KASP.
......@@ -379,7 +379,7 @@ dnssec_kasp_keystore_t *dnssec_kasp_keystore_new(const char *name);
void dnssec_kasp_keystore_free(dnssec_kasp_keystore_t *keystore);
int dnssec_kasp_keystore_load(dnssec_kasp_t *kasp, const char *name, dnssec_kasp_keystore_t **keystore);
int dnssec_kasp_keystore_save(dnssec_kasp_t *kasp, dnssec_kasp_keystore_t *keystore);
int dnssec_kasp_keystore_save(dnssec_kasp_t *kasp, const dnssec_kasp_keystore_t *keystore);
int dnssec_kasp_keystore_remove(dnssec_kasp_t *kasp, const char *name);
int dnssec_kasp_keystore_list(dnssec_kasp_t *kasp, dnssec_list_t **names);
int dnssec_kasp_keystore_exists(dnssec_kasp_t *kasp, const char *name);
......
......@@ -198,7 +198,7 @@ static int kasp_dir_zone_load(void *ctx, dnssec_kasp_zone_t *zone)
return entity_io(ENTITY_ZONE, ctx, zone, load_zone_config);
}
static int kasp_dir_zone_save(void *ctx, dnssec_kasp_zone_t *zone)
static int kasp_dir_zone_save(void *ctx, const dnssec_kasp_zone_t *zone)
{
return entity_io(ENTITY_ZONE, ctx, zone, save_zone_config);
}
......@@ -225,7 +225,7 @@ static int kasp_dir_policy_load(void *ctx, dnssec_kasp_policy_t *policy)
return entity_io(ENTITY_POLICY, ctx, policy, load_policy_config);
}
static int kasp_dir_policy_save(void *ctx, dnssec_kasp_policy_t *policy)
static int kasp_dir_policy_save(void *ctx, const dnssec_kasp_policy_t *policy)
{
return entity_io(ENTITY_POLICY, ctx, policy, save_policy_config);
}
......@@ -252,7 +252,7 @@ static int kasp_dir_keystore_load(void *ctx, dnssec_kasp_keystore_t *keystore)
return entity_io(ENTITY_KEYSTORE, ctx, keystore, load_keystore_config);
}
static int kasp_dir_keystore_save(void *ctx, dnssec_kasp_keystore_t *keystore)
static int kasp_dir_keystore_save(void *ctx, const dnssec_kasp_keystore_t *keystore)
{
return entity_io(ENTITY_KEYSTORE, ctx, keystore, save_keystore_config);
}
......
......@@ -29,7 +29,7 @@ static const encode_attr_t ATTRIBUTES[] = {
{ NULL }
};
static bool keystore_valid(dnssec_kasp_keystore_t *keystore)
static bool keystore_valid(const dnssec_kasp_keystore_t *keystore)
{
assert(keystore);
return keystore->backend && keystore->config;
......@@ -54,7 +54,7 @@ static int import_keystore(dnssec_kasp_keystore_t *keystore, const json_t *json)
return DNSSEC_EOK;
}
static int export_keystore(dnssec_kasp_keystore_t *keystore, json_t **json)
static int export_keystore(const dnssec_kasp_keystore_t *keystore, json_t **json)
{
assert(keystore);
assert(json);
......@@ -87,7 +87,7 @@ int load_keystore_config(dnssec_kasp_keystore_t *keystore, const char *filename)
return import_keystore(keystore, json);
}
int save_keystore_config(dnssec_kasp_keystore_t *keystore, const char *filename)
int save_keystore_config(const dnssec_kasp_keystore_t *keystore, const char *filename)
{
assert(keystore);
assert(filename);
......
......@@ -20,4 +20,4 @@
int load_keystore_config(dnssec_kasp_keystore_t *keystore, const char *filename);
int save_keystore_config(dnssec_kasp_keystore_t *keystore, const char *filename);
int save_keystore_config(const dnssec_kasp_keystore_t *keystore, const char *filename);
......@@ -60,7 +60,7 @@ int load_policy_config(dnssec_kasp_policy_t *policy, const char *filename)
return decode_object(POLICY_ATTRS, config, policy);
}
int save_policy_config(dnssec_kasp_policy_t *policy, const char *filename)
int save_policy_config(const dnssec_kasp_policy_t *policy, const char *filename)
{
assert(policy);
assert(filename);
......
......@@ -20,4 +20,4 @@
int load_policy_config(dnssec_kasp_policy_t *policy, const char *filename);
int save_policy_config(dnssec_kasp_policy_t *policy, const char *filename);
int save_policy_config(const dnssec_kasp_policy_t *policy, const char *filename);
......@@ -239,7 +239,7 @@ static void key_to_params(dnssec_kasp_key_t *key, key_params_t *params)
/*!
* Convert KASP keys to JSON array.
*/
static int export_zone_keys(dnssec_kasp_zone_t *zone, json_t **keys_ptr)
static int export_zone_keys(const dnssec_kasp_zone_t *zone, json_t **keys_ptr)
{
json_t *keys = json_array();
if (!keys) {
......@@ -270,7 +270,7 @@ static int export_zone_keys(dnssec_kasp_zone_t *zone, json_t **keys_ptr)
return DNSSEC_EOK;
}
static int export_zone_config(dnssec_kasp_zone_t *zone, json_t **config_ptr)
static int export_zone_config(const dnssec_kasp_zone_t *zone, json_t **config_ptr)
{
assert(zone);
assert(config_ptr);
......@@ -304,7 +304,7 @@ static int parse_zone_config(dnssec_kasp_zone_t *zone, json_t *config)
char *policy = NULL;
json_t *json_policy = json_object_get(config, "policy");
if (json_policy && !json_is_null(json_policy)) {
if (json_policy && json_is_string(json_policy)) {
policy = strdup(json_string_value(json_policy));
if (!policy) {
return DNSSEC_ENOMEM;
......@@ -357,7 +357,7 @@ int load_zone_config(dnssec_kasp_zone_t *zone, const char *filename)
/*!
* Save zone configuration.
*/
int save_zone_config(dnssec_kasp_zone_t *zone, const char *filename)
int save_zone_config(const dnssec_kasp_zone_t *zone, const char *filename)
{
assert(zone);
assert(filename);
......
......@@ -20,4 +20,4 @@
int load_zone_config(dnssec_kasp_zone_t *zone, const char *filename);
int save_zone_config(dnssec_kasp_zone_t *zone, const char *filename);
int save_zone_config(const dnssec_kasp_zone_t *zone, const char *filename);
......@@ -31,19 +31,19 @@ typedef struct dnssec_kasp_store_functions {
const char *(*base_path)(void *ctx);
// zone serialization/deserialization
int (*zone_load)(void *ctx, dnssec_kasp_zone_t *zone);
int (*zone_save)(void *ctx, dnssec_kasp_zone_t *zone);
int (*zone_save)(void *ctx, const dnssec_kasp_zone_t *zone);
int (*zone_remove)(void *ctx, const char *zone_name);
int (*zone_list)(void *ctx, dnssec_list_t *zone_names);
int (*zone_exists)(void *ctx, const char *zone_name);
// policy serialization/deserialization
int (*policy_load)(void *ctx, dnssec_kasp_policy_t *policy);
int (*policy_save)(void *ctx, dnssec_kasp_policy_t *policy);
int (*policy_save)(void *ctx, const dnssec_kasp_policy_t *policy);
int (*policy_remove)(void *ctx, const char *name);
int (*policy_list)(void *ctx, dnssec_list_t *policy_names);
int (*policy_exists)(void *ctx, const char *name);
// keystore serialization/deserialization
int (*keystore_load)(void *ctx, dnssec_kasp_keystore_t *keystore);
int (*keystore_save)(void *ctx, dnssec_kasp_keystore_t *keystore);
int (*keystore_save)(void *ctx, const dnssec_kasp_keystore_t *keystore);
int (*keystore_remove)(void *ctx, const char *name);
int (*keystore_list)(void *ctx, dnssec_list_t *names);
int (*keystore_exists)(void *ctx, const char *name);
......
......@@ -137,7 +137,7 @@ int dnssec_kasp_zone_load(dnssec_kasp_t *kasp, const char *zone_name,
}
_public_
int dnssec_kasp_zone_save(dnssec_kasp_t *kasp, dnssec_kasp_zone_t *zone)
int dnssec_kasp_zone_save(dnssec_kasp_t *kasp, const dnssec_kasp_zone_t *zone)
{
if (!kasp || !zone || !zone_valid(zone)) {
return DNSSEC_EINVAL;
......@@ -218,7 +218,7 @@ int dnssec_kasp_policy_load(dnssec_kasp_t *kasp, const char *name,
}
_public_
int dnssec_kasp_policy_save(dnssec_kasp_t *kasp, dnssec_kasp_policy_t *policy)
int dnssec_kasp_policy_save(dnssec_kasp_t *kasp, const dnssec_kasp_policy_t *policy)
{
if (!kasp || !policy) {
return DNSSEC_EINVAL;
......@@ -295,7 +295,7 @@ int dnssec_kasp_keystore_load(dnssec_kasp_t *kasp, const char *name,
}
_public_
int dnssec_kasp_keystore_save(dnssec_kasp_t *kasp, dnssec_kasp_keystore_t *keystore)
int dnssec_kasp_keystore_save(dnssec_kasp_t *kasp, const dnssec_kasp_keystore_t *keystore)
{
if (!kasp || !keystore) {
return DNSSEC_EINVAL;
......
......@@ -63,7 +63,7 @@ static int mock_zone_load(void *ctx, dnssec_kasp_zone_t *zone)
}
static bool mock_zone_save_ok = false;
static int mock_zone_save(void *ctx, dnssec_kasp_zone_t *zone)
static int mock_zone_save(void *ctx, const dnssec_kasp_zone_t *zone)
{
mock_zone_save_ok = ctx == MOCK_CTX && zone &&
streq(zone->policy, "cuttingedge");
......@@ -110,7 +110,7 @@ static int mock_policy_load(void *ctx, dnssec_kasp_policy_t *policy)
}
static bool mock_policy_save_ok = false;
static int mock_policy_save(void *ctx, dnssec_kasp_policy_t *policy)
static int mock_policy_save(void *ctx, const dnssec_kasp_policy_t *policy)
{
mock_policy_save_ok = ctx == MOCK_CTX && policy &&
streq(policy->name, "happy") &&
......@@ -159,7 +159,7 @@ static int mock_keystore_load(void *ctx, dnssec_kasp_keystore_t *keystore)
}
static bool mock_keystore_save_ok = false;
static int mock_keystore_save(void *ctx, dnssec_kasp_keystore_t *keystore)
static int mock_keystore_save(void *ctx, const dnssec_kasp_keystore_t *keystore)
{
mock_keystore_save_ok = ctx == MOCK_CTX && keystore &&
streq(keystore->name, "foobar") &&
......
......@@ -42,6 +42,8 @@
#define DEFAULT_POLICY "default"
#define DEFAULT_KEYSTORE "default"
#define MANUAL_POLICY "default_manual"
/* -- global options ------------------------------------------------------- */
struct options {
......@@ -360,15 +362,11 @@ static bool init_kasp(dnssec_kasp_t **kasp_ptr)
return true;
}
static bool init_default_keystore(dnssec_kasp_t *kasp)
static int create_default_keystore(dnssec_kasp_t *kasp)
{
int r = dnssec_kasp_keystore_exists(kasp, DEFAULT_KEYSTORE);
if (r == DNSSEC_EOK) {
return true;
} else if (r != DNSSEC_NOT_FOUND) {
error("Failed to check if the default key store exists (%s).",
dnssec_strerror(r));
return false;
if (r == DNSSEC_EOK || r != DNSSEC_NOT_FOUND) {
return r;
}
dnssec_kasp_keystore_t config = {
......@@ -380,44 +378,155 @@ static bool init_default_keystore(dnssec_kasp_t *kasp)
_cleanup_keystore_ dnssec_keystore_t *keystore = NULL;
r = dnssec_kasp_keystore_init(kasp, config.backend, config.config, &keystore);
if (r != DNSSEC_EOK) {
error("Failed to initialize the default key store (%s).",
dnssec_strerror(r));
return false;
return r;
}
r = dnssec_kasp_keystore_save(kasp, &config);
if (r != DNSSEC_EOK) {
error("Failed to save the default key store configuration (%s).",
dnssec_strerror(r));
return false;
return r;
}
return true;
return DNSSEC_EOK;
}
static bool init_default_policy(dnssec_kasp_t *kasp)
static int create_policy(dnssec_kasp_t *kasp, const dnssec_kasp_policy_t *policy)
{
int r = dnssec_kasp_policy_exists(kasp, DEFAULT_POLICY);
if (r == DNSSEC_EOK) {
return true;
} else if (r != DNSSEC_NOT_FOUND) {
error("Failed to check if the default policy exists (%s).",
dnssec_strerror(r));
int r = dnssec_kasp_policy_exists(kasp, policy->name);
if (r == DNSSEC_EOK || r != DNSSEC_NOT_FOUND) {
return r;
}
return dnssec_kasp_policy_save(kasp, policy);
}
static int create_default_policy(dnssec_kasp_t *kasp)
{
dnssec_kasp_policy_t config = { 0 };
dnssec_kasp_policy_defaults(&config);
config.name = DEFAULT_POLICY;
config.keystore = DEFAULT_KEYSTORE;
return create_policy(kasp, &config);
}
static int create_manual_policy(dnssec_kasp_t *kasp)
{
dnssec_kasp_policy_t config = { 0 };
dnssec_kasp_policy_defaults(&config);
config.name = MANUAL_POLICY;
config.keystore = DEFAULT_KEYSTORE;
config.manual = true;
return create_policy(kasp, &config);
}
static int create_manual_policy_lazy(dnssec_kasp_t *kasp, bool *created)
{
if (*created) {
return DNSSEC_EOK;
}
*created = true;
return create_manual_policy(kasp);
}
/*!
* Walk through existing policies, (a) add reference to default key store
* if missing, and (b) add default policy if missing.
*/
static bool update_policies(dnssec_kasp_t *kasp)
{
_cleanup_list_ dnssec_list_t *policies = NULL;
int r = dnssec_kasp_policy_list(kasp, &policies);
if (r != DNSSEC_EOK) {
error("Failed to get list of existing policies (%s).", dnssec_strerror(r));
return false;
}
dnssec_kasp_policy_t policy = { 0 };
dnssec_kasp_policy_defaults(&policy);
policy.name = DEFAULT_POLICY;
policy.keystore = DEFAULT_KEYSTORE;
bool has_default = false;
dnssec_list_foreach(i, policies) {
const char *name = dnssec_item_get(i);
if (strcmp(name, DEFAULT_POLICY) == 0) {
has_default = true;
}
_cleanup_policy_ dnssec_kasp_policy_t *policy = NULL;
r = dnssec_kasp_policy_load(kasp, name, &policy);
if (r != DNSSEC_EOK) {
error("Failed to load policy '%s' (%s).", name, dnssec_strerror(r));
return false;
}
if (policy->keystore == NULL) {
policy->keystore = strdup(DEFAULT_KEYSTORE);
}
r = dnssec_kasp_policy_save(kasp, policy);
if (r != DNSSEC_EOK) {
error("Failed to update policy '%s' (%s).", name, dnssec_strerror(r));
return false;
}
}
if (!has_default) {
r = create_default_policy(kasp);
if (r != DNSSEC_EOK) {
error("Failed to add default policy (%s).", dnssec_strerror(r));
return false;
}
}
r = dnssec_kasp_policy_save(kasp, &policy);
return true;
}
/*!
* Walk through existing zones and adds a default zone with manual signing
* enabled, if there is a zone with unassigned policy.
*/
static bool update_zones(dnssec_kasp_t *kasp)
{
_cleanup_list_ dnssec_list_t *zones = NULL;
int r = dnssec_kasp_zone_list(kasp, &zones);
if (r != DNSSEC_EOK) {
error("Failed to save the default policy configuration (%s).",
dnssec_strerror(r));
error("Failed to get list of existing zones (%s).", dnssec_strerror(r));
return false;
}
bool manual_ready = false;
dnssec_list_foreach(i, zones) {
const char *name = dnssec_item_get(i);
_cleanup_zone_ dnssec_kasp_zone_t *zone = NULL;
int r = dnssec_kasp_zone_load(kasp, name, &zone);
if (r != DNSSEC_EOK) {
error("Failed to load zone '%s' (%s).", name, dnssec_strerror(r));
return false;
}
if (dnssec_kasp_zone_get_policy(zone) == NULL) {
r = create_manual_policy_lazy(kasp, &manual_ready);
if (r != DNSSEC_EOK) {
error("Failed to create policy for manual signing (%s)", MANUAL_POLICY);
return false;
}
r = dnssec_kasp_zone_set_policy(zone, MANUAL_POLICY);
if (r != DNSSEC_EOK) {
error("Failed to assign policy '%s' to zone '%s' (%s).",
name, MANUAL_POLICY, dnssec_strerror(r));
return false;
}
}
r = dnssec_kasp_zone_save(kasp, zone);
if (r != DNSSEC_EOK) {
error("Failed to save zone '%s' (%s).", name, dnssec_strerror(r));
return false;
}
}
return true;
}
......@@ -436,7 +545,21 @@ static int cmd_init(int argc, char *argv[])
return 1;
}
return (init_default_keystore(kasp) && init_default_policy(kasp)) ? 0 : 1;
int r = create_default_keystore(kasp);
if (r != DNSSEC_EOK) {
error("Failed to initialize default key store (%s).", dnssec_strerror(r));
return 1;
}
if (!update_policies(kasp)) {
return 1;
}
if (!update_zones(kasp)) {
return 1;
}
return 0;
}
/*
......
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