[ZBXNEXT-2753] Add support for using SSL when connecting to database (backend) Created: 2015 Mar 19  Updated: 2024 Apr 10  Resolved: 2020 Mar 28

Status: Closed
Project: ZABBIX FEATURE REQUESTS
Component/s: Proxy (P), Server (S)
Affects Version/s: 2.4.4
Fix Version/s: 5.0.0alpha4, 5.0 (plan)

Type: Change Request Priority: Major
Reporter: A B Assignee: Vladislavs Sokurenko
Resolution: Fixed Votes: 18
Labels: database, security, ssl
Σ Remaining Estimate: Not Specified Remaining Estimate: Not Specified
Σ Time Spent: Not Specified Time Spent: Not Specified
Σ Original Estimate: Not Specified Original Estimate: Not Specified

Attachments: File ZBXNEXT-2753-frontend-mysql-enable-dbtls-for-zabbix-4.0.12.patch     File ZBXNEXT-2753-server-proxy-mysql-enable-dbtls-for-zabbix-4.0.12.patch     File ZBXNEXT-2753-server-proxy-mysql-enable-dbtls.patch    
Issue Links:
Causes
causes ZBXNEXT-6157 Improved setup page for the connectio... Closed
Duplicate
is duplicated by ZBXNEXT-3313 Implement support for TLS on MySQL co... Closed
is duplicated by ZBXNEXT-5534 dbtls support not present in Zabbix 4... Closed
is duplicated by ZBX-12650 PostgreSQL Database Connection using ... Closed
Sub-task
Sub-Tasks:
Key
Summary
Type
Status
Assignee
ZBXNEXT-5641 Frontend changes to add support for u... Specification change (Sub-task) Closed Vasily Goncharenko  
Team: Team A
Sprint: Sprint 59 (Dec 2019), Sprint 60 (Jan 2020), Sprint 61 (Feb 2020), Sprint 62 (Mar 2020)
Story Points: 3

 Description   

There is currently no support for using SSL for the database connection. This is important, however, for deployments where the database is not on the same closely controlled LAN as the server, such as deployments in the cloud (EC2, etc), as some recorded data (in particularly from log messages) may contain sensitive information. At the very least what is needed are two additional db config options: whether to enable SSL, and the name of the file containing a trusted CA cert to use when verifying the server's cert.



 Comments   
Comment by Oleg Egorov (Inactive) [ 2017 Jun 27 ]

For MySQL mysql_conntect should be changed to...

something like this:

$DB['DB'] = mysqli_init();
mysqli_ssl_set($DB['DB'], $DB['DB_KEY_FILE'], $DB['DB_CERT_FILE'], $DB['DB_CA_FILE'],
	$DB['DB_CA_PATH'], $DB['DB_CA_CIPHER']);
mysqli_real_connect($DB['DB'], $DB['SERVER'], $DB['USER'], $DB['PASSWORD'], $DB['DATABASE'],
	$DB['PORT']);

$ssl = DBfetch(DBselect("SHOW STATUS LIKE 'Ssl_cipher'"));

if ($DB['DB'] && (!$ssl || $ssl['Value'] === '')) {
	$error = 'Established connection is not secure';
	$result = false;
}
Comment by Glebs Ivanovskis (Inactive) [ 2017 Jun 27 ]

Linked duplicate contains community patch.

Comment by Glebs Ivanovskis (Inactive) [ 2017 Jun 27 ]

Server-side changes for MySQL:

Index: include/db.h
===================================================================
--- include/db.h	(revision 69325)
+++ include/db.h	(revision 69326)
@@ -32,6 +32,13 @@
 extern char	*CONFIG_DBPASSWORD;
 extern char	*CONFIG_DBSOCKET;
 extern int	CONFIG_DBPORT;
+#ifdef DBTLS
+extern char	*CONFIG_DB_KEY_FILE;
+extern char	*CONFIG_DB_CERT_FILE;
+extern char	*CONFIG_DB_CA_FILE;
+extern char	*CONFIG_DB_CA_PATH;
+extern char	*CONFIG_DB_CIPHER;
+#endif
 extern int	CONFIG_HISTSYNCER_FORKS;
 extern int	CONFIG_UNAVAILABLE_DELAY;
 
Index: include/zbxdb.h
===================================================================
--- include/zbxdb.h	(revision 69325)
+++ include/zbxdb.h	(revision 69326)
@@ -50,7 +50,11 @@
 #	define ZBX_ROW_DL	";\n"
 #endif
 
-int	zbx_db_connect(char *host, char *user, char *password, char *dbname, char *dbschema, char *dbsocket, int port);
+int	zbx_db_connect(char *host, char *user, char *password, char *dbname, char *dbschema, char *dbsocket, int port
+#ifdef DBTLS
+		, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher
+#endif
+);
 #ifdef HAVE_SQLITE3
 void	zbx_create_sqlite3_mutex(void);
 void	zbx_remove_sqlite3_mutex(void);
Index: src/zabbix_proxy/proxy.c
===================================================================
--- src/zabbix_proxy/proxy.c	(revision 69325)
+++ src/zabbix_proxy/proxy.c	(revision 69326)
@@ -198,6 +198,13 @@
 char	*CONFIG_DBPASSWORD		= NULL;
 char	*CONFIG_DBSOCKET		= NULL;
 int	CONFIG_DBPORT			= 0;
+#ifdef DBTLS
+char	*CONFIG_DB_KEY_FILE		= NULL;
+char	*CONFIG_DB_CERT_FILE		= NULL;
+char	*CONFIG_DB_CA_FILE		= NULL;
+char	*CONFIG_DB_CA_PATH		= NULL;
+char	*CONFIG_DB_CIPHER		= NULL;
+#endif
 int	CONFIG_ENABLE_REMOTE_COMMANDS	= 0;
 int	CONFIG_LOG_REMOTE_COMMANDS	= 0;
 int	CONFIG_UNSAFE_USER_PARAMETERS	= 0;
@@ -639,6 +646,18 @@
 			PARM_OPT,	0,			0},
 		{"DBPort",			&CONFIG_DBPORT,				TYPE_INT,
 			PARM_OPT,	1024,			65535},
+#ifdef DBTLS
+		{"DBKeyFile",			&CONFIG_DB_KEY_FILE,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+		{"DBCertFile",			&CONFIG_DB_CERT_FILE,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+		{"DBCAFile",			&CONFIG_DB_CA_FILE,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+		{"DBCAPath",			&CONFIG_DB_CA_PATH,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+		{"DBCipher",			&CONFIG_DB_CIPHER,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+#endif
 		{"SSHKeyLocation",		&CONFIG_SSH_KEY_LOCATION,		TYPE_STRING,
 			PARM_OPT,	0,			0},
 		{"LogSlowQueries",		&CONFIG_LOG_SLOW_QUERIES,		TYPE_INT,
Index: src/zabbix_server/server.c
===================================================================
--- src/zabbix_server/server.c	(revision 69325)
+++ src/zabbix_server/server.c	(revision 69326)
@@ -187,6 +187,13 @@
 char	*CONFIG_DBPASSWORD		= NULL;
 char	*CONFIG_DBSOCKET		= NULL;
 int	CONFIG_DBPORT			= 0;
+#ifdef DBTLS
+char	*CONFIG_DB_KEY_FILE		= NULL;
+char	*CONFIG_DB_CERT_FILE		= NULL;
+char	*CONFIG_DB_CA_FILE		= NULL;
+char	*CONFIG_DB_CA_PATH		= NULL;
+char	*CONFIG_DB_CIPHER		= NULL;
+#endif
 int	CONFIG_ENABLE_REMOTE_COMMANDS	= 0;
 int	CONFIG_LOG_REMOTE_COMMANDS	= 0;
 int	CONFIG_UNSAFE_USER_PARAMETERS	= 0;
@@ -593,6 +600,18 @@
 			PARM_OPT,	0,			0},
 		{"DBPort",			&CONFIG_DBPORT,				TYPE_INT,
 			PARM_OPT,	1024,			65535},
+#ifdef DBTLS
+		{"DBKeyFile",			&CONFIG_DB_KEY_FILE,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+		{"DBCertFile",			&CONFIG_DB_CERT_FILE,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+		{"DBCAFile",			&CONFIG_DB_CA_FILE,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+		{"DBCAPath",			&CONFIG_DB_CA_PATH,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+		{"DBCipher",			&CONFIG_DB_CIPHER,			TYPE_STRING,
+			PARM_OPT,	0,			0},
+#endif
 		{"SSHKeyLocation",		&CONFIG_SSH_KEY_LOCATION,		TYPE_STRING,
 			PARM_OPT,	0,			0},
 		{"LogSlowQueries",		&CONFIG_LOG_SLOW_QUERIES,		TYPE_INT,
Index: src/libs/zbxdbhigh/db.c
===================================================================
--- src/libs/zbxdbhigh/db.c	(revision 69325)
+++ src/libs/zbxdbhigh/db.c	(revision 69326)
@@ -73,7 +73,12 @@
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() flag:%d", __function_name, flag);
 
 	while (ZBX_DB_OK != (err = zbx_db_connect(CONFIG_DBHOST, CONFIG_DBUSER, CONFIG_DBPASSWORD,
-			CONFIG_DBNAME, CONFIG_DBSCHEMA, CONFIG_DBSOCKET, CONFIG_DBPORT)))
+			CONFIG_DBNAME, CONFIG_DBSCHEMA, CONFIG_DBSOCKET, CONFIG_DBPORT
+#ifdef DBTLS
+			, CONFIG_DB_KEY_FILE, CONFIG_DB_CERT_FILE, CONFIG_DB_CA_FILE, CONFIG_DB_CA_PATH
+			, CONFIG_DB_CIPHER
+#endif
+			)))
 	{
 		if (ZBX_DB_CONNECT_ONCE == flag)
 			break;
Index: src/libs/zbxdb/db.c
===================================================================
--- src/libs/zbxdb/db.c	(revision 69325)
+++ src/libs/zbxdb/db.c	(revision 69326)
@@ -21,6 +21,10 @@
 
 #include "zbxdb.h"
 
+#if defined(DBTLS) && !defined(HAVE_MYSQL)
+#	error "Secure connection with database server is only available for MySQL."
+#endif
+
 #if defined(HAVE_IBM_DB2)
 #	include <sqlcli1.h>
 #elif defined(HAVE_MYSQL)
@@ -283,7 +287,11 @@
  *               ZBX_DB_FAIL - failed to connect                              *
  *                                                                            *
  ******************************************************************************/
-int	zbx_db_connect(char *host, char *user, char *password, char *dbname, char *dbschema, char *dbsocket, int port)
+int	zbx_db_connect(char *host, char *user, char *password, char *dbname, char *dbschema, char *dbsocket, int port
+#ifdef DBTLS
+		, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher
+#endif
+)
 {
 	int		ret = ZBX_DB_OK, last_txn_error, last_txn_level;
 #if defined(HAVE_IBM_DB2)
@@ -290,6 +298,9 @@
 	char		*connect = NULL;
 #elif defined(HAVE_MYSQL)
 	my_bool		mysql_reconnect = 1;
+#ifdef DBTLS
+	unsigned char	use_tls;
+#endif
 #elif defined(HAVE_ORACLE)
 	char		*connect = NULL;
 	sword		err = OCI_SUCCESS;
@@ -392,13 +403,43 @@
 		zabbix_log(LOG_LEVEL_CRIT, "cannot allocate or initialize MYSQL database connection object");
 		exit(EXIT_FAILURE);
 	}
+#ifdef DBTLS
+	/* if at least one of DB TLS parameters was provided, pass them to MySQL and require secure connection */
+	if (NULL != key || NULL != cert || NULL != ca || NULL != capath || NULL != cipher)
+	{
+		my_bool	verify = 1;
 
+		use_tls = 1;
+
+		mysql_ssl_set(conn, key, cert, ca, capath, cipher);
+		mysql_options(conn, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (void *)&verify);
+	}
+	else
+	{
+		use_tls = 0;
+		zabbix_log(LOG_LEVEL_WARNING, "None of encryption parameters was provided. Database connection is going"
+				" to be unencrypted.");
+	}
+#endif
 	if (NULL == mysql_real_connect(conn, host, user, password, dbname, port, dbsocket, CLIENT_MULTI_STATEMENTS))
 	{
 		zabbix_errlog(ERR_Z3001, dbname, mysql_errno(conn), mysql_error(conn));
 		ret = ZBX_DB_FAIL;
 	}
+#ifdef DBTLS
+	if (ZBX_DB_OK == ret && 1 == use_tls)
+	{
+		const char	*ssl_cipher;
 
+		if (NULL == (ssl_cipher = mysql_get_ssl_cipher(conn)))
+		{
+			zabbix_log(LOG_LEVEL_ERR, "cannot establish TLS to MySQL database");
+			ret = ZBX_DB_FAIL;
+		}
+		else
+			zabbix_log(LOG_LEVEL_DEBUG, "Cipher in use: \"%s\".", ssl_cipher);
+	}
+#endif
 	/* The RECONNECT option setting is placed here, AFTER the connection	*/
 	/* is made, due to a bug in MySQL versions prior to 5.1.6 where it	*/
 	/* reset the options value to the default, regardless of what it was	*/
Index: configure.ac
===================================================================
--- configure.ac	(revision 69325)
+++ configure.ac	(revision 69326)
@@ -1089,6 +1089,14 @@
 esac],
 [ipv6=no])
 
+AC_ARG_ENABLE(dbtls,[  --enable-dbtls          Turn on support of secure DB connections],
+[case "${enableval}" in
+  yes) dbtls=yes ;;
+  no)  dbtls=no ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --enable-dbtls]) ;;
+esac],
+[dbtls=no])
+
 have_db="no"
 have_unixodbc="no"
 have_web_monitoring="no"
@@ -1104,6 +1112,11 @@
 	have_ipv6="yes"
 fi
 
+if test "x$dbtls" = "xyes"; then
+	AC_DEFINE(DBTLS,1,[Define to 1 if support for secure DB connections should be enabled.])
+	have_dbtls="yes"
+fi
+
 if test "x$server" = "xyes" || test "x$proxy" = "xyes"; then
 
 	have_multirow_insert="no"
@@ -1111,6 +1124,10 @@
 	dnl Checking for IBM DB2 support
 	AX_LIB_IBM_DB2()
 	if test "x$want_ibm_db2" = "xyes"; then
+		if test "x$have_dbtls" = "xyes"; then
+			AC_MSG_ERROR([Secure connections are not supported for IBM DB2])
+		fi
+
 		if test "x$have_db" != "xno"; then
 			AC_MSG_ERROR([You can configure for only one database.])
 		fi
@@ -1141,6 +1158,10 @@
 	dnl Checking for Oracle support
 	AX_LIB_ORACLE_OCI([10.0])
 	if test "x$want_oracle_oci" = "xyes"; then
+		if test "x$have_dbtls" = "xyes"; then
+			AC_MSG_ERROR([Secure connections are not supported for Oracle])
+		fi
+
 		if test "x$have_db" != "xno"; then
 			AC_MSG_ERROR([You can configure for only one database.])
 		fi
@@ -1161,6 +1182,10 @@
 	dnl Checking for PostgreSQL support
 	AX_LIB_POSTGRESQL("8.1")
 	if test "x$want_postgresql" = "xyes"; then
+		if test "x$have_dbtls" = "xyes"; then
+			AC_MSG_ERROR([Secure connections are not supported for PostgreSQL])
+		fi
+
 		if test "x$have_db" != "xno"; then
 			AC_MSG_ERROR([You can configure for only one database.])
 		fi
@@ -1184,6 +1209,10 @@
 	dnl Checking for SQLite3 support
 	AX_LIB_SQLITE3()
 	if test "x$want_sqlite3" = "xyes"; then
+		if test "x$have_dbtls" = "xyes"; then
+			AC_MSG_ERROR([Secure connections are not supported for SQLite3])
+		fi
+
 		if test "x$have_db" != "xno"; then
 			AC_MSG_ERROR([You can configure for only one database.])
 		fi
@@ -1668,6 +1697,7 @@
 
 echo "  Server details:
     With database:         ${have_db}
+    Secure connections:    ${have_dbtls}
     WEB Monitoring:        ${have_web_monitoring}
     Native Jabber:         ${have_jabber}
     SNMP:                  ${have_snmp}
@@ -1687,6 +1717,7 @@
 
 echo "  Proxy details:
     With database:         ${have_db}
+    Secure connections:    ${have_dbtls}
     WEB Monitoring:        ${have_web_monitoring}
     SNMP:                  ${have_snmp}
     IPMI:                  ${have_ipmi}
Comment by N Forbes [ 2017 Oct 02 ]

Is there an update on this feature request?

Comment by Rostislav Palivoda [ 2017 Oct 02 ]

Currently only for MySQL and without nice UI for front end during installation.
If you really need itin Zabbix product (for MySQL only) please contact [email protected] to sponsorship missed parts of UI.
Thank you.

Comment by N Forbes [ 2017 Oct 02 ]

Thank you for the update. Is my understanding correct that the feature will be available for MySQL in Zabbix version 4.0 in March next year?

Comment by Rostislav Palivoda [ 2017 Oct 02 ]

Code is for MySQL only.
No, it's not yet confirmed for 4.0alpha1 version.
Implementation for all supported DBs is a significant effort. Now we could talk about finishing implementation for MySQL only.
Sponsorship will greatly increase chances to include it for 4.0 release.

Comment by dimir [ 2019 Mar 01 ]

The following are the instructions to add support for secure connections to MySQL database to Proxy/Server and Frontend.

Proxy/Server

Choose the patch for 4.0 or 3.0:

Get Zabbix sources, when running configure specify option --enable-dbtls:

$ wget https://github.com/zabbix/zabbix/archive/4.0.12.zip
$ unzip 4.0.12.zip
$ cd zabbix-4.0.12
$ patch -b -p1 < ZBXNEXT-2753-server-proxy-mysql-enable-dbtls-for-zabbix-4.0.12.patch
$ ./bootstrap.sh
$ ./configure ... --prefix=$(pwd) --with-mysql --enable-dbtls
$ make -s install
$ ls -l sbin/zabbix_server sbin/zabbix_proxy 
-rwxr-xr-x  1  zabbix  zabbix  5488656  Sep   4  14:20  sbin/zabbix_proxy
-rwxr-xr-x  1  zabbix  zabbix  7179208  Sep   4  14:20  sbin/zabbix_server

You should see

    Secure connections:    yes

For both server and proxy. New options supported in server and proxy config files:

# The path name of the client private key file.
#DBKeyFile=

# The path name of the client public key certificate file.
#DBCertFile=

# The path name of the Certificate Authority (CA) certificate file. This option, if used, must specify the same certificate used by the server.
#DBCAFile=

# The path name of the directory that contains trusted SSL CA certificate files.
#DBCAPath=

# The list of permissible ciphers for SSL encryption.
#DBCipher=

These will be passed as options to mysql_ssl_set.

Frontend

Patch for Frontend, tested on 4.0.12:

Patching:

$ cd frontends/php
$ patch -b -p0 < ZBXNEXT-2753-frontend-mysql-enable-dbtls-for-zabbix-4.0.12.patch

The patch changes file include/db.inc.php . New config options supported in zabbix.conf.php:

// TLS parameters. Used only for MySQL. Optional.
//$DB['DB_KEY_FILE'] = null;
//$DB['DB_CERT_FILE'] = null;
//$DB['DB_CA_FILE'] = null;
//$DB['DB_CA_PATH'] = null;
//$DB['DB_CA_CIPHER'] = null;

These will be passed as options to mysqli_ssl_set.

Comment by Konstantin Kornienko [ 2019 Dec 02 ]

Any updates on including these patches to master? Thanks!

Comment by dimir [ 2019 Dec 02 ]

The problem is that we have only MySQL implementation ready. PostgreSQL and Oracle yet to come. So question is, should we release the functionality limited to MySQL and add others later or wait and release when we are ready completely. This is for decision makers to decide.

Comment by Paul Mohr [ 2019 Dec 07 ]

I would like to add, that some cloud providers (Digitalocean for example) offer their managed database service only via SSL connections. I'd think having SSL support (even when it's only for MySQL) would be a great positive for zabbix, because it could be deployed on more cloud solutions.

Comment by Konstantin Kornienko [ 2019 Dec 08 ]

Agreed with Paul! If MySQL code is ready, it'd be great to release it. Then, based on this code, somebody can prepare patch for the rest of supported DBs.

Comment by Alexei Vladishev [ 2020 Jan 24 ]

Support of encrypted connections is coming in Zabbix 5.0, the work is already in progress. It will be available for both MySQL and PostgreSQL. 

Comment by Konstantin Kornienko [ 2020 Feb 20 ]

Thanks a lot, Zabbix team. So great news!

Comment by Martins Abele [ 2020 Mar 17 ]

Available in

Documentation updated:

Generated at Sat Apr 27 04:50:57 EEST 2024 using Jira 9.12.4#9120004-sha1:625303b708afdb767e17cb2838290c41888e9ff0.