diff --git a/Documentation/Getting-Started/Building-MaxScale-from-Source-Code.md b/Documentation/Getting-Started/Building-MaxScale-from-Source-Code.md index 787c6b69e..71e1edc2b 100644 --- a/Documentation/Getting-Started/Building-MaxScale-from-Source-Code.md +++ b/Documentation/Getting-Started/Building-MaxScale-from-Source-Code.md @@ -11,6 +11,7 @@ requirements are as follows: * Bison 2.7 or later * Flex 2.5.35 or later * libuuid +* libmicrohttpd ## Required packages @@ -30,7 +31,8 @@ You can install the packages with the following commands. ``` sudo yum install git gcc gcc-c++ ncurses-devel bison flex glibc-devel cmake \ libgcc perl make libtool openssl openssl-devel libcurl-devel pcre-devel \ - tcl tcl-devel systemtap-sdt-devel libuuid libuuid-devel sqlite3 sqlite3-devel + tcl tcl-devel systemtap-sdt-devel libuuid libuuid-devel sqlite3 sqlite3-devel \ + libmicrohttpd-devel ``` ### Required packages on Ubuntu and Debian systems @@ -40,7 +42,7 @@ require other packages in addition to these. ``` git build-essential libssl-dev ncurses-dev bison flex cmake perl libtool \ -libcurl4-openssl-dev libpcre3-dev tlc tcl-dev uuid uuid-dev sqlite3-dev +libcurl4-openssl-dev libpcre3-dev tlc tcl-dev uuid uuid-dev sqlite3-dev libmicrohttpd-dev ``` You can install the packages with the following command. @@ -48,7 +50,7 @@ You can install the packages with the following command. ``` sudo apt-get install git build-essential libssl-dev ncurses-dev bison flex \ cmake perl libtool libcurl4-openssl-dev libpcre3-dev tcl tcl-dev uuid \ - uuid-dev libsqlite3-dev + uuid-dev libsqlite3-dev libmicrohttpd-dev ``` ## Preparing the MariaDB MaxScale build diff --git a/Documentation/Getting-Started/Configuration-Guide.md b/Documentation/Getting-Started/Configuration-Guide.md index 4d86b0eee..feba31959 100644 --- a/Documentation/Getting-Started/Configuration-Guide.md +++ b/Documentation/Getting-Started/Configuration-Guide.md @@ -172,6 +172,29 @@ write or modify the data in the backend server. The default is 2 seconds. auth_write_timeout=10 ``` +#### `admin_port` + +The port where the HTTP admin interface listens on. The default value is port +8080. + +#### `admin_auth` + +Enable HTTP admin interface authentication using HTTP Basic Access +authentication. This is not a secure method of authentication but it does add a +small layer of security. This option id disabled by default. + +#### `admin_user` + +The HTTP admin interface username. This is the username which is used when +_admin_auth_ is enabled. The default user for the HTTP admin interface is +`admin`. + +#### `admin_password` + +The HTTP admin interface password. This is the which which is used when +_admin_auth_ is enabled. The default password for the HTTP admin interface is +`mariadb`. + #### `ms_timestamp` Enable or disable the high precision timestamps in logfiles. Enabling this adds diff --git a/include/maxscale/adminusers.h.in b/include/maxscale/adminusers.h.in index a9540db30..89de638d3 100644 --- a/include/maxscale/adminusers.h.in +++ b/include/maxscale/adminusers.h.in @@ -30,6 +30,9 @@ MXS_BEGIN_DECLS /** Default user for the administrative interface */ #define DEFAULT_ADMIN_USER "@DEFAULT_ADMIN_USER@" +static const char INET_DEFAULT_USERNAME[] = "admin"; +static const char INET_DEFAULT_PASSWORD[] = "mariadb"; + /* * MySQL session specific data * diff --git a/include/maxscale/config.h b/include/maxscale/config.h index 49c15c4e7..cbf02cc90 100644 --- a/include/maxscale/config.h +++ b/include/maxscale/config.h @@ -26,7 +26,12 @@ MXS_BEGIN_DECLS +/** Default port where the REST API listens */ +#define DEFAULT_ADMIN_HTTP_PORT 8080 + #define _RELEASE_STR_LENGTH 256 /**< release len */ +#define MAX_ADMIN_USER_LEN 1024 +#define MAX_ADMIN_PW_LEN 1024 /** * The config parameter @@ -74,6 +79,10 @@ typedef struct bool skip_permission_checks; /**< Skip service and monitor permission checks */ char qc_name[PATH_MAX]; /**< The name of the query classifier to load */ char* qc_args; /**< Arguments for the query classifier */ + char admin_user[MAX_ADMIN_USER_LEN]; /**< Admin interface user */ + char admin_password[MAX_ADMIN_PW_LEN]; /**< Admin interface password */ + uint16_t admin_port; /**< Admin interface port */ + bool admin_auth; /**< Admin interface authentication */ } MXS_CONFIG; /** diff --git a/server/core/admin.cc b/server/core/admin.cc index 3647afd34..96c38cfb5 100644 --- a/server/core/admin.cc +++ b/server/core/admin.cc @@ -21,15 +21,12 @@ #include #include #include +#include +#include #include "maxscale/admin.hh" -#include "maxscale/hk_heartbeat.h" #include "maxscale/resource.hh" -#define DEFAULT_ADMIN_HOST "127.0.0.1" -#define DEFAULT_ADMIN_PORT 8080 -#define DEFAULT_ADMIN_AUTH HTTP_AUTH_NONE - static struct MHD_Daemon* http_daemon = NULL; int handle_client(void *cls, @@ -42,6 +39,26 @@ int handle_client(void *cls, void **con_cls) { + const char *admin_user = config_get_global_options()->admin_user; + const char *admin_pw = config_get_global_options()->admin_password; + bool admin_auth = config_get_global_options()->admin_auth; + + char* pw = NULL; + char* user = MHD_basic_auth_get_username_password(connection, &pw); + + if (admin_auth && (!user || !pw || strcmp(user, admin_user) || strcmp(pw, admin_pw))) + { + static char error_resp[] = "Access denied\r\n"; + struct MHD_Response *resp; + + resp = MHD_create_response_from_buffer(sizeof (error_resp) - 1, error_resp, + MHD_RESPMEM_PERSISTENT); + + MHD_queue_basic_auth_fail_response(connection, "maxscale", resp); + MHD_destroy_response(resp); + return MHD_YES; + } + string verb(method); json_t* json = NULL; @@ -77,8 +94,10 @@ int handle_client(void *cls, bool mxs_admin_init() { http_daemon = MHD_start_daemon(MHD_USE_EPOLL_INTERNALLY | MHD_USE_DUAL_STACK, - DEFAULT_ADMIN_PORT, NULL, NULL, - handle_client, NULL, MHD_OPTION_END); + config_get_global_options()->admin_port, + NULL, NULL, + handle_client, NULL, + MHD_OPTION_END); return http_daemon != NULL; } diff --git a/server/core/adminusers.cc b/server/core/adminusers.cc index fc2a8f4e1..fbc7c49b1 100644 --- a/server/core/adminusers.cc +++ b/server/core/adminusers.cc @@ -62,9 +62,6 @@ static const int LINELEN = 80; static const char LINUX_USERS_FILE_NAME[] = "maxadmin-users"; static const char INET_USERS_FILE_NAME[] = "passwd"; -static const char INET_DEFAULT_USERNAME[] = "admin"; -static const char INET_DEFAULT_PASSWORD[] = "mariadb"; - /** * Admin Users initialisation */ diff --git a/server/core/config.cc b/server/core/config.cc index 357023b54..b1ed9add9 100644 --- a/server/core/config.cc +++ b/server/core/config.cc @@ -59,6 +59,7 @@ #include #include +#include #include #include #include @@ -1458,6 +1459,22 @@ handle_global_item(const char *name, const char *value) MXS_FREE(v); } } + else if (strcmp(name, "admin_user") == 0) + { + strcpy(gateway.admin_user, value); + } + else if (strcmp(name, "admin_password") == 0) + { + strcpy(gateway.admin_password, value); + } + else if (strcmp(name, "admin_port") == 0) + { + gateway.admin_port = atoi(value); + } + else if (strcmp(name, "admin_auth") == 0) + { + gateway.admin_auth = config_truth_value(value); + } else { for (i = 0; lognames[i].name; i++) @@ -1678,6 +1695,11 @@ global_defaults() gateway.auth_read_timeout = DEFAULT_AUTH_READ_TIMEOUT; gateway.auth_write_timeout = DEFAULT_AUTH_WRITE_TIMEOUT; gateway.skip_permission_checks = false; + gateway.admin_port = DEFAULT_ADMIN_HTTP_PORT; + gateway.admin_auth = false; + strcpy(gateway.admin_user, INET_DEFAULT_USERNAME); + strcpy(gateway.admin_password, INET_DEFAULT_PASSWORD); + if (version_string != NULL) { gateway.version_string = MXS_STRDUP_A(version_string);