MEDIUM: cli/ssl: configure ssl on server at runtime
in the context of a progressive backend migration, we want to be able to
activate SSL on outgoing connections to the server at runtime without
reloading.
This patch adds a `set server ssl` command; in order to allow that:
- add `srv_use_ssl` to `show servers state` command for compatibility,
also update associated parsing
- when using default-server ssl setting, and `no-ssl` on server line,
init SSL ctx without activating it
- when triggering ssl API, de/activate SSL connections as requested
- clean ongoing connections as it is done for addr/port changes, without
checking prior server state
example config:
backend be_foo
default-server ssl
server srv0 127.0.0.1:6011 weight 1 no-ssl
show servers state:
5 be_foo 1 srv0 127.0.0.1 2 0 1 1 15 1 0 4 0 0 0 0 - 6011 - -1
where srv0 can switch to ssl later during the runtime:
set server be_foo/srv0 ssl on
5 be_foo 1 srv0 127.0.0.1 2 0 1 1 15 1 0 4 0 0 0 0 - 6011 - 1
Also update existing tests and create a new one.
Signed-off-by: William Dauchy <wdauchy@gmail.com>
diff --git a/src/server.c b/src/server.c
index d72e7e0..3a3ccc6 100644
--- a/src/server.c
+++ b/src/server.c
@@ -38,6 +38,7 @@
#include <haproxy/queue.h>
#include <haproxy/sample.h>
#include <haproxy/server.h>
+#include <haproxy/ssl_sock.h>
#include <haproxy/stats-t.h>
#include <haproxy/stream.h>
#include <haproxy/stream_interface.h>
@@ -2579,6 +2580,9 @@
const char *port_str;
unsigned int port;
char *srvrecord;
+#ifdef USE_OPENSSL
+ int use_ssl;
+#endif
fqdn = NULL;
port = 0;
@@ -2603,6 +2607,7 @@
* srv_fqdn: params[13]
* srv_port: params[14]
* srvrecord: params[15]
+ * srv_use_ssl: params[16]
*/
/* validating srv_op_state */
@@ -2742,6 +2747,10 @@
if (srvrecord && *srvrecord != '_')
srvrecord = NULL;
+#ifdef USE_OPENSSL
+ use_ssl = strtol(params[16], &p, 10);
+#endif
+
/* don't apply anything if one error has been detected */
if (msg->data)
goto out;
@@ -2941,6 +2950,13 @@
if (port_str)
srv->svc_port = port;
+
+#ifdef USE_OPENSSL
+ /* configure ssl if connection has been initated at startup */
+ if (srv->ssl_ctx.ctx != NULL)
+ ssl_sock_set_srv(srv, use_ssl);
+#endif
+
HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
break;
@@ -4396,10 +4412,29 @@
if (warning)
cli_msg(appctx, LOG_WARNING, warning);
}
- else {
+ else if (strcmp(args[3], "ssl") == 0) {
+#ifdef USE_OPENSSL
+ if (sv->ssl_ctx.ctx == NULL) {
+ cli_err(appctx, "'set server <srv> ssl' cannot be set. "
+ " default-server should define ssl settings\n");
+ goto out_unlock;
+ } else if (strcmp(args[4], "on") == 0) {
+ ssl_sock_set_srv(sv, 1);
+ } else if (strcmp(args[4], "off") == 0) {
+ ssl_sock_set_srv(sv, 0);
+ } else {
+ cli_err(appctx, "'set server <srv> ssl' expects 'on' or 'off'.\n");
+ goto out_unlock;
+ }
+ srv_cleanup_connections(sv);
+ cli_msg(appctx, LOG_NOTICE, "server ssl setting updated.\n");
+#else
+ cli_msg(appctx, LOG_NOTICE, "server ssl setting not supported.\n");
+#endif
+ } else {
cli_err(appctx,
"'set server <srv>' only supports 'agent', 'health', 'state',"
- " 'weight', 'addr', 'fqdn' and 'check-port'.\n");
+ " 'weight', 'addr', 'fqdn', 'check-port' and 'ssl'.\n");
}
out_unlock:
HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
@@ -4633,7 +4668,7 @@
{ { "enable", "health", NULL }, "enable health : enable health checks (use 'set server' instead)", cli_parse_enable_health, NULL },
{ { "enable", "server", NULL }, "enable server : enable a disabled server (use 'set server' instead)", cli_parse_enable_server, NULL },
{ { "set", "maxconn", "server", NULL }, "set maxconn server : change a server's maxconn setting", cli_parse_set_maxconn_server, NULL },
- { { "set", "server", NULL }, "set server : change a server's state, weight or address", cli_parse_set_server },
+ { { "set", "server", NULL }, "set server : change a server's state, weight, address or ssl", cli_parse_set_server },
{ { "get", "weight", NULL }, "get weight : report a server's current weight", cli_parse_get_weight },
{ { "set", "weight", NULL }, "set weight : change a server's weight (deprecated)", cli_parse_set_weight },