You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1183 lines
38 KiB
1183 lines
38 KiB
1 year ago
|
<?php
|
||
|
/*
|
||
|
** Zabbix
|
||
|
** Copyright (C) 2001-2023 Zabbix SIA
|
||
|
**
|
||
|
** This program is free software; you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation; either version 2 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program; if not, write to the Free Software
|
||
|
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
**/
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Setup wizard form.
|
||
|
*/
|
||
|
class CSetupWizard extends CForm {
|
||
|
|
||
|
public const STAGE_WELCOME = 1;
|
||
|
public const STAGE_REQUIREMENTS = 2;
|
||
|
public const STAGE_DB_CONNECTION = 3;
|
||
|
public const STAGE_SETTINGS = 4;
|
||
|
public const STAGE_SUMMARY = 5;
|
||
|
public const STAGE_INSTALL = 6;
|
||
|
|
||
|
private $frontend_setup;
|
||
|
private $stages;
|
||
|
|
||
|
private $disable_cancel_button = false;
|
||
|
private $disable_back_button = false;
|
||
|
private $show_retry_button = false;
|
||
|
|
||
|
private $step_failed = false;
|
||
|
|
||
|
public function __construct() {
|
||
|
parent::__construct();
|
||
|
|
||
|
$this->setId('setup-form');
|
||
|
|
||
|
$this->frontend_setup = new CFrontendSetup();
|
||
|
|
||
|
$this->stages = [
|
||
|
self::STAGE_WELCOME => [
|
||
|
'title' => _('Welcome'),
|
||
|
'fn' => 'stageWelcome'
|
||
|
],
|
||
|
self::STAGE_REQUIREMENTS => [
|
||
|
'title' => _('Check of pre-requisites'),
|
||
|
'fn' => 'stageRequirements'
|
||
|
],
|
||
|
self::STAGE_DB_CONNECTION => [
|
||
|
'title' => _('Configure DB connection'),
|
||
|
'fn' => 'stageDbConnection'
|
||
|
],
|
||
|
self::STAGE_SETTINGS => [
|
||
|
'title' => _('Settings'),
|
||
|
'fn' => 'stageSettings'
|
||
|
],
|
||
|
self::STAGE_SUMMARY => [
|
||
|
'title' => _('Pre-installation summary'),
|
||
|
'fn' => 'stageSummary'
|
||
|
],
|
||
|
self::STAGE_INSTALL => [
|
||
|
'title' => _('Install'),
|
||
|
'fn' => 'stageInstall'
|
||
|
]
|
||
|
];
|
||
|
|
||
|
$this->doAction();
|
||
|
}
|
||
|
|
||
|
public function getStep(): int {
|
||
|
$step = $this->getConfig('step');
|
||
|
|
||
|
return array_key_exists($step, $this->stages) ? $step : self::STAGE_WELCOME;
|
||
|
}
|
||
|
|
||
|
private function doAction(): void {
|
||
|
/*
|
||
|
* Having non-super-admin authenticated at this step means:
|
||
|
* - Either the config file has been manually created by the user.
|
||
|
* - Or dealing with a spoofed session cookie.
|
||
|
*
|
||
|
* Since it is not possible to distinguish between the two, skip data validation and prevent stage switching.
|
||
|
* Any of either cases is only possible with self::STAGE_INSTALL stage.
|
||
|
*/
|
||
|
if (CWebUser::$data && CWebUser::getType() < USER_TYPE_SUPER_ADMIN) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (hasRequest('back') && array_key_exists($this->getStep(), getRequest('back'))) {
|
||
|
$this->doBack();
|
||
|
}
|
||
|
|
||
|
if ($this->getStep() == self::STAGE_REQUIREMENTS) {
|
||
|
if (hasRequest('next') && array_key_exists(self::STAGE_REQUIREMENTS, getRequest('next'))) {
|
||
|
$finalResult = CFrontendSetup::CHECK_OK;
|
||
|
|
||
|
foreach ($this->frontend_setup->checkRequirements() as $req) {
|
||
|
if ($req['result'] > $finalResult) {
|
||
|
$finalResult = $req['result'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($finalResult == CFrontendSetup::CHECK_FATAL) {
|
||
|
$this->step_failed = true;
|
||
|
unset($_REQUEST['next']);
|
||
|
}
|
||
|
else {
|
||
|
$this->doNext();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
elseif ($this->getStep() == self::STAGE_DB_CONNECTION) {
|
||
|
$input = [
|
||
|
'DB_TYPE' => getRequest('type', $this->getConfig('DB_TYPE')),
|
||
|
'DB_SERVER' => getRequest('server', $this->getConfig('DB_SERVER', 'localhost')),
|
||
|
'DB_PORT' => getRequest('port', $this->getConfig('DB_PORT', '0')),
|
||
|
'DB_DATABASE' => getRequest('database', $this->getConfig('DB_DATABASE', 'zabbix')),
|
||
|
'DB_CREDS_STORAGE' => getRequest('creds_storage',
|
||
|
$this->getConfig('DB_CREDS_STORAGE', DB_STORE_CREDS_CONFIG)
|
||
|
),
|
||
|
'DB_PASSWORD' => getRequest('password', $this->getConfig('DB_PASSWORD', '')),
|
||
|
'DB_SCHEMA' => getRequest('schema', $this->getConfig('DB_SCHEMA', '')),
|
||
|
'DB_ENCRYPTION' => (bool) getRequest('tls_encryption', $this->getConfig('DB_ENCRYPTION', false)),
|
||
|
'DB_ENCRYPTION_ADVANCED' => (bool) getRequest('verify_certificate',
|
||
|
$this->getConfig('DB_ENCRYPTION_ADVANCED', false)
|
||
|
),
|
||
|
'DB_VERIFY_HOST' => (bool) getRequest('verify_host', $this->getConfig('DB_VERIFY_HOST', false)),
|
||
|
'DB_KEY_FILE' => getRequest('key_file', $this->getConfig('DB_KEY_FILE', '')),
|
||
|
'DB_CERT_FILE' => getRequest('cert_file', $this->getConfig('DB_CERT_FILE', '')),
|
||
|
'DB_CA_FILE' => getRequest('ca_file', $this->getConfig('DB_CA_FILE', '')),
|
||
|
'DB_CIPHER_LIST' => getRequest('cipher_list', $this->getConfig('DB_CIPHER_LIST', ''))
|
||
|
];
|
||
|
|
||
|
if (!$input['DB_ENCRYPTION_ADVANCED']) {
|
||
|
$input['DB_KEY_FILE'] = '';
|
||
|
$input['DB_CERT_FILE'] = '';
|
||
|
$input['DB_CA_FILE'] = '';
|
||
|
$input['DB_CIPHER_LIST'] = '';
|
||
|
}
|
||
|
else if ($input['DB_TYPE'] === ZBX_DB_MYSQL) {
|
||
|
$input['DB_VERIFY_HOST'] = true;
|
||
|
}
|
||
|
|
||
|
if ($input['DB_TYPE'] !== ZBX_DB_POSTGRESQL) {
|
||
|
$input['DB_SCHEMA'] = '';
|
||
|
}
|
||
|
|
||
|
foreach ($input as $name => $value) {
|
||
|
$this->setConfig($name, $value);
|
||
|
}
|
||
|
|
||
|
switch ($this->getConfig('DB_CREDS_STORAGE')) {
|
||
|
case DB_STORE_CREDS_VAULT_HASHICORP:
|
||
|
$this->setConfig('DB_VAULT_URL', getRequest('vault_url',
|
||
|
$this->getConfig('DB_VAULT_URL', CVaultHashiCorp::API_ENDPOINT_DEFAULT)
|
||
|
));
|
||
|
|
||
|
$this->setConfig('DB_VAULT_DB_PATH', getRequest('vault_db_path',
|
||
|
$this->getConfig('DB_VAULT_DB_PATH', '')
|
||
|
));
|
||
|
|
||
|
$this->setConfig('DB_VAULT_TOKEN', getRequest('vault_token', $this->getConfig('DB_VAULT_TOKEN')));
|
||
|
|
||
|
$this->unsetConfig(['DB_USER', 'DB_PASSWORD', 'DB_VAULT_CERTIFICATES', 'DB_VAULT_CERT_FILE',
|
||
|
'DB_VAULT_KEY_FILE']
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case DB_STORE_CREDS_VAULT_CYBERARK:
|
||
|
$this->setConfig('DB_VAULT_URL', getRequest('vault_url',
|
||
|
$this->getConfig('DB_VAULT_URL', CVaultCyberArk::API_ENDPOINT_DEFAULT)
|
||
|
));
|
||
|
|
||
|
$this->setConfig('DB_VAULT_DB_PATH',
|
||
|
getRequest('vault_query_string', $this->getConfig('DB_VAULT_DB_PATH'))
|
||
|
);
|
||
|
|
||
|
$vault_certificates = (bool) getRequest('vault_certificates',
|
||
|
$this->getConfig('DB_VAULT_CERTIFICATES', false)
|
||
|
);
|
||
|
$this->setConfig('DB_VAULT_CERTIFICATES', $vault_certificates);
|
||
|
|
||
|
if ($vault_certificates) {
|
||
|
$this->setConfig('DB_VAULT_CERT_FILE', getRequest('vault_cert_file',
|
||
|
$this->getConfig('DB_VAULT_CERT_FILE')
|
||
|
));
|
||
|
|
||
|
$this->setConfig('DB_VAULT_KEY_FILE', getRequest('vault_key_file',
|
||
|
$this->getConfig('DB_VAULT_KEY_FILE')
|
||
|
));
|
||
|
}
|
||
|
|
||
|
$this->unsetConfig(['DB_USER', 'DB_PASSWORD', 'DB_VAULT_TOKEN']);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
$this->setConfig('DB_USER', getRequest('user', $this->getConfig('DB_USER', 'root')));
|
||
|
$this->setConfig('DB_PASSWORD', getRequest('password', $this->getConfig('DB_PASSWORD', '')));
|
||
|
|
||
|
$this->unsetConfig(['DB_VAULT_URL', 'DB_VAULT_DB_PATH', 'DB_VAULT_TOKEN', 'DB_VAULT_CERTIFICATES',
|
||
|
'DB_VAULT_CERT_FILE', 'DB_VAULT_KEY_FILE']
|
||
|
);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (hasRequest('next') && array_key_exists(self::STAGE_DB_CONNECTION, getRequest('next'))) {
|
||
|
switch ($this->getConfig('DB_CREDS_STORAGE')) {
|
||
|
case DB_STORE_CREDS_VAULT_HASHICORP:
|
||
|
$vault_provider = new CVaultHashiCorp($this->getConfig('DB_VAULT_URL'),
|
||
|
$this->getConfig('DB_VAULT_DB_PATH'), $this->getConfig('DB_VAULT_TOKEN')
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case DB_STORE_CREDS_VAULT_CYBERARK:
|
||
|
$vault_provider = new CVaultCyberArk($this->getConfig('DB_VAULT_URL'),
|
||
|
$this->getConfig('DB_VAULT_DB_PATH'), $this->getConfig('DB_VAULT_CERT_FILE'),
|
||
|
$this->getConfig('DB_VAULT_KEY_FILE')
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
$vault_provider = null;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
$db_connected = false;
|
||
|
|
||
|
if ($vault_provider !== null) {
|
||
|
if (ini_get('allow_url_fopen') != 1) {
|
||
|
error(_('Please enable "allow_url_fopen" directive.'));
|
||
|
}
|
||
|
else {
|
||
|
$db_credentials = $vault_provider->validateParameters()
|
||
|
? $vault_provider->getCredentials()
|
||
|
: null;
|
||
|
|
||
|
if ($db_credentials === null) {
|
||
|
foreach ($vault_provider->getErrors() as $error) {
|
||
|
error($error);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
$db_connected = $this->dbConnect($db_credentials['user'], $db_credentials['password']);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
$db_connected = $this->dbConnect();
|
||
|
}
|
||
|
|
||
|
if ($db_connected) {
|
||
|
if ($this->checkConnection()) {
|
||
|
$this->doNext();
|
||
|
}
|
||
|
|
||
|
$this->dbClose();
|
||
|
}
|
||
|
else {
|
||
|
$this->step_failed = true;
|
||
|
unset($_REQUEST['next']);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
elseif ($this->getStep() == self::STAGE_SETTINGS) {
|
||
|
$this->setConfig('ZBX_SERVER_NAME', getRequest('zbx_server_name', $this->getConfig('ZBX_SERVER_NAME', '')));
|
||
|
|
||
|
if (hasRequest('next') && array_key_exists(self::STAGE_SETTINGS, getRequest('next'))) {
|
||
|
$this->doNext();
|
||
|
}
|
||
|
}
|
||
|
elseif ($this->getStep() == self::STAGE_INSTALL) {
|
||
|
if (hasRequest('save_config')) {
|
||
|
$vault_config = [
|
||
|
'VAULT' => '',
|
||
|
'VAULT_URL' => '',
|
||
|
'VAULT_DB_PATH' => '',
|
||
|
'VAULT_TOKEN' => '',
|
||
|
'VAULT_CERT_FILE' => '',
|
||
|
'VAULT_KEY_FILE' => ''
|
||
|
];
|
||
|
|
||
|
$db_creds_config = [
|
||
|
'USER' => '',
|
||
|
'PASSWORD' => ''
|
||
|
];
|
||
|
|
||
|
switch ($this->getConfig('DB_CREDS_STORAGE', DB_STORE_CREDS_CONFIG)) {
|
||
|
case DB_STORE_CREDS_VAULT_HASHICORP:
|
||
|
$vault_config['VAULT'] = CVaultHashiCorp::NAME;
|
||
|
$vault_config['VAULT_URL'] = $this->getConfig('DB_VAULT_URL');
|
||
|
$vault_config['VAULT_DB_PATH'] = $this->getConfig('DB_VAULT_DB_PATH');
|
||
|
$vault_config['VAULT_TOKEN'] = $this->getConfig('DB_VAULT_TOKEN');
|
||
|
break;
|
||
|
|
||
|
case DB_STORE_CREDS_VAULT_CYBERARK:
|
||
|
$vault_config['VAULT'] = CVaultCyberArk::NAME;
|
||
|
$vault_config['VAULT_URL'] = $this->getConfig('DB_VAULT_URL');
|
||
|
$vault_config['VAULT_DB_PATH'] = $this->getConfig('DB_VAULT_DB_PATH');
|
||
|
$vault_config['VAULT_CERT_FILE'] = $this->getConfig('VAULT_CERT_FILE');
|
||
|
$vault_config['VAULT_KEY_FILE'] = $this->getConfig('VAULT_KEY_FILE');
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
$db_creds_config['USER'] = $this->getConfig('DB_USER');
|
||
|
$db_creds_config['PASSWORD'] = $this->getConfig('DB_PASSWORD');
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// make zabbix.conf.php downloadable
|
||
|
header('Content-Type: application/x-httpd-php');
|
||
|
header('Content-Disposition: attachment; filename="'.basename(CConfigFile::CONFIG_FILE_PATH).'"');
|
||
|
$config = new CConfigFile(APP::getRootDir().CConfigFile::CONFIG_FILE_PATH);
|
||
|
$config->config = [
|
||
|
'DB' => [
|
||
|
'TYPE' => $this->getConfig('DB_TYPE'),
|
||
|
'SERVER' => $this->getConfig('DB_SERVER'),
|
||
|
'PORT' => $this->getConfig('DB_PORT'),
|
||
|
'DATABASE' => $this->getConfig('DB_DATABASE'),
|
||
|
'SCHEMA' => $this->getConfig('DB_SCHEMA'),
|
||
|
'ENCRYPTION' => (bool) $this->getConfig('DB_ENCRYPTION'),
|
||
|
'VERIFY_HOST' => (bool) $this->getConfig('DB_VERIFY_HOST'),
|
||
|
'KEY_FILE' => $this->getConfig('DB_KEY_FILE'),
|
||
|
'CERT_FILE' => $this->getConfig('DB_CERT_FILE'),
|
||
|
'CA_FILE' => $this->getConfig('DB_CA_FILE'),
|
||
|
'CIPHER_LIST' => $this->getConfig('DB_CIPHER_LIST')
|
||
|
] + $db_creds_config + $vault_config,
|
||
|
'ZBX_SERVER_NAME' => $this->getConfig('ZBX_SERVER_NAME')
|
||
|
];
|
||
|
die($config->getString());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (hasRequest('next') && array_key_exists($this->getStep(), getRequest('next'))) {
|
||
|
$this->doNext();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private function doNext(): void {
|
||
|
if (array_key_exists($this->getStep() + 1, $this->stages)) {
|
||
|
$this->setConfig('step', $this->getStep() + 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private function doBack(): void {
|
||
|
if (array_key_exists($this->getStep() - 1, $this->stages)) {
|
||
|
$this->setConfig('step', $this->getStep() - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected function bodyToString($destroy = true): string {
|
||
|
$setup_left = (new CDiv())
|
||
|
->addClass(ZBX_STYLE_SETUP_LEFT)
|
||
|
->addItem(makeLogo(LOGO_TYPE_NORMAL))
|
||
|
->addItem($this->getList());
|
||
|
|
||
|
$setup_right = (new CDiv($this->getStage()))->addClass(ZBX_STYLE_SETUP_RIGHT);
|
||
|
|
||
|
if (CWebUser::$data && CWebUser::getType() == USER_TYPE_SUPER_ADMIN) {
|
||
|
$cancel_button = (new CSubmit('cancel', _('Cancel')))
|
||
|
->addClass(ZBX_STYLE_BTN_ALT)
|
||
|
->addClass(ZBX_STYLE_FLOAT_LEFT);
|
||
|
|
||
|
if ($this->disable_cancel_button) {
|
||
|
$cancel_button->setEnabled(false);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
$cancel_button = null;
|
||
|
}
|
||
|
|
||
|
$back_button = (new CSubmit('back['.($this->getStep()).']', _('Back')))
|
||
|
->addClass(ZBX_STYLE_BTN_ALT)
|
||
|
->addClass(ZBX_STYLE_FLOAT_LEFT);
|
||
|
|
||
|
if ($this->getStep() == self::STAGE_WELCOME || $this->disable_back_button) {
|
||
|
$back_button->setEnabled(false);
|
||
|
}
|
||
|
|
||
|
if (array_key_exists($this->getStep() + 1, $this->stages)) {
|
||
|
$next_button = new CSubmit('next['.($this->getStep()).']', _('Next step'));
|
||
|
}
|
||
|
else {
|
||
|
$next_button = new CSubmit($this->show_retry_button ? 'retry' : 'finish', _('Finish'));
|
||
|
}
|
||
|
|
||
|
$setup_footer = (new CDiv([new CDiv([$next_button, $back_button]), $cancel_button]))
|
||
|
->addClass(ZBX_STYLE_SETUP_FOOTER);
|
||
|
|
||
|
$setup_container = (new CDiv([$setup_left, $setup_right, $setup_footer]))->addClass(ZBX_STYLE_SETUP_CONTAINER);
|
||
|
|
||
|
return parent::bodyToString().$setup_container->toString();
|
||
|
}
|
||
|
|
||
|
private function getStage(): array {
|
||
|
$function = $this->stages[$this->getStep()]['fn'];
|
||
|
|
||
|
return $this->$function();
|
||
|
}
|
||
|
|
||
|
private function stageWelcome(): array {
|
||
|
preg_match('/^\d+\.\d+/', ZABBIX_VERSION, $version);
|
||
|
$setup_title = (new CDiv([new CSpan(_('Welcome to')), 'Zabbix '.$version[0]]))->addClass(ZBX_STYLE_SETUP_TITLE);
|
||
|
|
||
|
$default_lang = $this->getConfig('default_lang');
|
||
|
$lang_select = (new CSelect('default_lang'))
|
||
|
->setId('default-lang')
|
||
|
->setValue($default_lang)
|
||
|
->setFocusableElementId('label-default-lang')
|
||
|
->setAttribute('autofocus', 'autofocus');
|
||
|
|
||
|
$all_locales_available = true;
|
||
|
|
||
|
foreach (getLocales() as $localeid => $locale) {
|
||
|
if (!$locale['display']) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Checking if this locale exists in the system. The only way of doing it is to try and set one
|
||
|
* trying to set only the LC_MONETARY locale to avoid changing LC_NUMERIC.
|
||
|
*/
|
||
|
$locale_available = ($localeid === ZBX_DEFAULT_LANG
|
||
|
|| setlocale(LC_MONETARY, zbx_locale_variants($localeid))
|
||
|
);
|
||
|
|
||
|
$lang_select->addOption((new CSelectOption($localeid, $locale['name']))->setDisabled(!$locale_available));
|
||
|
|
||
|
if (!$locale_available) {
|
||
|
$all_locales_available = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Restoring original locale.
|
||
|
setlocale(LC_MONETARY, zbx_locale_variants($default_lang));
|
||
|
|
||
|
$language_error = '';
|
||
|
if (!function_exists('bindtextdomain')) {
|
||
|
$language_error = 'Translations are unavailable because the PHP gettext module is missing.';
|
||
|
$lang_select->setReadonly();
|
||
|
}
|
||
|
elseif (!$all_locales_available) {
|
||
|
$language_error = _('You are not able to choose some of the languages, because locales for them are not installed on the web server.');
|
||
|
}
|
||
|
|
||
|
$language_error = $language_error !== '' ? makeErrorIcon($language_error) : null;
|
||
|
|
||
|
$language_select = (new CFormList())
|
||
|
->addRow(new CLabel(_('Default language'), $lang_select->getFocusableElementId()), [
|
||
|
$lang_select, $language_error
|
||
|
]);
|
||
|
|
||
|
return [(new CDiv([$setup_title, $language_select]))->addClass(ZBX_STYLE_SETUP_RIGHT_BODY)];
|
||
|
}
|
||
|
|
||
|
private function stageRequirements(): array {
|
||
|
$table = (new CTable())
|
||
|
->addClass(ZBX_STYLE_LIST_TABLE)
|
||
|
->setHeader(['', _('Current value'), _('Required'), '']);
|
||
|
|
||
|
$messages = [];
|
||
|
$finalResult = CFrontendSetup::CHECK_OK;
|
||
|
|
||
|
foreach ($this->frontend_setup->checkRequirements() as $req) {
|
||
|
if ($req['result'] == CFrontendSetup::CHECK_OK) {
|
||
|
$class = ZBX_STYLE_GREEN;
|
||
|
$result = 'OK';
|
||
|
}
|
||
|
elseif ($req['result'] == CFrontendSetup::CHECK_WARNING) {
|
||
|
$class = ZBX_STYLE_ORANGE;
|
||
|
$result = new CSpan(_x('Warning', 'setup'));
|
||
|
}
|
||
|
else {
|
||
|
$class = ZBX_STYLE_RED;
|
||
|
$result = new CSpan(_('Fail'));
|
||
|
$messages[] = ['type' => 'error', 'message' => $req['error']];
|
||
|
}
|
||
|
|
||
|
$table->addRow(
|
||
|
[
|
||
|
$req['name'],
|
||
|
$req['current'],
|
||
|
($req['required'] !== null) ? $req['required'] : '',
|
||
|
(new CCol($result))->addClass($class)
|
||
|
]
|
||
|
);
|
||
|
|
||
|
if ($req['result'] > $finalResult) {
|
||
|
$finalResult = $req['result'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($finalResult == CFrontendSetup::CHECK_FATAL) {
|
||
|
$message_box = makeMessageBox(ZBX_STYLE_MSG_BAD, $messages, null, false, true);
|
||
|
}
|
||
|
else {
|
||
|
$message_box = null;
|
||
|
}
|
||
|
|
||
|
return [
|
||
|
new CTag('h1', true, _('Check of pre-requisites')),
|
||
|
(new CDiv([$message_box, $table]))->addClass(ZBX_STYLE_SETUP_RIGHT_BODY)
|
||
|
];
|
||
|
}
|
||
|
|
||
|
private function stageDbConnection(): array {
|
||
|
$DB['TYPE'] = $this->getConfig('DB_TYPE', key(CFrontendSetup::getSupportedDatabases()));
|
||
|
$db_warning = _('Support for Oracle DB is deprecated since Zabbix 7.0 and will be removed in future versions.');
|
||
|
|
||
|
$table = (new CFormList())
|
||
|
->addItem([
|
||
|
(new CVar('tls_encryption', 0))->removeId(),
|
||
|
(new CVar('verify_certificate', 0))->removeId(),
|
||
|
(new CVar('verify_host', 0))->removeId()
|
||
|
])
|
||
|
->addRow(new CLabel(_('Database type'), 'label-type'), [
|
||
|
(new CSelect('type'))
|
||
|
->setId('type')
|
||
|
->setFocusableElementId('label-type')
|
||
|
->setValue($DB['TYPE'])
|
||
|
->addOptions(CSelect::createOptionsFromArray(CFrontendSetup::getSupportedDatabases())),
|
||
|
makeWarningIcon($db_warning)->setId('db_warning')
|
||
|
])
|
||
|
->addRow(_('Database host'),
|
||
|
(new CTextBox('server', $this->getConfig('DB_SERVER', 'localhost')))
|
||
|
->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
|
||
|
)
|
||
|
->addRow(_('Database port'), [
|
||
|
(new CNumericBox('port', $this->getConfig('DB_PORT', '0'), 5, false, false, false))
|
||
|
->setWidth(ZBX_TEXTAREA_SMALL_WIDTH),
|
||
|
(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
|
||
|
(new CSpan(_('0 - use default port')))->addClass(ZBX_STYLE_GREY)
|
||
|
])
|
||
|
->addRow(_('Database name'),
|
||
|
(new CTextBox('database', $this->getConfig('DB_DATABASE', 'zabbix')))
|
||
|
->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
|
||
|
)
|
||
|
->addRow(_('Database schema'),
|
||
|
(new CTextBox('schema', $this->getConfig('DB_SCHEMA', '')))
|
||
|
->setWidth(ZBX_TEXTAREA_SMALL_WIDTH),
|
||
|
'db_schema_row',
|
||
|
ZBX_STYLE_DISPLAY_NONE
|
||
|
);
|
||
|
|
||
|
$db_creds_storage = (int) $this->getConfig('DB_CREDS_STORAGE', DB_STORE_CREDS_CONFIG);
|
||
|
|
||
|
$table
|
||
|
->addRow(_('Store credentials in'),
|
||
|
(new CRadioButtonList('creds_storage', $db_creds_storage))
|
||
|
->addValue(_('Plain text'), DB_STORE_CREDS_CONFIG)
|
||
|
->addValue(_('HashiCorp Vault'), DB_STORE_CREDS_VAULT_HASHICORP)
|
||
|
->addValue(_('CyberArk Vault'), DB_STORE_CREDS_VAULT_CYBERARK)
|
||
|
->setModern(true)
|
||
|
)
|
||
|
// Plaintext.
|
||
|
->addRow(_('User'),
|
||
|
(new CTextBox('user', $this->getConfig('DB_USER', 'zabbix')))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH),
|
||
|
'db_user',
|
||
|
($db_creds_storage != DB_STORE_CREDS_CONFIG) ? ZBX_STYLE_DISPLAY_NONE : null
|
||
|
)
|
||
|
->addRow(_('Password'),
|
||
|
(new CPassBox('password', $this->getConfig('DB_PASSWORD')))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH),
|
||
|
'db_password',
|
||
|
($db_creds_storage != DB_STORE_CREDS_CONFIG) ? ZBX_STYLE_DISPLAY_NONE : null
|
||
|
)
|
||
|
// Vault common.
|
||
|
->addRow(
|
||
|
(new CLabel(_('Vault API endpoint')))->setAsteriskMark(),
|
||
|
(new CTextBox('vault_url',
|
||
|
$this->getConfig('DB_VAULT_URL', $db_creds_storage == DB_STORE_CREDS_VAULT_HASHICORP
|
||
|
? CVaultHashiCorp::API_ENDPOINT_DEFAULT
|
||
|
: CVaultCyberArk::API_ENDPOINT_DEFAULT
|
||
|
)
|
||
|
))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH),
|
||
|
'vault_url_row',
|
||
|
!in_array($db_creds_storage, [DB_STORE_CREDS_VAULT_HASHICORP, DB_STORE_CREDS_VAULT_CYBERARK])
|
||
|
? ZBX_STYLE_DISPLAY_NONE
|
||
|
: null
|
||
|
)
|
||
|
// HashiCorp Vault - related fields.
|
||
|
->addRow(
|
||
|
_('Vault secret path'),
|
||
|
(new CTextBox('vault_db_path', $this->getConfig('DB_VAULT_DB_PATH')))
|
||
|
->setAttribute('placeholder', CVaultHashiCorp::DB_PATH_PLACEHOLDER)
|
||
|
->setWidth(ZBX_TEXTAREA_SMALL_WIDTH),
|
||
|
'vault_db_path_row',
|
||
|
($db_creds_storage != DB_STORE_CREDS_VAULT_HASHICORP) ? ZBX_STYLE_DISPLAY_NONE : null
|
||
|
)
|
||
|
->addRow(_('Vault authentication token'),
|
||
|
(new CTextBox('vault_token', $this->getConfig('DB_VAULT_TOKEN')))
|
||
|
->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
|
||
|
->setAttribute('maxlength', 2048),
|
||
|
'vault_token_row',
|
||
|
($db_creds_storage != DB_STORE_CREDS_VAULT_HASHICORP) ? ZBX_STYLE_DISPLAY_NONE : null
|
||
|
)
|
||
|
// CyberArk Vault - related fields.
|
||
|
->addRow(
|
||
|
(new CLabel(_('Vault secret query string')))->setAsteriskMark(),
|
||
|
(new CTextBox('vault_query_string', $this->getConfig('DB_VAULT_DB_PATH')))
|
||
|
->setAttribute('placeholder', CVaultCyberArk::DB_PATH_PLACEHOLDER)
|
||
|
->setAttribute('maxlength', 2048)
|
||
|
->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH),
|
||
|
'vault_query_string_row',
|
||
|
($db_creds_storage != DB_STORE_CREDS_VAULT_CYBERARK) ? ZBX_STYLE_DISPLAY_NONE : null
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CLabel(_('Vault certificates'), 'vault_certificates_toggle')),
|
||
|
(new CCheckBox('vault_certificates'))
|
||
|
->setId('vault_certificates_toggle')
|
||
|
->setChecked($this->getConfig('DB_VAULT_CERTIFICATES', false)),
|
||
|
'vault_certificates',
|
||
|
($db_creds_storage != DB_STORE_CREDS_VAULT_CYBERARK) ? ZBX_STYLE_DISPLAY_NONE : null
|
||
|
)
|
||
|
->addRow(_('SSL certificate file'),
|
||
|
(new CTextBox('vault_cert_file', $this->getConfig('VAULT_CERT_FILE', 'conf/certs/cyberark-cert.pem')))
|
||
|
->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH)
|
||
|
->setAttribute('maxlength', 2048),
|
||
|
'vault_cert_file',
|
||
|
($db_creds_storage != DB_STORE_CREDS_VAULT_CYBERARK || !$this->getConfig('DB_VAULT_CERTIFICATES', false))
|
||
|
? ZBX_STYLE_DISPLAY_NONE
|
||
|
: null
|
||
|
)
|
||
|
->addRow(_('SSL key file'),
|
||
|
(new CTextBox('vault_key_file', $this->getConfig('VAULT_KEY_FILE', 'conf/certs/cyberark-key.pem')))
|
||
|
->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH)
|
||
|
->setAttribute('maxlength', 2048),
|
||
|
'vault_key_file',
|
||
|
($db_creds_storage != DB_STORE_CREDS_VAULT_CYBERARK || !$this->getConfig('DB_VAULT_CERTIFICATES', false))
|
||
|
? ZBX_STYLE_DISPLAY_NONE
|
||
|
: null
|
||
|
);
|
||
|
|
||
|
$table
|
||
|
->addRow(_('Database TLS encryption'),
|
||
|
[
|
||
|
(new CCheckBox('tls_encryption'))->setChecked($this->getConfig('DB_ENCRYPTION', true)),
|
||
|
(new CDiv(
|
||
|
_('Connection will not be encrypted because it uses a socket file (on Unix) or shared memory (Windows).')
|
||
|
))
|
||
|
->setId('tls_encryption_hint')
|
||
|
->addClass(ZBX_STYLE_DISPLAY_NONE)
|
||
|
],
|
||
|
'db_encryption_row',
|
||
|
ZBX_STYLE_DISPLAY_NONE
|
||
|
)
|
||
|
->addRow(_('Verify database certificate'),
|
||
|
(new CCheckBox('verify_certificate'))->setChecked($this->getConfig('DB_ENCRYPTION_ADVANCED')),
|
||
|
'db_verify_host',
|
||
|
ZBX_STYLE_DISPLAY_NONE
|
||
|
)
|
||
|
->addRow((new CLabel(_('Database TLS CA file')))->setAsteriskMark(),
|
||
|
(new CTextBox('ca_file', $this->getConfig('DB_CA_FILE')))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH),
|
||
|
'db_cafile_row',
|
||
|
ZBX_STYLE_DISPLAY_NONE
|
||
|
)
|
||
|
->addRow(_('Database TLS key file'),
|
||
|
(new CTextBox('key_file', $this->getConfig('DB_KEY_FILE')))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH),
|
||
|
'db_keyfile_row',
|
||
|
ZBX_STYLE_DISPLAY_NONE
|
||
|
)
|
||
|
->addRow(_('Database TLS certificate file'),
|
||
|
(new CTextBox('cert_file', $this->getConfig('DB_CERT_FILE')))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH),
|
||
|
'db_certfile_row',
|
||
|
ZBX_STYLE_DISPLAY_NONE
|
||
|
)
|
||
|
->addRow(_('Database host verification'),
|
||
|
(new CCheckBox('verify_host'))->setChecked($this->getConfig('DB_VERIFY_HOST')),
|
||
|
'db_verify_host_row',
|
||
|
ZBX_STYLE_DISPLAY_NONE
|
||
|
)
|
||
|
->addRow(_('Database TLS cipher list'),
|
||
|
(new CTextBox('cipher_list', $this->getConfig('DB_CIPHER_LIST')))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH),
|
||
|
'db_cipher_row',
|
||
|
ZBX_STYLE_DISPLAY_NONE
|
||
|
);
|
||
|
|
||
|
if ($this->step_failed) {
|
||
|
$message_box = makeMessageBox(ZBX_STYLE_MSG_BAD, CMessageHelper::getMessages(),
|
||
|
_('Cannot connect to the database.'), false, true
|
||
|
);
|
||
|
}
|
||
|
else {
|
||
|
$message_box = null;
|
||
|
}
|
||
|
|
||
|
return [
|
||
|
new CTag('h1', true, _('Configure DB connection')),
|
||
|
(new CDiv([
|
||
|
new CTag('p', true, _s('Please create database manually, and set the configuration parameters for connection to this database. Press "%1$s" button when done.', _('Next step'))),
|
||
|
$message_box,
|
||
|
$table
|
||
|
]))->addClass(ZBX_STYLE_SETUP_RIGHT_BODY)
|
||
|
];
|
||
|
}
|
||
|
|
||
|
private function stageSettings(): array {
|
||
|
$timezones[ZBX_DEFAULT_TIMEZONE] = CTimezoneHelper::getTitle(CTimezoneHelper::getSystemTimezone(), _('System'));
|
||
|
$timezones += CTimezoneHelper::getList();
|
||
|
|
||
|
$table = (new CFormList())
|
||
|
->addRow(
|
||
|
_('Zabbix server name'),
|
||
|
(new CTextBox('zbx_server_name', $this->getConfig('ZBX_SERVER_NAME', '')))
|
||
|
->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
|
||
|
)
|
||
|
->addRow(
|
||
|
new CLabel(_('Default time zone'), 'label-default-timezone'),
|
||
|
(new CSelect('default_timezone'))
|
||
|
->setValue($this->getConfig('default_timezone', ZBX_DEFAULT_TIMEZONE))
|
||
|
->addOptions(CSelect::createOptionsFromArray($timezones))
|
||
|
->setFocusableElementId('label-default-timezone')
|
||
|
->setAttribute('autofocus', 'autofocus')
|
||
|
)
|
||
|
->addRow(new CLabel(_('Default theme'), 'label-default-theme'),
|
||
|
(new CSelect('default_theme'))
|
||
|
->setId('default-theme')
|
||
|
->setFocusableElementId('label-default-theme')
|
||
|
->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
|
||
|
->setValue($this->getConfig('default_theme'))
|
||
|
->addOptions(CSelect::createOptionsFromArray(APP::getThemes()))
|
||
|
);
|
||
|
|
||
|
return [
|
||
|
new CTag('h1', true, _('Settings')),
|
||
|
(new CDiv($table))->addClass(ZBX_STYLE_SETUP_RIGHT_BODY)
|
||
|
];
|
||
|
}
|
||
|
|
||
|
private function stageSummary(): array {
|
||
|
$db_type = $this->getConfig('DB_TYPE');
|
||
|
$databases = CFrontendSetup::getSupportedDatabases();
|
||
|
|
||
|
$table = (new CFormList())
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database type')))->addClass(ZBX_STYLE_GREY),
|
||
|
$databases[$db_type]
|
||
|
);
|
||
|
|
||
|
$db_port = ($this->getConfig('DB_PORT') == 0) ? _('default') : $this->getConfig('DB_PORT');
|
||
|
|
||
|
if ($this->getConfig('DB_CREDS_STORAGE', DB_STORE_CREDS_CONFIG) == DB_STORE_CREDS_CONFIG) {
|
||
|
$db_password = preg_replace('/./', '*', $this->getConfig('DB_PASSWORD'));
|
||
|
$db_username = $this->getConfig('DB_USER');
|
||
|
}
|
||
|
else {
|
||
|
$db_password = _('Stored in Vault secret');
|
||
|
$db_username = _('Stored in Vault secret');
|
||
|
}
|
||
|
|
||
|
$table
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database server')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_SERVER')
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database port')))->addClass(ZBX_STYLE_GREY),
|
||
|
$db_port
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database name')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_DATABASE')
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database user')))->addClass(ZBX_STYLE_GREY),
|
||
|
$db_username
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database password')))->addClass(ZBX_STYLE_GREY),
|
||
|
$db_password
|
||
|
);
|
||
|
|
||
|
if ($db_type === ZBX_DB_POSTGRESQL) {
|
||
|
$table->addRow(
|
||
|
(new CSpan(_('Database schema')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_SCHEMA')
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ($this->getConfig('DB_CREDS_STORAGE', DB_STORE_CREDS_CONFIG) == DB_STORE_CREDS_VAULT_HASHICORP) {
|
||
|
$table
|
||
|
->addRow(
|
||
|
(new CSpan(_('Vault API endpoint')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_VAULT_URL')
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Vault secret path')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_VAULT_DB_PATH')
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Vault authentication token')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_VAULT_TOKEN')
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ($this->getConfig('DB_CREDS_STORAGE', DB_STORE_CREDS_CONFIG) == DB_STORE_CREDS_VAULT_CYBERARK) {
|
||
|
$table
|
||
|
->addRow(
|
||
|
(new CSpan(_('Vault API endpoint')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_VAULT_URL')
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Vault secret query string')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_VAULT_DB_PATH')
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Vault certificates')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_VAULT_CERTIFICATES') ? 'true' : 'false'
|
||
|
);
|
||
|
|
||
|
if ($this->getConfig('DB_VAULT_CERTIFICATES')) {
|
||
|
$table
|
||
|
->addRow(
|
||
|
(new CSpan(_('SSL certificate file')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('VAULT_CERT_FILE') ? $this->getConfig('VAULT_CERT_FILE') : ''
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('SSL key file')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('VAULT_KEY_FILE') ? $this->getConfig('VAULT_KEY_FILE') : ''
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$table->addRow(
|
||
|
(new CSpan(_('Database TLS encryption')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_ENCRYPTION') ? 'true' : 'false'
|
||
|
);
|
||
|
|
||
|
if ($this->getConfig('DB_ENCRYPTION_ADVANCED')) {
|
||
|
$table
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database TLS CA file')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_CA_FILE')
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database TLS key file')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_KEY_FILE')
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database TLS certificate file')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_CERT_FILE')
|
||
|
)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Database host verification')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_VERIFY_HOST') ? 'true' : 'false'
|
||
|
);
|
||
|
|
||
|
if ($db_type === ZBX_DB_MYSQL) {
|
||
|
$table->addRow(
|
||
|
(new CSpan(_('Database TLS cipher list')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('DB_CIPHER_LIST')
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$server_name = $this->getConfig('ZBX_SERVER_NAME');
|
||
|
|
||
|
if ($server_name !== '') {
|
||
|
$table
|
||
|
->addRow(null)
|
||
|
->addRow(
|
||
|
(new CSpan(_('Zabbix server name')))->addClass(ZBX_STYLE_GREY),
|
||
|
$this->getConfig('ZBX_SERVER_NAME')
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return [
|
||
|
new CTag('h1', true, _('Pre-installation summary')),
|
||
|
(new CDiv([
|
||
|
new CTag('p', true, _s('Please check configuration parameters. If all is correct, press "%1$s" button, or "%2$s" button to change configuration parameters.', _('Next step'), _('Back'))),
|
||
|
$table
|
||
|
]))->addClass(ZBX_STYLE_SETUP_RIGHT_BODY)
|
||
|
];
|
||
|
}
|
||
|
|
||
|
private function stageInstall(): array {
|
||
|
/*
|
||
|
* Having non-super-admin authenticated at this step means:
|
||
|
* - Either the config file has been manually created by the user.
|
||
|
* - Or dealing with a spoofed session cookie.
|
||
|
*
|
||
|
* Since it is not possible to distinguish between the two, it's also impossible to validate the config file
|
||
|
* and display any discrepancies with the configuration stored within the session.
|
||
|
*/
|
||
|
if (CWebUser::$data && CWebUser::getType() < USER_TYPE_SUPER_ADMIN) {
|
||
|
CSessionHelper::clear();
|
||
|
|
||
|
return $this->stageInstalled();
|
||
|
}
|
||
|
|
||
|
$vault_config = [
|
||
|
'VAULT' => '',
|
||
|
'VAULT_URL' => '',
|
||
|
'VAULT_DB_PATH' => '',
|
||
|
'VAULT_TOKEN' => '',
|
||
|
'VAULT_CERT_FILE' => '',
|
||
|
'VAULT_KEY_FILE' => ''
|
||
|
];
|
||
|
|
||
|
$db_creds_config = [
|
||
|
'USER' => '',
|
||
|
'PASSWORD' => ''
|
||
|
];
|
||
|
|
||
|
$db_user = null;
|
||
|
$db_password = null;
|
||
|
|
||
|
if ($this->getConfig('DB_CREDS_STORAGE', DB_STORE_CREDS_CONFIG) == DB_STORE_CREDS_VAULT_HASHICORP) {
|
||
|
$vault_config['VAULT'] = CVaultHashiCorp::NAME;
|
||
|
$vault_config['VAULT_URL'] = $this->getConfig('DB_VAULT_URL');
|
||
|
$vault_config['VAULT_DB_PATH'] = $this->getConfig('DB_VAULT_DB_PATH');
|
||
|
$vault_config['VAULT_TOKEN'] = $this->getConfig('DB_VAULT_TOKEN');
|
||
|
|
||
|
$vault_provider = new CVaultHashiCorp($vault_config['VAULT_URL'], $vault_config['VAULT_DB_PATH'],
|
||
|
$vault_config['VAULT_TOKEN']
|
||
|
);
|
||
|
|
||
|
$db_credentials = $vault_provider->getCredentials();
|
||
|
|
||
|
if ($db_credentials === null) {
|
||
|
$this->step_failed = true;
|
||
|
$this->setConfig('step', self::STAGE_DB_CONNECTION);
|
||
|
return $this->stageDbConnection();
|
||
|
}
|
||
|
|
||
|
$db_user = $db_credentials['user'];
|
||
|
$db_password = $db_credentials['password'];
|
||
|
}
|
||
|
elseif ($this->getConfig('DB_CREDS_STORAGE', DB_STORE_CREDS_CONFIG) == DB_STORE_CREDS_VAULT_CYBERARK) {
|
||
|
$vault_config['VAULT'] = CVaultCyberArk::NAME;
|
||
|
$vault_config['VAULT_URL'] = $this->getConfig('DB_VAULT_URL');
|
||
|
$vault_config['VAULT_DB_PATH'] = $this->getConfig('DB_VAULT_DB_PATH');
|
||
|
$vault_config['VAULT_CERT_FILE'] = $this->getConfig('DB_VAULT_CERT_FILE');
|
||
|
$vault_config['VAULT_KEY_FILE'] = $this->getConfig('DB_VAULT_KEY_FILE');
|
||
|
|
||
|
$vault_provider = new CVaultCyberArk($vault_config['VAULT_URL'], $vault_config['VAULT_DB_PATH'],
|
||
|
$vault_config['VAULT_CERT_FILE'], $vault_config['VAULT_KEY_FILE']);
|
||
|
|
||
|
$db_credentials = $vault_provider->getCredentials();
|
||
|
|
||
|
if ($db_credentials === null) {
|
||
|
$this->step_failed = true;
|
||
|
$this->setConfig('step', self::STAGE_DB_CONNECTION);
|
||
|
return $this->stageDbConnection();
|
||
|
}
|
||
|
|
||
|
$db_user = $db_credentials['user'];
|
||
|
$db_password = $db_credentials['password'];
|
||
|
}
|
||
|
else {
|
||
|
$db_creds_config['USER'] = $this->getConfig('DB_USER');
|
||
|
$db_creds_config['PASSWORD'] = $this->getConfig('DB_PASSWORD');
|
||
|
}
|
||
|
|
||
|
$this->dbConnect($db_user, $db_password);
|
||
|
|
||
|
$update = [];
|
||
|
foreach (['default_lang', 'default_timezone', 'default_theme'] as $key) {
|
||
|
$update[] = $key.'='.zbx_dbstr($this->getConfig($key));
|
||
|
}
|
||
|
DBexecute('UPDATE config SET '.implode(',', $update));
|
||
|
$this->dbClose();
|
||
|
|
||
|
$this->setConfig('ZBX_CONFIG_FILE_CORRECT', true);
|
||
|
|
||
|
$config_file_name = APP::getRootDir().CConfigFile::CONFIG_FILE_PATH;
|
||
|
$config = new CConfigFile($config_file_name);
|
||
|
$config->config = [
|
||
|
'DB' => [
|
||
|
'TYPE' => $this->getConfig('DB_TYPE'),
|
||
|
'SERVER' => $this->getConfig('DB_SERVER'),
|
||
|
'PORT' => $this->getConfig('DB_PORT'),
|
||
|
'DATABASE' => $this->getConfig('DB_DATABASE'),
|
||
|
'SCHEMA' => $this->getConfig('DB_SCHEMA'),
|
||
|
'ENCRYPTION' => $this->getConfig('DB_ENCRYPTION'),
|
||
|
'KEY_FILE' => $this->getConfig('DB_KEY_FILE'),
|
||
|
'CERT_FILE' => $this->getConfig('DB_CERT_FILE'),
|
||
|
'CA_FILE' => $this->getConfig('DB_CA_FILE'),
|
||
|
'VERIFY_HOST' => $this->getConfig('DB_VERIFY_HOST'),
|
||
|
'CIPHER_LIST' => $this->getConfig('DB_CIPHER_LIST')
|
||
|
] + $db_creds_config + $vault_config,
|
||
|
'ZBX_SERVER_NAME' => $this->getConfig('ZBX_SERVER_NAME')
|
||
|
];
|
||
|
|
||
|
$error = false;
|
||
|
|
||
|
/*
|
||
|
* Create session secret key for first installation. If installation already exists, don't make a new key
|
||
|
* because that will terminate the existing session.
|
||
|
*/
|
||
|
$db_connected = $this->dbConnect($db_user, $db_password);
|
||
|
$is_superadmin = (CWebUser::$data && CWebUser::getType() == USER_TYPE_SUPER_ADMIN);
|
||
|
|
||
|
$session_key_update_failed = $db_connected && !$is_superadmin
|
||
|
? !CEncryptHelper::updateKey(CEncryptHelper::generateKey())
|
||
|
: false;
|
||
|
|
||
|
if (!$db_connected || $session_key_update_failed) {
|
||
|
$this->step_failed = true;
|
||
|
$this->setConfig('step', self::STAGE_DB_CONNECTION);
|
||
|
|
||
|
return $this->stageDbConnection();
|
||
|
}
|
||
|
|
||
|
$this->dbClose();
|
||
|
|
||
|
$messages = [];
|
||
|
|
||
|
if (!$config->save()) {
|
||
|
$error = true;
|
||
|
$messages[] = [
|
||
|
'type' => 'error',
|
||
|
'message' => $config->error
|
||
|
];
|
||
|
}
|
||
|
|
||
|
if ($error) {
|
||
|
$this->show_retry_button = true;
|
||
|
|
||
|
$this->setConfig('ZBX_CONFIG_FILE_CORRECT', false);
|
||
|
|
||
|
$message_box = makeMessageBox(ZBX_STYLE_MSG_BAD, $messages, _('Cannot create the configuration file.'),
|
||
|
false, true
|
||
|
);
|
||
|
$message = [
|
||
|
new CTag('p', true, _('Alternatively, you can install it manually:')),
|
||
|
new CTag('ol', true, [
|
||
|
new CTag('li', true, new CLink(_('Download the configuration file'), 'setup.php?save_config=1')),
|
||
|
new CTag('li', true, _s('Save it as "%1$s"', $config_file_name))
|
||
|
])
|
||
|
];
|
||
|
|
||
|
return [
|
||
|
new CTag('h1', true, _('Install')),
|
||
|
(new CDiv([$message_box, $message]))->addClass(ZBX_STYLE_SETUP_RIGHT_BODY)
|
||
|
];
|
||
|
}
|
||
|
|
||
|
// Clear session after success install.
|
||
|
CSessionHelper::clear();
|
||
|
|
||
|
return $this->stageInstalled();
|
||
|
}
|
||
|
|
||
|
private function stageInstalled() {
|
||
|
$this->disable_cancel_button = true;
|
||
|
$this->disable_back_button = true;
|
||
|
|
||
|
$message_box = null;
|
||
|
$message = [
|
||
|
(new CTag('h1', true, _('Congratulations! You have successfully installed Zabbix frontend.')))
|
||
|
->addClass(ZBX_STYLE_GREEN),
|
||
|
new CTag('p', true, _s('Configuration file "%1$s" created.', ltrim(CConfigFile::CONFIG_FILE_PATH, '/')))
|
||
|
];
|
||
|
|
||
|
return [
|
||
|
new CTag('h1', true, _('Install')),
|
||
|
(new CDiv([$message_box, $message]))->addClass(ZBX_STYLE_SETUP_RIGHT_BODY)
|
||
|
];
|
||
|
}
|
||
|
|
||
|
private function getConfig($name, $default = null) {
|
||
|
return CSessionHelper::has($name) ? CSessionHelper::get($name) : $default;
|
||
|
}
|
||
|
|
||
|
private function setConfig($name, $value): void {
|
||
|
CSessionHelper::set($name, $value);
|
||
|
}
|
||
|
|
||
|
private function unsetConfig(array $keys): void {
|
||
|
CSessionHelper::unset($keys);
|
||
|
}
|
||
|
|
||
|
private function getList(): CList {
|
||
|
$list = new CList();
|
||
|
|
||
|
foreach ($this->stages as $id => $data) {
|
||
|
$list->addItem($data['title'], ($id <= $this->getStep()) ? ZBX_STYLE_SETUP_LEFT_CURRENT : null);
|
||
|
}
|
||
|
|
||
|
return $list;
|
||
|
}
|
||
|
|
||
|
private function dbConnect(string $username = null, string $password = null) {
|
||
|
global $DB;
|
||
|
|
||
|
if (!$this->getConfig('check_fields_result')) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$DB['TYPE'] = $this->getConfig('DB_TYPE');
|
||
|
if ($DB['TYPE'] === null) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$DB['SERVER'] = $this->getConfig('DB_SERVER', 'localhost');
|
||
|
$DB['PORT'] = $this->getConfig('DB_PORT', '0');
|
||
|
$DB['DATABASE'] = $this->getConfig('DB_DATABASE', 'zabbix');
|
||
|
$DB['USER'] = $username ?? $this->getConfig('DB_USER', 'root');
|
||
|
$DB['PASSWORD'] = $password ?? $this->getConfig('DB_PASSWORD', '');
|
||
|
$DB['SCHEMA'] = $this->getConfig('DB_SCHEMA', '');
|
||
|
$DB['ENCRYPTION'] = (bool) $this->getConfig('DB_ENCRYPTION', true);
|
||
|
$DB['VERIFY_HOST'] = (bool) $this->getConfig('DB_VERIFY_HOST', true);
|
||
|
$DB['KEY_FILE'] = $this->getConfig('DB_KEY_FILE', '');
|
||
|
$DB['CERT_FILE'] = $this->getConfig('DB_CERT_FILE', '');
|
||
|
$DB['CA_FILE'] = $this->getConfig('DB_CA_FILE', '');
|
||
|
$DB['CIPHER_LIST'] = $this->getConfig('DB_CIPHER_LIST', '');
|
||
|
|
||
|
$error = '';
|
||
|
|
||
|
// Check certificate files exists.
|
||
|
if ($DB['ENCRYPTION'] && ($DB['TYPE'] === ZBX_DB_MYSQL || $DB['TYPE'] === ZBX_DB_POSTGRESQL)) {
|
||
|
if (($this->getConfig('DB_ENCRYPTION_ADVANCED') || $DB['CA_FILE'] !== '') && !file_exists($DB['CA_FILE'])) {
|
||
|
error(_s('Incorrect file path for "%1$s": %2$s.', _('Database TLS CA file'), $DB['CA_FILE']));
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ($DB['KEY_FILE'] !== '' && !file_exists($DB['KEY_FILE'])) {
|
||
|
error(_s('Incorrect file path for "%1$s": %2$s.', _('Database TLS key file'), $DB['KEY_FILE']));
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ($DB['CERT_FILE'] !== '' && !file_exists($DB['CERT_FILE'])) {
|
||
|
error(_s('Incorrect file path for "%1$s": %2$s.', _('Database TLS certificate file'),
|
||
|
$DB['CERT_FILE']));
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!DBconnect($error)) {
|
||
|
error($error);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private function dbClose(): void {
|
||
|
global $DB;
|
||
|
|
||
|
DBclose();
|
||
|
|
||
|
$DB = null;
|
||
|
}
|
||
|
|
||
|
private function checkConnection() {
|
||
|
global $DB;
|
||
|
|
||
|
$result = true;
|
||
|
|
||
|
if ($DB['TYPE'] === ZBX_DB_POSTGRESQL && $DB['SCHEMA'] !== '') {
|
||
|
$db_schema = DBselect(
|
||
|
'SELECT NULL'.
|
||
|
' FROM information_schema.schemata'.
|
||
|
' WHERE schema_name='.zbx_dbstr($DB['SCHEMA'])
|
||
|
);
|
||
|
$result = (bool) DBfetch($db_schema);
|
||
|
}
|
||
|
|
||
|
$db = DB::getDbBackend();
|
||
|
|
||
|
if (!$db->checkEncoding()) {
|
||
|
error($db->getWarning());
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
}
|