diff --git a/include/maxscale/config_runtime.h b/include/maxscale/config_runtime.h index 775902eeb..db8674493 100644 --- a/include/maxscale/config_runtime.h +++ b/include/maxscale/config_runtime.h @@ -79,3 +79,30 @@ bool runtime_link_server(SERVER *server, const char *target); * if no object matching @c target was found */ bool runtime_unlink_server(SERVER *server, const char *target); + +/** + * @brief Alter server parameters + * + * @param server Server to alter + * @param key Key to modify + * @param value New value + * @return True if @c key was one of the supported parameters + */ +bool runtime_alter_server(SERVER *server, char *key, char *value); + +/** + * @brief Enable SSL for a server + * + * The @c key , @c cert and @c ca parameters are required. @c version and @c depth + * are optional. + * + * @param server Server to configure + * @param key Path to SSL private key + * @param cert Path to SSL public certificate + * @param ca Path to certificate authority + * @param version Required SSL Version + * @param depth Certificate verification depth + * @return True if SSL was successfully enabled + */ +bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert, + const char *ca, const char *version, const char *depth); diff --git a/server/core/config_runtime.c b/server/core/config_runtime.c index 05760e113..2fa5fabc0 100644 --- a/server/core/config_runtime.c +++ b/server/core/config_runtime.c @@ -11,6 +11,7 @@ * Public License. */ +#include #include #include #include @@ -188,3 +189,72 @@ bool runtime_destroy_server(SERVER *server) spinlock_release(&crt_lock); return rval; } + +bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert, + const char *ca, const char *version, const char *depth) +{ + spinlock_acquire(&crt_lock); + bool rval = false; + + if (key && cert && ca) + { + CONFIG_CONTEXT *obj = config_context_create(server->unique_name); + + if (obj && config_add_param(obj, "ssl_key", key) && + config_add_param(obj, "ssl_cert", cert) && + config_add_param(obj, "ssl_ca_cert", ca) && + (!version || config_add_param(obj, "ssl_version", version)) && + (!depth || config_add_param(obj, "ssl_cert_verify_depth", depth))) + { + int err = 0; + SSL_LISTENER *ssl = make_ssl_structure(obj, true, &err); + + if (err == 0 && ssl && listener_init_SSL(ssl) == 0) + { + /** Sync to prevent reads on partially initialized server_ssl */ + atomic_synchronize(); + + server->server_ssl = ssl; + if (server_serialize(server)) + { + rval = true; + } + } + } + + config_context_free(obj); + } + + spinlock_release(&crt_lock); + return rval; +} + +bool runtime_alter_server(SERVER *server, char *key, char *value) +{ + spinlock_acquire(&crt_lock); + bool valid = true; + + if (strcmp(key, "address") == 0) + { + server_update_address(server, value); + } + else if (strcmp(key, "port") == 0) + { + server_update_port(server, atoi(value)); + } + else if (strcmp(key, "monuser") == 0) + { + server_update_credentials(server, value, server->monpw); + } + else if (strcmp(key, "monpw") == 0) + { + server_update_credentials(server, server->monuser, value); + } + else + { + valid = false; + } + + spinlock_release(&crt_lock); + return valid; +} diff --git a/server/modules/routing/debugcli/debugcmd.c b/server/modules/routing/debugcli/debugcmd.c index 24e272398..2f215733c 100644 --- a/server/modules/routing/debugcli/debugcmd.c +++ b/server/modules/routing/debugcli/debugcmd.c @@ -1080,71 +1080,6 @@ struct subcommand destroyoptions[] = } }; -static bool handle_alter_server(SERVER *server, char *key, char *value) -{ - bool valid = true; - - if (strcmp(key, "address") == 0) - { - server_update_address(server, value); - } - else if (strcmp(key, "port") == 0) - { - server_update_port(server, atoi(value)); - } - else if (strcmp(key, "monuser") == 0) - { - server_update_credentials(server, value, server->monpw); - } - else if (strcmp(key, "monpw") == 0) - { - server_update_credentials(server, server->monuser, value); - } - else - { - valid = false; - } - - return valid; -} - -void handle_server_ssl(DCB *dcb, SERVER *server, CONFIG_CONTEXT *obj) -{ - if (config_have_required_ssl_params(obj)) - { - int err = 0; - SSL_LISTENER *ssl = make_ssl_structure(obj, true, &err); - - if (err == 0 && ssl && listener_init_SSL(ssl) == 0) - { - /** Sync to prevent reads on partially initialized server_ssl */ - atomic_synchronize(); - - server->server_ssl = ssl; - if (server_serialize(server)) - { - dcb_printf(dcb, "SSL enabled for server '%s'\n", server->unique_name); - } - else - { - dcb_printf(dcb, "SSL enabled for server '%s' but persisting " - "it to disk failed, see log for more details.\n", - server->unique_name); - } - } - else - { - dcb_printf(dcb, "Enabling SSL for server '%s' failed, see log " - "for more details.\n", server->unique_name); - } - } - else - { - dcb_printf(dcb, "Error: SSL configuration requires the following parameters:\n" - "ssl=required ssl_key=PATH ssl_cert=PATH ssl_ca_cert=PATH\n"); - } -} - /** * @brief Process multiple alter operations at once * @@ -1159,6 +1094,12 @@ static void alterServer(DCB *dcb, SERVER *server, char *v1, char *v2, char *v3, char *values[11] = {v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11}; const int items = sizeof(values) / sizeof(values[0]); CONFIG_CONTEXT *obj = NULL; + char *ssl_key = NULL; + char *ssl_cert = NULL; + char *ssl_ca = NULL; + char *ssl_version = NULL; + char *ssl_depth = NULL; + bool enable = false; for (int i = 0; i < items && values[i]; i++) { @@ -1171,19 +1112,33 @@ static void alterServer(DCB *dcb, SERVER *server, char *v1, char *v2, char *v3, if (config_is_ssl_parameter(key)) { - /** - * All the required SSL parameters must be defined at once to - * enable SSL for created servers. This removes the problem - * of partial configuration and allows a somewhat atomic - * operation. - */ - if ((obj == NULL && (obj = config_context_create(server->unique_name)) == NULL) || - (!config_add_param(obj, key, value))) + if (strcmp("ssl_cert", key) == 0) { - dcb_printf(dcb, "Internal error, see log for more details\n"); + ssl_cert = value; + } + else if (strcmp("ssl_ca_cert", key) == 0) + { + ssl_ca = value; + } + else if (strcmp("ssl_key", key) == 0) + { + ssl_key = value; + } + else if (strcmp("ssl_version", key) == 0) + { + ssl_version = value; + } + else if (strcmp("ssl_cert_verify_depth", key) == 0) + { + ssl_depth = value; + } + else + { + enable = strcmp("ssl", key) == 0 && strcmp(value, "required") == 0; + /** Must be 'ssl' */ } } - else if (!handle_alter_server(server, key, value)) + else if (!runtime_alter_server(server, key, value)) { dcb_printf(dcb, "Error: Bad key-value parameter: %s=%s\n", key, value); } @@ -1194,11 +1149,23 @@ static void alterServer(DCB *dcb, SERVER *server, char *v1, char *v2, char *v3, } } - if (obj) + if (enable || ssl_key || ssl_cert || ssl_ca) { - /** We have SSL parameters, try to process them */ - handle_server_ssl(dcb, server, obj); - config_context_free(obj); + if (enable && ssl_key && ssl_cert && ssl_ca) + { + /** We have SSL parameters, try to process them */ + if (!runtime_enable_server_ssl(server, ssl_key, ssl_cert, ssl_ca, + ssl_version, ssl_depth)) + { + dcb_printf(dcb, "Enabling SSL for server '%s' failed, see log " + "for more details.\n", server->unique_name); + } + } + else + { + dcb_printf(dcb, "Error: SSL configuration requires the following parameters:\n" + "ssl=required ssl_key=PATH ssl_cert=PATH ssl_ca_cert=PATH\n"); + } } }