Add custom cache directory for MySQLAuth

The MySQLAuth authenticator can now store the cached credentials in a
custom location. This is intended for the binlogrouter, which currently
uses a different location for the user cache.

The MySQL authentication modules now have their own document in the
Authenticators directory. Right now this document only describes the
general details of the MySQL authentication and the new option.
This commit is contained in:
Markus Makela
2016-10-18 10:40:06 +03:00
parent 21094fb0cb
commit d938f0e72f
2 changed files with 109 additions and 9 deletions

View File

@ -0,0 +1,34 @@
# MySQL Authenticator
The _MySQLAuth_ and _MySQLBackendAuth_ modules implement the client and
backend authentication for the MySQL native password authentication. This
is the default authentication plugin used by both MariaDB and MySQL.
These modules are the default authenticators for all MySQL connections and
needs no further configuration to work.
## Authenticator options
The client authentication module, _MySQLAuth_, supports authenticator options.
### `cache_dir`
The location where the user credential cache is stored. The default value
for this is `<cache dir>/<service name>/<listener name>/cache/` where
`<cache dir>` by default is `/var/cache`.
Each listener has its own user cache where the user credential information
queried from the backends is stored. This information is used to
authenticate users if a connection to the backend servers can't be made.
#### Example configuration
```
[Read-Write Listener]
type=listener
service=Read-Write Service
protocol=MySQLClient
port=4006
authenticator=MySQLAuth
authenticator_options=cache_dir=/tmp
```

View File

@ -35,6 +35,12 @@
#include <maxscale/secrets.h>
#include <maxscale/utils.h>
typedef struct mysql_auth
{
char *cache_dir; /**< Custom cache directory location */
} MYSQL_AUTH;
/* @see function load_module in load_utils.c for explanation of the following
* lint directives.
*/
@ -50,6 +56,7 @@ MODULE_INFO info =
static char *version_str = "V1.1.0";
static void* mysql_auth_init(char **options);
static int mysql_auth_set_protocol_data(DCB *dcb, GWBUF *buf);
static bool mysql_auth_is_client_ssl_capable(DCB *dcb);
static int mysql_auth_authenticate(DCB *dcb);
@ -61,7 +68,7 @@ static int mysql_auth_load_users(SERV_LISTENER *port);
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* No initialize entry point */
mysql_auth_init, /* Initialize the authenticator */
NULL, /* No create entry point */
mysql_auth_set_protocol_data, /* Extract data into structure */
mysql_auth_is_client_ssl_capable, /* Check if client supports SSL */
@ -121,6 +128,60 @@ GWAUTHENTICATOR* GetModuleObject()
}
/*lint +e14 */
/**
* @brief Initialize the authenticator instance
*
* @param options Authenticator options
* @return New MYSQL_AUTH instance or NULL on error
*/
static void* mysql_auth_init(char **options)
{
MYSQL_AUTH *instance = MXS_MALLOC(sizeof(*instance));
if (instance)
{
bool error = false;
instance->cache_dir = NULL;
for (int i = 0; options[i]; i++)
{
char *value = strchr(options[i], '=');
if (value)
{
*value++ = '\0';
if (strcmp(options[i], "cache_dir") == 0)
{
if ((instance->cache_dir = MXS_STRDUP(value)) == NULL)
{
error = true;
}
}
else
{
MXS_ERROR("Unknown authenticator option: %s", options[i]);
error = true;
}
}
else
{
MXS_ERROR("Unknown authenticator option: %s", options[i]);
error = true;
}
}
if (error)
{
MXS_FREE(instance->cache_dir);
MXS_FREE(instance);
instance = NULL;
}
}
return instance;
}
/**
* @brief Authenticates a MySQL user who is a client to MaxScale.
*
@ -781,21 +842,29 @@ static int mysql_auth_load_users(SERV_LISTENER *port)
{
int rc = MXS_AUTH_LOADUSERS_OK;
SERVICE *service = port->listener->service;
MYSQL_AUTH *instance = (MYSQL_AUTH*)port->auth_instance;
int loaded = replace_mysql_users(port);
char path[PATH_MAX];
if (instance->cache_dir)
{
strcpy(path, instance->cache_dir);
}
else
{
sprintf(path, "%s/%s/%s/%s/", get_cachedir(), service->name, port->name, DBUSERS_DIR);
}
if (loaded < 0)
{
MXS_ERROR("[%s] Unable to load users for listener %s listening at %s:%d.", service->name,
port->name, port->address ? port->address : "0.0.0.0", port->port);
/* Try loading authentication data from file cache */
char path[PATH_MAX];
sprintf(path, "%s/%s/%s/%s/%s", get_cachedir(), service->name, port->name,
DBUSERS_DIR, DBUSERS_FILE);
strcat(path, DBUSERS_FILE);
if ((loaded = dbusers_load(port->users, path)) == -1)
{
MXS_ERROR("[%s] Failed to load cached users from '%s'.", service->name, path);;
MXS_ERROR("[%s] Failed to load cached users from '%s'.", service->name, path);
rc = MXS_AUTH_LOADUSERS_ERROR;
}
else
@ -806,9 +875,6 @@ static int mysql_auth_load_users(SERV_LISTENER *port)
else
{
/* Users loaded successfully, save authentication data to file cache */
char path[PATH_MAX];
sprintf(path, "%s/%s/%s/%s/", get_cachedir(), service->name, port->name, DBUSERS_DIR);
if (mxs_mkdir_all(path, 0777))
{
strcat(path, DBUSERS_FILE);