MXS-1220: Add HTTPS support
The REST API now supports encryption. The user needs to configure certificates for the REST API before encryption is used.
This commit is contained in:
@ -18,7 +18,9 @@
|
||||
|
||||
#include <climits>
|
||||
#include <new>
|
||||
#include <fstream>
|
||||
#include <microhttpd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
@ -29,14 +31,23 @@
|
||||
#include <maxscale/utils.h>
|
||||
#include <maxscale/config.h>
|
||||
#include <maxscale/hk_heartbeat.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "maxscale/resource.hh"
|
||||
#include "maxscale/http.hh"
|
||||
|
||||
using std::string;
|
||||
using std::ifstream;
|
||||
|
||||
static struct MHD_Daemon* http_daemon = NULL;
|
||||
|
||||
/** In-memory certificates in PEM format */
|
||||
static char* admin_ssl_key = NULL;
|
||||
static char* admin_ssl_cert = NULL;
|
||||
static char* admin_ssl_ca_cert = NULL;
|
||||
|
||||
static bool using_ssl = false;
|
||||
|
||||
int kv_iter(void *cls,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
@ -221,6 +232,58 @@ static bool host_to_sockaddr(const char* host, uint16_t port, struct sockaddr_st
|
||||
return true;
|
||||
}
|
||||
|
||||
static char* load_cert(const char* file)
|
||||
{
|
||||
char* rval = NULL;
|
||||
ifstream infile(file);
|
||||
struct stat st;
|
||||
|
||||
if (stat(file, &st) == 0 &&
|
||||
(rval = new (std::nothrow) char[st.st_size + 1]))
|
||||
{
|
||||
infile.read(rval, st.st_size);
|
||||
rval[st.st_size] = '\0';
|
||||
|
||||
if (!infile.good())
|
||||
{
|
||||
MXS_ERROR("Failed to load certificate file: %s", file);
|
||||
delete rval;
|
||||
rval = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static bool load_ssl_certificates()
|
||||
{
|
||||
bool rval = false;
|
||||
const char* key = config_get_global_options()->admin_ssl_key;
|
||||
const char* cert = config_get_global_options()->admin_ssl_cert;
|
||||
const char* ca = config_get_global_options()->admin_ssl_ca_cert;
|
||||
|
||||
if (*key && *cert && *ca)
|
||||
{
|
||||
if ((admin_ssl_key = load_cert(key)) &&
|
||||
(admin_ssl_cert = load_cert(cert)) &&
|
||||
(admin_ssl_ca_cert = load_cert(ca)))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete admin_ssl_key;
|
||||
delete admin_ssl_cert;
|
||||
delete admin_ssl_ca_cert;
|
||||
admin_ssl_key = NULL;
|
||||
admin_ssl_cert = NULL;
|
||||
admin_ssl_ca_cert = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool mxs_admin_init()
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
@ -236,10 +299,20 @@ bool mxs_admin_init()
|
||||
options |= MHD_USE_DUAL_STACK;
|
||||
}
|
||||
|
||||
if (load_ssl_certificates())
|
||||
{
|
||||
using_ssl = true;
|
||||
options |= MHD_USE_SSL;
|
||||
}
|
||||
|
||||
// The port argument is ignored and the port in the struct sockaddr is used instead
|
||||
http_daemon = MHD_start_daemon(options, 0, NULL, NULL, handle_client, NULL,
|
||||
http_daemon = MHD_start_daemon(options, 0, NULL, NULL, handle_client, NULL,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, close_client, NULL,
|
||||
MHD_OPTION_SOCK_ADDR, &addr,
|
||||
!using_ssl ? MHD_OPTION_END :
|
||||
MHD_OPTION_HTTPS_MEM_KEY, admin_ssl_key,
|
||||
MHD_OPTION_HTTPS_MEM_CERT, admin_ssl_cert,
|
||||
MHD_OPTION_HTTPS_MEM_TRUST, admin_ssl_cert,
|
||||
MHD_OPTION_END);
|
||||
}
|
||||
|
||||
@ -250,3 +323,8 @@ void mxs_admin_shutdown()
|
||||
{
|
||||
MHD_stop_daemon(http_daemon);
|
||||
}
|
||||
|
||||
bool mxs_admin_https_enabled()
|
||||
{
|
||||
return using_ssl;
|
||||
}
|
||||
|
||||
@ -57,6 +57,9 @@ const char CN_ADMIN_HOST[] = "admin_host";
|
||||
const char CN_ADMIN_PASSWORD[] = "admin_password";
|
||||
const char CN_ADMIN_PORT[] = "admin_port";
|
||||
const char CN_ADMIN_USER[] = "admin_user";
|
||||
const char CN_ADMIN_SSL_KEY[] = "admin_ssl_key";
|
||||
const char CN_ADMIN_SSL_CERT[] = "admin_ssl_cert";
|
||||
const char CN_ADMIN_SSL_CA_CERT[] = "admin_ssl_ca_cert";
|
||||
const char CN_AUTHENTICATOR[] = "authenticator";
|
||||
const char CN_AUTHENTICATOR_OPTIONS[] = "authenticator_options";
|
||||
const char CN_AUTH_ALL_SERVERS[] = "auth_all_servers";
|
||||
@ -1525,6 +1528,18 @@ handle_global_item(const char *name, const char *value)
|
||||
{
|
||||
strcpy(gateway.admin_host, value);
|
||||
}
|
||||
else if (strcmp(name, CN_ADMIN_SSL_KEY) == 0)
|
||||
{
|
||||
strcpy(gateway.admin_ssl_key, value);
|
||||
}
|
||||
else if (strcmp(name, CN_ADMIN_SSL_CERT) == 0)
|
||||
{
|
||||
strcpy(gateway.admin_ssl_cert, value);
|
||||
}
|
||||
else if (strcmp(name, CN_ADMIN_SSL_CA_CERT) == 0)
|
||||
{
|
||||
strcpy(gateway.admin_ssl_ca_cert, value);
|
||||
}
|
||||
else if (strcmp(name, CN_ADMIN_AUTH) == 0)
|
||||
{
|
||||
gateway.admin_auth = config_truth_value(value);
|
||||
@ -1754,6 +1769,9 @@ global_defaults()
|
||||
strcpy(gateway.admin_host, DEFAULT_ADMIN_HOST);
|
||||
strcpy(gateway.admin_user, INET_DEFAULT_USERNAME);
|
||||
strcpy(gateway.admin_password, INET_DEFAULT_PASSWORD);
|
||||
gateway.admin_ssl_key[0] = '\0';
|
||||
gateway.admin_ssl_cert[0] = '\0';
|
||||
gateway.admin_ssl_ca_cert[0] = '\0';
|
||||
|
||||
if (version_string != NULL)
|
||||
{
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "maxscale/httprequest.hh"
|
||||
#include "maxscale/admin.hh"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
@ -98,8 +99,8 @@ HttpRequest::HttpRequest(struct MHD_Connection *connection, string url, string m
|
||||
m_connection(connection)
|
||||
{
|
||||
process_uri(url, m_resource_parts);
|
||||
// TODO: Add https support
|
||||
m_hostname = HttpRequest::HTTP_PREFIX;
|
||||
|
||||
m_hostname = mxs_admin_https_enabled() ? HttpRequest::HTTPS_PREFIX : HttpRequest::HTTP_PREFIX;
|
||||
m_hostname += get_header(HTTP_HOST_HEADER);
|
||||
}
|
||||
|
||||
|
||||
@ -68,3 +68,10 @@ bool mxs_admin_init();
|
||||
* @brief Shutdown the administrative interface
|
||||
*/
|
||||
void mxs_admin_shutdown();
|
||||
|
||||
/**
|
||||
* @brief Check if admin interface uses HTTPS protocol
|
||||
*
|
||||
* @return True if HTTPS is enabled
|
||||
*/
|
||||
bool mxs_admin_https_enabled();
|
||||
|
||||
Reference in New Issue
Block a user