diff --git a/include/zbxdb.h b/include/zbxdb.h index ff00865da8..60f87ee6b7 100644 --- a/include/zbxdb.h +++ b/include/zbxdb.h @@ -30,6 +30,7 @@ #define ZBX_DB_TLS_CONNECT_REQUIRED_TXT "required" #define ZBX_DB_TLS_CONNECT_VERIFY_CA_TXT "verify_ca" #define ZBX_DB_TLS_CONNECT_VERIFY_FULL_TXT "verify_full" +#define ZBX_DB_SESSION_TARGET_ATTR_READ_WRITE "read-write" typedef char **DB_ROW; typedef struct zbx_db_result *DB_RESULT; @@ -46,7 +47,9 @@ zbx_db_value_t; typedef struct { + char *config_dbconnstring; char *config_dbhost; + char *config_dbtargetattr; char *config_dbname; char *config_dbschema; char *config_dbuser; diff --git a/src/libs/zbxdb/db.c b/src/libs/zbxdb/db.c index 1801f436b4..0b571e487c 100644 --- a/src/libs/zbxdb/db.c +++ b/src/libs/zbxdb/db.c @@ -411,11 +411,13 @@ void zbx_db_init_autoincrement_options_basic(void) int zbx_db_connect_basic(const zbx_config_dbhigh_t *config_dbhigh) { int ret = ZBX_DB_OK, last_txn_error, last_txn_level; - const char *host, *user, *password, *dbname, *dbschema, *dbsocket, *tls_connect, *cert, *key, *ca, *cipher, + const char *connectionstring, *host, *session_target_attr, *user, *password, *dbname, *dbschema, *dbsocket, *tls_connect, *cert, *key, *ca, *cipher, *cipher_13; const int port = config_dbhigh->config_dbport; + connectionstring = config_dbhigh->config_dbconnstring; host = config_dbhigh->config_dbhost; + session_target_attr = config_dbhigh->config_dbtargetattr; user = config_dbhigh->config_dbuser; password = config_dbhigh->config_dbpassword; dbname = config_dbhigh->config_dbname; @@ -764,72 +766,84 @@ int zbx_db_connect_basic(const zbx_config_dbhigh_t *config_dbhigh) ZBX_UNUSED(cipher); ZBX_UNUSED(cipher_13); - if (NULL != tls_connect) + if NULL != connectionstring { - keywords[i] = "sslmode"; + conn = PQconnectdb(connectionstring); + } else { + if (NULL != tls_connect) + { + keywords[i] = "sslmode"; - if (0 == strcmp(tls_connect, ZBX_DB_TLS_CONNECT_REQUIRED_TXT)) - values[i++] = "require"; - else if (0 == strcmp(tls_connect, ZBX_DB_TLS_CONNECT_VERIFY_CA_TXT)) - values[i++] = "verify-ca"; - else - values[i++] = "verify-full"; - } + if (0 == strcmp(tls_connect, ZBX_DB_TLS_CONNECT_REQUIRED_TXT)) + values[i++] = "require"; + else if (0 == strcmp(tls_connect, ZBX_DB_TLS_CONNECT_VERIFY_CA_TXT)) + values[i++] = "verify-ca"; + else + values[i++] = "verify-full"; + } - if (NULL != cert) - { - keywords[i] = "sslcert"; - values[i++] = cert; - } + if (NULL != cert) + { + keywords[i] = "sslcert"; + values[i++] = cert; + } - if (NULL != key) - { - keywords[i] = "sslkey"; - values[i++] = key; - } + if (NULL != key) + { + keywords[i] = "sslkey"; + values[i++] = key; + } - if (NULL != ca) - { - keywords[i] = "sslrootcert"; - values[i++] = ca; - } + if (NULL != ca) + { + keywords[i] = "sslrootcert"; + values[i++] = ca; + } - if (NULL != host) - { - keywords[i] = "host"; - values[i++] = host; - } + if (NULL != host) + { + keywords[i] = "host"; + values[i++] = host; + } - if (NULL != dbname) - { - keywords[i] = "dbname"; - values[i++] = dbname; - } + if (NULL != dbname) + { + keywords[i] = "dbname"; + values[i++] = dbname; + } - if (NULL != user) - { - keywords[i] = "user"; - values[i++] = user; - } + if (NULL != user) + { + keywords[i] = "user"; + values[i++] = user; + } - if (NULL != password) - { - keywords[i] = "password"; - values[i++] = password; - } + if (NULL != password) + { + keywords[i] = "password"; + values[i++] = password; + } - if (0 != port) - { - keywords[i] = "port"; - values[i++] = cport = zbx_dsprintf(cport, "%d", port); - } + if (0 != port) + { + keywords[i] = "port"; + values[i++] = cport = zbx_dsprintf(cport, "%d", port); + } - keywords[i] = NULL; - values[i] = NULL; + if (NULL != target_session_attr) + { + keywords[i] = "target_session_attr"; + values[i++] = target_session_attr; + } + + keywords[i] = NULL; + values[i] = NULL; - conn = PQconnectdbParams(keywords, values, 0); + conn = PQconnectdbParams(keywords, values, 0); - zbx_free(cport); + zbx_free(cport); + + } /* check to see that the backend connection was successfully made */ if (CONNECTION_OK != PQstatus(conn)) diff --git a/src/zabbix_server/server.c b/src/zabbix_server/server.c index cf590e6e32..8b95c79520 100644 --- a/src/zabbix_server/server.c +++ b/src/zabbix_server/server.c @@ -615,6 +615,9 @@ static void zbx_set_defaults(void) if (NULL == zbx_config_dbhigh->config_dbhost) zbx_config_dbhigh->config_dbhost = zbx_strdup(zbx_config_dbhigh->config_dbhost, "localhost"); + if (NULL == zbx_config_dbhigh->config_dbtargetattr) + zbx_config_dbhigh->config_dbtargetattr = zbx_strdup(zbx_config_dbhigh->config_dbtargetattr, ZBX_DB_SESSION_TARGET_ATTR_READ_WRITE); + if (NULL == CONFIG_SNMPTRAP_FILE) CONFIG_SNMPTRAP_FILE = zbx_strdup(CONFIG_SNMPTRAP_FILE, "/tmp/zabbix_traps.tmp"); @@ -911,8 +914,12 @@ static void zbx_load_config(ZBX_TASK_EX *task) PARM_OPT, 0, 0}, {"ExternalScripts", &CONFIG_EXTERNALSCRIPTS, TYPE_STRING, PARM_OPT, 0, 0}, + {"DBConnectionString", &(zbx_config_dbhigh->config_dbconnstring), TYPE_STRING, + PARM_OPT, 0, 0}, {"DBHost", &(zbx_config_dbhigh->config_dbhost), TYPE_STRING, PARM_OPT, 0, 0}, + {"DBTargetSessionAttr", &(zbx_config_dbhigh->config_dbtargetattr), TYPE_STRING, + PARM_OPT, 0, 0}, {"DBName", &(zbx_config_dbhigh->config_dbname), TYPE_STRING, PARM_MAND, 0, 0}, {"DBSchema", &(zbx_config_dbhigh->config_dbschema), TYPE_STRING, diff --git a/ui/conf/zabbix.conf.php.example b/ui/conf/zabbix.conf.php.example index 6568b6a8a3..4daf3f6910 100644 --- a/ui/conf/zabbix.conf.php.example +++ b/ui/conf/zabbix.conf.php.example @@ -2,11 +2,18 @@ // Zabbix GUI configuration file. $DB['TYPE'] = 'MYSQL'; +// If $DB['CONNECTIONSTRING'] used with PostgreSQL, then rest of DB connection parameters are ignored for connection. +// $DB['DATABASE'] and $DB['USER'] are required for internal purposes. +//$DB['CONNECTIONSTRING'] = 'postgresql://zabbix:ZabbixPassword@localhost/zabbix'; + +// DB Connection parameters $DB['SERVER'] = 'localhost'; $DB['PORT'] = '0'; $DB['DATABASE'] = 'zabbix'; $DB['USER'] = 'zabbix'; $DB['PASSWORD'] = ''; +// Uncomment and set to desired values for PG target_session_attr. If not set or empty, defaults to 'read-write'. +$DB['TARGET_SESSION_ATTR'] = ''; // Schema name. Used for PostgreSQL. $DB['SCHEMA'] = ''; diff --git a/ui/include/classes/core/CConfigFile.php b/ui/include/classes/core/CConfigFile.php index 9e2fd882ff..4a6b3c6602 100644 --- a/ui/include/classes/core/CConfigFile.php +++ b/ui/include/classes/core/CConfigFile.php @@ -94,6 +94,14 @@ class CConfigFile { $this->config['DB']['TYPE'] = $DB['TYPE']; $this->config['DB']['DATABASE'] = $DB['DATABASE']; + if (isset($DB['CONNECTIONSTRING'])) { + $this->config['DB']['CONNECTIONSTRING'] = $DB['CONNECTIONSTRING']; + } + + if (isset($DB['TARGET_SESSION_ATTR'])) { + $this->config['DB']['TARGET_SESSION_ATTR'] = $DB['TARGET_SESSION_ATTR']; + } + if (isset($DB['SERVER'])) { $this->config['DB']['SERVER'] = $DB['SERVER']; } @@ -254,12 +262,19 @@ class CConfigFile { 'config['DB']['CONNECTIONSTRING'], "'\\") . '\'; + +// DB Connection parameters $DB[\'TYPE\'] = \''.addcslashes($this->config['DB']['TYPE'], "'\\").'\'; $DB[\'SERVER\'] = \''.addcslashes($this->config['DB']['SERVER'], "'\\").'\'; $DB[\'PORT\'] = \''.addcslashes($this->config['DB']['PORT'], "'\\").'\'; $DB[\'DATABASE\'] = \''.addcslashes($this->config['DB']['DATABASE'], "'\\").'\'; $DB[\'USER\'] = \''.addcslashes($this->config['DB']['USER'], "'\\").'\'; $DB[\'PASSWORD\'] = \''.addcslashes($this->config['DB']['PASSWORD'], "'\\").'\'; +// Uncomment and set to desired values for PG target_session_attr. If not set or empty, defaults to \'read-write\'. +$DB[\'TARGET_SESSION_ATTR\'] = \''.addcslashes($this->config['DB']['TARGET_SESSION_ATTR'], "'\\") . '\'; // Schema name. Used for PostgreSQL. $DB[\'SCHEMA\'] = \''.addcslashes($this->config['DB']['SCHEMA'], "'\\").'\'; diff --git a/ui/include/classes/db/PostgresqlDbBackend.php b/ui/include/classes/db/PostgresqlDbBackend.php index 7f61bbc511..d6ecb16f60 100644 --- a/ui/include/classes/db/PostgresqlDbBackend.php +++ b/ui/include/classes/db/PostgresqlDbBackend.php @@ -44,6 +44,13 @@ class PostgresqlDbBackend extends DbBackend { */ protected $user = ''; + /** + * Target session attrs. + * + * @var string + */ + protected $target_session_attrs = ''; + /** * Check if 'dbversion' table exists. * @@ -189,6 +196,17 @@ class PostgresqlDbBackend extends DbBackend { return $is_secure; } + /** + * Sets target_session_attrs. + * + * @param string $target_session_attrs Postgres target_session_attr parameter value. + * + */ + public function set_target_attr($target_session_attrs) + { + $this->target_session_attrs = $target_session_attrs; + } + /** * Create connection to database server. * @@ -217,6 +235,10 @@ class PostgresqlDbBackend extends DbBackend { ]; } + $params += [ + 'target_session_attrs' => $this->target_session_attrs ? $this->target_session_attrs : 'read-write' + ]; + $conn_string = ''; foreach ($params as $key => $param) { @@ -233,6 +255,33 @@ class PostgresqlDbBackend extends DbBackend { return $resource; } + /** + * Create connection to database server using connectionstring. + * + * @param string $connectionstring ConnectionString to connect to PG + * @param string $user User name. + * @param string $dbname Database name. + * @param string $schema DB schema. + * + * @param + * @return resource|null + */ + public function connect_connectionstring($connectionstring, $user, $dbname, $schema) + { + $this->user = $user; + $this->dbname = $dbname; + $this->schema = ($schema) ? $schema : 'public'; + + $resource = @pg_connect($connectionstring); + + if (!$resource) { + $this->setError('Error connecting to database.'); + return null; + } + + return $resource; + } + /** * Initialize database connection. * diff --git a/ui/include/db.inc.php b/ui/include/db.inc.php index cf9b4af1f2..1f8365234b 100644 --- a/ui/include/db.inc.php +++ b/ui/include/db.inc.php @@ -65,7 +65,14 @@ function DBconnect(&$error) { ); } - $DB['DB'] = $db->connect($DB['SERVER'], $DB['PORT'], $DB['USER'], $DB['PASSWORD'], $DB['DATABASE'], $DB['SCHEMA']); + if ($DB['TYPE'] == ZBX_DB_POSTGRESQL && isset($DB['TARGET_SESSION_ATTR'])) { + $db->set_target_attr($DB['TARGET_SESSION_ATTR']); + } + if ($DB['TYPE'] == ZBX_DB_POSTGRESQL and isset($DB['CONNECTIONSTRING']) and $DB['CONNECTIONSTRING']) { + $DB['DB'] = $db->connect_connectionstring($DB['CONNECTIONSTRING'], $DB['USER'], $DB['DATABASE'], $DB['SCHEMA']); + } else { + $DB['DB'] = $db->connect($DB['SERVER'], $DB['PORT'], $DB['USER'], $DB['PASSWORD'], $DB['DATABASE'], $DB['SCHEMA']); + } if ($DB['DB']) { $db->init();