Merge branch '2.2' into develop

This commit is contained in:
Johan Wikman
2018-03-12 14:38:37 +02:00
14 changed files with 267 additions and 112 deletions

View File

@ -36,7 +36,7 @@ These tutorials are for specific use cases and module combinations.
- [Administration Tutorial](Tutorials/Administration-Tutorial.md)
- [Avro Router Tutorial](Tutorials/Avrorouter-Tutorial.md)
- [Failover with Keepalived](Tutorials/Failover-with-Keepalived.md)
- [MaxScale Failover with Keepalived and MaxCtrl](Tutorials/MaxScale-Failover-with-Keepalived-and-MaxCtrl.md)
- [Filter Tutorial](Tutorials/Filter-Tutorial.md)
- [Galera Cluster Connection Routing Tutorial](Tutorials/Galera-Cluster-Connection-Routing-Tutorial.md)
- [Galera Gluster Read Write Splitting Tutorial](Tutorials/Galera-Cluster-Read-Write-Splitting-Tutorial.md)

View File

@ -21,6 +21,7 @@ plugin modules that tailor the behavior of the program.
* [Diagnostic Modules](#diagnostic-modules)
* [Monitor Modules](#monitor-modules)
* [Filter Modules](#filter-modules)
* [Encrypting Passwords](#encrypting-passwords)
* [Reloading Configuration](#reloading-configuration)
* [Authentication](#authentication)
* [Error Reporting](#error-reporting)
@ -887,9 +888,6 @@ In versions of MySQL 5.7.6 and later, the `Password` column was replaced by
`authentication_string`. Change `user.password` above with
`user.authentication_string`.
**Note**: If authentication fails, MaxScale will try to refresh the list of
database users used by the service up to 4 times every 30 seconds.
<a id="passwd"></a>
#### `password`
@ -1524,6 +1522,49 @@ can add a filter to a service and combine multiple filters in one service.
* [Query Redirection Filter](../Filters/Named-Server-Filter.md)
* [RabbitMQ Filter](../Filters/RabbitMQ-Filter.md)
## Encrypting Passwords
Passwords stored in the maxscale.cnf file may optionally be encrypted for added security.
This is done by creation of an encryption key on installation of MariaDB MaxScale.
Encryption keys may be created manually by executing the maxkeys utility with the argument
of the filename to store the key. The default location MariaDB MaxScale stores
the keys is `/var/lib/maxscale`.
```
# Usage: maxkeys [PATH]
maxkeys /var/lib/maxscale/
```
Changing the encryption key for MariaDB MaxScale will invalidate any currently
encrypted keys stored in the maxscale.cnf file.
## Creating Encrypted Passwords
Encrypted passwords are created by executing the maxpasswd command with the location
of the .secrets file and the password you require to encrypt as an argument.
```
# Usage: maxpasswd PATH PASSWORD
maxpasswd /var/lib/maxscale/ MaxScalePw001
61DD955512C39A4A8BC4BB1E5F116705
```
The output of the maxpasswd command is a hexadecimal string, this should be inserted
into the maxscale.cnf file in place of the ordinary, plain text, password.
MariaDB MaxScale will determine this as an encrypted password and automatically decrypt
it before sending it the database server.
```
[Split Service]
type=service
router=readwritesplit
servers=server1,server2,server3,server4
user=maxscale
password=61DD955512C39A4A8BC4BB1E5F116705
```
## Reloading Configuration
**Note:** This functionality has been deprecated. Use the MaxScale REST API or the

View File

@ -174,44 +174,9 @@ that discusses the concept and gives some examples of ways to use filters.
## Encrypting Passwords
Passwords stored in the maxscale.cnf file may optionally be encrypted for added security.
This is done by creation of an encryption key on installation of MariaDB MaxScale.
Encryption keys may be created manually by executing the maxkeys utility with the argument
of the filename to store the key. The default location MariaDB MaxScale stores
the keys is `/var/lib/maxscale`.
```
# Usage: maxkeys [PATH]
maxkeys /var/lib/maxscale/
```
Changing the encryption key for MariaDB MaxScale will invalidate any currently
encrypted keys stored in the maxscale.cnf file.
### Creating Encrypted Passwords
Encrypted passwords are created by executing the maxpasswd command with the location
of the .secrets file and the password you require to encrypt as an argument.
```
# Usage: maxpasswd PATH PASSWORD
maxpasswd /var/lib/maxscale/ MaxScalePw001
61DD955512C39A4A8BC4BB1E5F116705
```
The output of the maxpasswd command is a hexadecimal string, this should be inserted
into the maxscale.cnf file in place of the ordinary, plain text, password.
MariaDB MaxScale will determine this as an encrypted password and automatically decrypt
it before sending it the database server.
```
[Split Service]
type=service
router=readwritesplit
servers=server1,server2,server3,server4
user=maxscale
password=61DD955512C39A4A8BC4BB1E5F116705
```
Read the [Encrypting Passwords](Configuration-Guide.md#encrypting-passwords)
section of the configuration guide to set up password encryption for the
configuration file.
## Running MariaDB MaxScale

View File

@ -120,9 +120,8 @@ service=Galera Service
```
A listener must also define the protocol module it will use for the incoming
network protocol, currently this should be the MariaDBClient protocol for all
database listeners. The listener may then supply a network port to listen on
and/or a socket within the file system.
network protocol, currently this must be the `MariaDBClient` protocol for all
database listeners. The listener must also supply the network port to listen on.
```
[Galera Listener]
@ -130,7 +129,6 @@ type=listener
service=Galera Service
protocol=MariaDBClient
port=4306
socket=/tmp/DB.Cluster
```
An address parameter may be given if the listener is required to bind to a particular

View File

@ -71,7 +71,9 @@ type=listener
service=Splitter Service
```
A listener must also define the protocol module it will use for the incoming network protocol, currently this should be the `MariaDBClient` protocol for all database listeners. The listener may then supply a network port to listen on and/or a socket within the file system.
A listener must also define the protocol module it will use for the incoming
network protocol, currently this must be the `MariaDBClient` protocol for all
database listeners. The listener must also supply the network port to listen on.
```
[Splitter Listener]
@ -79,7 +81,6 @@ type=listener
service=Splitter Service
protocol=MariaDBClient
port=3306
socket=/tmp/ClusterMaster
```
An address parameter may be given if the listener is required to bind to a particular network address when using hosts with multiple network addresses. The default behavior is to listen on all network interfaces.

View File

@ -106,7 +106,9 @@ type=listener
service=Read-Service
```
A listener must also define the protocol module it will use for the incoming network protocol, currently this should be the MariaDBClient protocol for all database listeners. The listener may then supply a network port to listen on and/or a socket within the file system.
A listener must also define the protocol module it will use for the incoming
network protocol, currently this must be the `MariaDBClient` protocol for all
database listeners. The listener must also supply the network port to listen on.
```
[Write-Listener]
@ -114,7 +116,6 @@ type=listener
service=Write-Service
protocol=MariaDBClient
port=4306
socket=/tmp/ClusterMaster
[Read-Listener]
type=listener

View File

@ -106,9 +106,8 @@ service=Splitter Service
```
A listener must also define the protocol module it will use for the incoming
network protocol, currently this should be the `MariaDBClient` protocol for all
database listeners. The listener may then supply a network port to listen on
and/or a socket within the file system.
network protocol, currently this must be the `MariaDBClient` protocol for all
database listeners. The listener must also supply the network port to listen on.
```
[Splitter Listener]
@ -116,7 +115,6 @@ type=listener
service=Splitter Service
protocol=MariaDBClient
port=3306
socket=/tmp/ClusterMaster
```
An address parameter may be given if the listener is required to bind to a

View File

@ -5,7 +5,7 @@
set(MAXSCALE_VERSION_MAJOR "2" CACHE STRING "Major version")
set(MAXSCALE_VERSION_MINOR "1" CACHE STRING "Minor version")
set(MAXSCALE_VERSION_PATCH "14" CACHE STRING "Patch version")
set(MAXSCALE_VERSION_PATCH "15" CACHE STRING "Patch version")
# This should only be incremented if a package is rebuilt
set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number")

View File

@ -7,54 +7,6 @@
#include <set>
#include <string>
typedef std::set<std::string> StringSet;
// Note: This is backported from 2.2 and can be replaced with MaxScales::get_server_status once merged
StringSet state(TestConnections& test, const char* name)
{
StringSet rval;
int exit_code;
char* res = test.maxscales->ssh_node_output_f(0, true, &exit_code,
"maxadmin list servers|grep \'%s\'", name);
char* pipe = strrchr(res, '|');
if (res && pipe)
{
pipe++;
char* tok = strtok(pipe, ",");
while (tok)
{
char* p = tok;
char *end = strchr(tok, '\n');
if (!end)
{
end = strchr(tok, '\0');
}
// Trim leading whitespace
while (p < end && isspace(*p))
{
p++;
}
// Trim trailing whitespace
while (end > tok && isspace(*end))
{
*end-- = '\0';
}
rval.insert(p);
tok = strtok(NULL, ",\n");
}
}
free(res);
return rval;
}
int main(int argc, char** argv)
{
TestConnections test(argc, argv);
@ -63,6 +15,7 @@ int main(int argc, char** argv)
execute_query(test.repl->nodes[3], "CHANGE MASTER TO MASTER_HOST='%s', MASTER_PORT=%d",
test.repl->IP_private[2], test.repl->port[2]);
execute_query(test.repl->nodes[3], "START SLAVE");
sleep(5);
StringSet master = {"Master", "Running"};
StringSet slave = {"Slave", "Running"};
@ -74,10 +27,10 @@ int main(int argc, char** argv)
test.tprintf("%s", output);
free(output);
test.add_result(state(test, "server1") != master, "server1 is not a master");
test.add_result(state(test, "server2") != slave, "server2 is not a slave");
test.add_result(state(test, "server3") != relay_master, "server3 is not a relay master");
test.add_result(state(test, "server4") != slave, "server4 is not a slave");
test.add_result(test.maxscales->get_server_status("server1") != master, "server1 is not a master");
test.add_result(test.maxscales->get_server_status("server2") != slave, "server2 is not a slave");
test.add_result(test.maxscales->get_server_status("server3") != relay_master, "server3 is not a relay master");
test.add_result(test.maxscales->get_server_status("server4") != slave, "server4 is not a slave");
execute_query(test.repl->nodes[2], "STOP SLAVE IO_THREAD");
sleep(10);
@ -86,10 +39,10 @@ int main(int argc, char** argv)
output = test.maxscales->ssh_node_output(0, "maxadmin list servers", true, &exit_code);
test.tprintf("%s", output);
free(output);
test.add_result(state(test, "server1") != master, "server1 is not a master");
test.add_result(state(test, "server2") != slave, "server2 is not a slave");
test.add_result(state(test, "server3") != relay_master, "server3 is not a relay master");
test.add_result(state(test, "server4") != slave, "server4 is not a slave");
test.add_result(test.maxscales->get_server_status("server1") != master, "server1 is not a master");
test.add_result(test.maxscales->get_server_status( "server2") != slave, "server2 is not a slave");
test.add_result(test.maxscales->get_server_status("server3") != relay_master, "server3 is not a relay master");
test.add_result(test.maxscales->get_server_status("server4") != slave, "server4 is not a slave");
test.repl->fix_replication();
return test.global_result;

View File

@ -90,7 +90,7 @@ int main(int argc, char *argv[])
}
Test->stop_timeout();
sleep(5);
sleep(20);
Test->check_maxscale_alive(0);
Test->check_current_operations(0, 0);

View File

@ -179,6 +179,18 @@ MYSQL *mxs_mysql_real_connect(MYSQL *con, SERVER *server, const char *user, cons
mysql_optionsv(con, MYSQL_OPT_RECONNECT, &yes);
mysql_optionsv(con, MYSQL_INIT_COMMAND, "SET SQL_MODE=''");
MXS_CONFIG* config = config_get_global_options();
if (config->local_address)
{
if (mysql_optionsv(con, MYSQL_OPT_BIND, config->local_address) != 0)
{
MXS_ERROR("'local_address' specified in configuration file, but could not "
"configure MYSQL handle. MaxScale will try to connect using default "
"address.");
}
}
MYSQL* mysql = mysql_real_connect(con, server->name, user, passwd, NULL, server->port, NULL, 0);
if (mysql)

View File

@ -9,6 +9,7 @@ add_executable(test_hash test_hash.cc)
add_executable(test_hint test_hint.cc)
add_executable(test_http test_http.cc)
add_executable(test_json test_json.cc)
add_executable(test_local_address test_local_address.cc)
add_executable(test_log test_log.cc)
add_executable(test_logorder test_logorder.cc)
add_executable(test_logthrottling test_logthrottling.cc)
@ -38,6 +39,7 @@ target_link_libraries(test_hash maxscale-common)
target_link_libraries(test_hint maxscale-common)
target_link_libraries(test_http maxscale-common)
target_link_libraries(test_json maxscale-common)
target_link_libraries(test_local_address maxscale-common)
target_link_libraries(test_log maxscale-common)
target_link_libraries(test_logorder maxscale-common)
target_link_libraries(test_logthrottling maxscale-common)

View File

@ -0,0 +1,183 @@
/*
* Copyright (c) 2016 MariaDB Corporation Ab
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
*
* Change Date: 2019-07-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <maxscale/config.h>
#include <maxscale/mysql_utils.h>
using namespace std;
char USAGE[] =
"usage: test_local_address -u user [-p password] [-a address] [-h host] [-s success]\n"
"\n"
"user : The user to connect as.\n"
"password: The password of the user, default none.\n"
"address : The address to connect from, default none specified.\n"
"host : The address of the host to connect to, default 127.0.0.1.\n"
"success : (0|1), whether the connection attempt is expected to succeed or not, defaul 1.\n"
"\n"
"Example:\n"
"\n"
"MariaDB [(none)]> create user 'l1'@'192.168.1.254';\n"
"MariaDB [(none)]> create user 'l2'@'127.0.0.1';\n"
"\n"
"$ ./test_local_address -s 1 -u l1 -a 192.168.1.254\n"
"User : l1\n"
"Password: (none)\n"
"Server : 127.0.0.1\n"
"Address : 192.168.1.254\n"
"Success : 1\n"
"\n"
"Could connect, as expected.\n"
"$ ./test_local_address -s 0 -u l1 -a 127.0.0.1\n"
"User : l1\n"
"Password: (none)\n"
"Server : 127.0.0.1\n"
"Address : 127.0.0.1\n"
"Success : 0\n"
"\n"
"Could not connect, as expected. "
"Reported error: Access denied for user 'l1'@'localhost' (using password: NO)\n"
"$ ./test_local_address -s 1 -u l2 -a 127.0.0.1\n"
"User : l2\n"
"Password: (none)\n"
"Server : 127.0.0.1\n"
"Address : 127.0.0.1\n"
"Success : 1\n"
"\n"
"Could connect, as expected.\n"
"$ ./test_local_address -s 0 -u l2 -a 192.168.1.254\n"
"User : l2\n"
"Password: (none)\n"
"Server : 127.0.0.1\n"
"Address : 192.168.1.254\n"
"Success : 0\n"
"\n"
"Could not connect, as expected. "
"Reported error: Access denied for user 'l2'@'192.168.1.254' (using password: NO)\n";
namespace
{
int test(bool success, const char* zHost, const char* zUser, const char* zPassword, const char* zAddress)
{
int rv = EXIT_FAILURE;
MXS_CONFIG* config = config_get_global_options();
config->local_address = const_cast<char*>(zAddress);
SERVER server;
memset(&server, 0, sizeof(server));
strcpy(server.name, zHost);
server.port = 3306;
MYSQL* pMysql = mysql_init(NULL);
MYSQL* pConn = mxs_mysql_real_connect(pMysql, &server, zUser, zPassword);
if (pConn)
{
if (success)
{
cout << "Could connect, as expected." << endl;
rv = EXIT_SUCCESS;
}
else
{
cerr << "Error: Connection succeeded, although expected not to." << endl;
}
mysql_close(pConn);
}
else
{
if (!success)
{
cout << "Could not connect, as expected. Reported error: " << mysql_error(pMysql) << endl;
rv = EXIT_SUCCESS;
}
else
{
cerr << "Error: " << mysql_error(pMysql) << endl;
}
mysql_close(pMysql);
}
return rv;
}
}
int main(int argc, char* argv[])
{
int rv = EXIT_SUCCESS;
int opt;
const char* zUser = NULL;
const char* zPassword = NULL;
const char* zAddress = NULL;
const char* zHost = "127.0.0.1";
bool success = true;
while ((opt = getopt(argc, argv, "a:h:p:s:u:")) != -1)
{
switch (opt)
{
case 'a':
zAddress = optarg;
break;
case 'h':
zHost = optarg;
break;
case 'p':
zPassword = optarg;
break;
case 's':
success = (atoi(optarg) == 0) ? false : true;
break;
case 'u':
zUser = optarg;
break;
default:
rv = EXIT_FAILURE;
}
}
if ((rv == EXIT_SUCCESS) && zUser)
{
cout << "User : " << zUser << endl;
cout << "Password: " << (zPassword ? zPassword : "(none)") << endl;
cout << "Server : " << zHost << endl;
cout << "Address : " << (zAddress ? zAddress : "(default)") << endl;
cout << "Success : " << success << endl;
cout << endl;
rv = test(success, zHost, zUser, zPassword, zAddress);
}
else
{
cerr << USAGE << endl;
}
return rv;
}

View File

@ -1255,6 +1255,7 @@ static bool slave_receiving_events(MariaDBMonitor* handle)
MySqlServerInfo* info = get_server_info(handle, server);
if (info->slave_configured &&
info->slave_status.slave_io_running &&
info->slave_status.master_server_id == master_id &&
difftime(time(NULL), info->latest_event) < handle->master_failure_timeout)
{