<?php /* ** Zabbix ** Copyright (C) 2001-2022 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. **/ require_once dirname(__FILE__).'/../include/CLegacyWebTest.php'; /** * @onBefore removeGuestFromDisabledGroup * @onAfter addGuestToDisabledGroup */ class testFormAdministrationAuthenticationHttp extends CLegacyWebTest { const LOGIN_GUEST = 1; const LOGIN_USER = 2; const LOGIN_HTTP = 3; public function getHttpData() { return [ // HTTP authentication disabled, default zabbix login form. [ [ 'user' => 'Admin', 'password' => 'zabbix', 'pages' => [ [ 'page' => 'zabbix.php?action=dashboard.view', 'action' => self::LOGIN_GUEST, 'target' => 'Global view' ], [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], [ 'page' => 'index.php', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], // Redirect to default zabbix login form, if open HTTP login form. [ 'page' => 'index_http.php', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], // Couldn't open GUI page due access. [ 'page' => 'zabbix.php?action=gui.edit', 'error' => 'Access denied' ], // Login after logout. [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ] ], 'db_check' => [ 'http_auth_enabled' => '0', 'http_login_form' => '0', 'http_strip_domains' => '', 'http_case_sensitive' => '1' ] ] ], // HTTP authentication enabled, but file isn't created. [ [ 'user' => 'Admin', 'password' => 'zabbix', 'http_authentication' => [ 'Enable HTTP authentication' => true ], 'pages' => [ [ 'page' => 'zabbix.php?action=dashboard.view', 'action' => self::LOGIN_GUEST, 'target' => 'Global view' ], [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], [ 'page' => 'index.php', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], // Redirect to default zabbix login form, if open HTTP login form. [ 'page' => 'index_http.php', 'error' => 'You are not logged in' ], // Couldn't open GUI page due access. [ 'page' => 'zabbix.php?action=gui.edit', 'error' => 'Access denied' ], // Login after logout. [ 'page' => 'index.php?reconnect=1&form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ] ], 'db_check' => [ 'http_auth_enabled' => '1', 'http_login_form' => '0', 'http_strip_domains' => '', 'http_case_sensitive' => '1' ] ] ], // HTTP authentication enabled (default login form is set to 'Zabbix login form'). [ [ 'user' => 'Admin', 'password' => '123456', 'db_password' => 'zabbix', 'file' => 'pwfile', 'http_authentication' => [ 'Enable HTTP authentication' => true, 'Default login form' => 'Zabbix login form' ], 'pages' => [ [ 'page' => 'zabbix.php?action=dashboard.view', 'action' => self::LOGIN_GUEST, 'target' => 'Global view' ], // No redirect - sign in through default zabbix login form. [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], // No redirect - sign in through default zabbix login form. [ 'page' => 'index.php', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], // Redirect to HTTP login form and user is signed on Dashboard page. [ 'page' => 'index_http.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], // Sign in through zabbix login form after logout. [ 'page' => 'index.php?reconnect=1&form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], // Couldn't open Hosts page due access. [ 'page' => 'hosts.php', 'error' => 'Access denied' ], // Couldn't open GUI page due access. [ 'page' => 'zabbix.php?action=gui.edit', 'error' => 'Access denied' ] ], 'db_check' => [ 'http_auth_enabled' => '1', 'http_login_form' => '0', 'http_strip_domains' => '', 'http_case_sensitive' => '1' ] ] ], // HTTP authentication enabled (default login form is set to 'HTTP login form'). [ [ 'user' => 'Admin', 'password' => '123456', 'db_password' => 'zabbix', 'file' => 'pwfile', 'http_authentication' => [ 'Enable HTTP authentication' => true, 'Default login form' => 'HTTP login form' ], 'pages' => [ // No redirect - default zabbix login form. [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], // // wait for ZBX-14774. // // Redirect to HTTP login form and user is signed on hosts page. // [ // 'page' => 'hosts.php', // 'action' => self::LOGIN_HTTP, // 'target' => 'Hosts' // ], // Redirect to HTTP login form and user is signed on dashboard page. [ 'page' => 'index.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], // Redirect to dashboard page and user is signed. [ 'page' => 'index_http.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], // Sign in through zabbix login form after logout. [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], // Redirect to HTTP login form and user is signed on GUI page. [ 'page' => 'zabbix.php?action=gui.edit', 'action' => self::LOGIN_HTTP, 'target' => 'GUI' ] ], 'db_check' => [ 'http_auth_enabled' => '1', 'http_login_form' => '1', 'http_strip_domains' => '', 'http_case_sensitive' => '1' ] ] ], // HTTP authentication - Check domain (@local.com). [ [ 'user' => 'Admin@local.com', 'password' => '123456', 'file' => 'htaccess', 'db_password' => 'zabbix', 'http_authentication' => [ 'Enable HTTP authentication' => true, 'Default login form' => 'HTTP login form', 'Remove domain name' => 'local.com' ], 'pages' => [ [ 'page' => 'zabbix.php?action=dashboard.view', 'action' => self::LOGIN_GUEST, 'target' => 'Global view' ], [ 'page' => 'index.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], [ 'page' => 'index_http.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ] ], 'db_check' => [ 'http_auth_enabled' => '1', 'http_login_form' => '1', 'http_strip_domains' => 'local.com', 'http_case_sensitive' => '1' ] ] ], // HTTP authentication - Login with user http-auth-admin (Zabbix Admin). [ [ 'user' => 'local.com\\http-auth-admin', 'password' => 'zabbix', 'file' => 'htaccess', 'http_authentication' => [ 'Enable HTTP authentication' => true, 'Default login form' => 'HTTP login form', 'Remove domain name' => 'local.com' ], 'pages' => [ [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], [ 'page' => 'zabbix.php?action=dashboard.view', 'action' => self::LOGIN_GUEST, 'target' => 'Global view' ], [ 'page' => 'zabbix.php?action=user.list', 'error' => 'Access denied' ], // // Redirect to HTTP login form and user is signed on hosts page. // // wait for ZBX-14774. // [ // 'page' => 'hosts.php', // 'action' => self::LOGIN_HTTP, // 'target' => 'Hosts' // ], // Redirect to HTTP login form and user is signed on dashboard page. [ 'page' => 'index.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], // Redirect to dashboard page and user is signed. [ 'page' => 'index_http.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], // Login after logout. [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ] ], 'db_check' => [ 'http_auth_enabled' => '1', 'http_login_form' => '1', 'http_strip_domains' => 'local.com', 'http_case_sensitive' => '1' ] ] ], // HTTP authentication - Login with user test-user (Zabbix User), [ [ 'user' => 'local.com\\test-user', 'password' => 'zabbix', 'file' => 'htaccess', 'http_authentication' => [ 'Enable HTTP authentication' => true, 'Default login form' => 'HTTP login form', 'Remove domain name' => 'local.com' ], 'pages' => [ [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ], [ 'page' => 'zabbix.php?action=user.list', 'error' => 'Access denied' ], // // wait for ZBX-14774. // [ // 'page' => 'hosts.php', // 'action' => self::LOGIN_HTTP, // 'target' => 'hosts' // ], [ 'page' => 'zabbix.php?action=dashboard.view', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], [ 'page' => 'index.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], [ 'page' => 'index_http.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ], [ 'page' => 'index.php?form=default', 'action' => self::LOGIN_USER, 'target' => 'Global view' ] ], 'db_check' => [ 'http_auth_enabled' => '1', 'http_login_form' => '1', 'http_strip_domains' => 'local.com', 'http_case_sensitive' => '1' ] ] ], // HTTP authentication - Case sensitive login, [ [ 'user' => 'admin', 'password' => 'zabbix', 'file' => 'htaccess', 'http_authentication' => [ 'Enable HTTP authentication' => true, 'Default login form' => 'Zabbix login form', 'Case sensitive login' => true ], 'pages' => [ [ 'page' => 'index_http.php', 'error' => 'You are not logged in' ] ], 'db_check' => [ 'http_auth_enabled' => '1', 'http_login_form' => '0', 'http_strip_domains' => '', 'http_case_sensitive' => '1' ] ] ], [ [ 'user' => 'admin', 'password' => 'zabbix', 'file' => 'htaccess', 'user_case_sensitive' => 'Admin', 'http_authentication' => [ 'Enable HTTP authentication' => true, 'Default login form' => 'Zabbix login form', 'Case sensitive login' => false ], 'pages' => [ [ 'page' => 'index_http.php', 'action' => self::LOGIN_HTTP, 'target' => 'Global view' ] ], 'db_check' => [ 'http_auth_enabled' => '1', 'http_login_form' => '0', 'http_strip_domains' => '', 'http_case_sensitive' => '0' ] ] ] ]; } /** * Login with different authentication methods. */ protected function loginAs($data, $page) { switch (CTestArrayHelper::get($page, 'action', self::LOGIN_GUEST)) { case self::LOGIN_GUEST: $this->page->open($page['page']); return 'guest'; case self::LOGIN_USER: $this->page->open($page['page']); $this->page->waitUntilReady(); // Check button 'Sign in with HTTP'. $xpath = '//a[@href="index_http.php"][text()="Sign in with HTTP"]'; if (CTestArrayHelper::get($data, 'http_authentication.Enable HTTP authentication', false) === true) { $this->assertTrue($this->query('xpath', $xpath)->one()->isVisible()); } else { $this->assertTrue($this->query('xpath', $xpath)->one(false)->isVisible(false)); } $this->query('id:name')->one()->fill($this->getUsernameWithoutDomain($data['user'])); $this->query('id:password')->one()->fill(CTestArrayHelper::get($data, 'db_password', $data['password'])); $this->query('button:Sign in')->one()->click(); break; case self::LOGIN_HTTP: $this->openAsHttpUser($data['user'], $data['password'], $page['page']); break; } return $this->getUsernameWithoutDomain($data['user']); } /** * @dataProvider getHttpData * @backup config * @onAfter removeConfigurationFiles * * Internal authentication with HTTP settings. */ public function testFormAdministrationAuthenticationHttp_CheckSettings($data) { $this->setHttpConfiguration($data); // Check authentication on pages. foreach ($data['pages'] as $check) { $alias = $this->loginAs($data, $check); if (array_key_exists('error', $check)) { foreach (['simple', 'http'] as $type) { switch ($type) { case 'simple': $this->page->open($check['page']); break; case 'http': $this->openAsHttpUser($data['user'], $data['password'], $check['page']); break; } $message = CMessageElement::find()->one(); $this->assertEquals('msg-bad msg-global', $message->getAttribute('class')); $message_title= $message->getText(); $this->assertStringContainsString($check['error'], $message_title); } continue; } // Check page header after successful login. else { $this->assertEquals($check['target'], $this->query('tag:h1')->one()->getText()); } // Check user data in DB after login. $session = $this->webDriver->manage()->getCookieNamed(ZBX_SESSION_NAME); $user_data = CDBHelper::getRow( 'SELECT u.alias'. ' FROM users u,sessions s'. ' WHERE u.userid=s.userid'. ' AND sessionid='.zbx_dbstr($session['value']) ); if (array_key_exists('user_case_sensitive', $data)) { $this->assertEquals($user_data['alias'], $data['user_case_sensitive']); } else { $this->assertEquals($user_data['alias'], $alias); } $this->page->logout(); $this->page->reset(); $this->page->open('index.php?form=default'); } } /** * Creating a configuration file. * * @param type $data */ protected function createConfigurationFiles($data) { switch (CTestArrayHelper::get($data, 'file')) { case 'htaccess': $this->assertTrue(file_put_contents(PHPUNIT_BASEDIR.'/ui/.htaccess', 'SetEnv REMOTE_USER "'. $data['user'].'"') !== false); break; case 'pwfile': $this->assertTrue(exec('htpasswd -c -b "'.PHPUNIT_BASEDIR.'/ui/.pwd" "'.$data['user'].'" "'. $data['password'].'" > /dev/null 2>&1') !== false); $content = '<Files index_http.php>'."\n". ' AuthType Basic'."\n". ' AuthName "Password Required"'."\n". ' AuthUserFile "'.PHPUNIT_BASEDIR.'/ui/.pwd"'."\n". ' Require valid-user'."\n". '</Files>'; $this->assertTrue(file_put_contents(PHPUNIT_BASEDIR.'/ui/.htaccess', $content) !== false); break; } } /** * Set HTTP authentication settings. * * @param array $data data array for HTTP settings setup. */ private function setHttpConfiguration($data) { $this->page->login()->open('zabbix.php?action=authentication.edit'); $this->assertEquals('Authentication', $this->query('tag:h1')->one()->getText()); $this->page->assertTitle('Configuration of authentication'); // Fill fields in 'HTTP settings' tab. $form = $this->query('name:form_auth')->asForm()->one(); $http_options = CTestArrayHelper::get($data, 'http_authentication', ['Enable HTTP authentication' => false]); $form->selectTab('HTTP settings'); $form->fill($http_options); // Check disabled or enabled fields. $fields = ['Default login form', 'Remove domain name', 'Case sensitive login']; foreach ($fields as $field) { $this->assertTrue($form->getField($field)->isEnabled($http_options['Enable HTTP authentication'])); } $this->createConfigurationFiles($data); $form->submit(); // Check DB configuration. $defautl_values = [ 'authentication_type' => '0', 'ldap_host' => '', 'ldap_port' => '389', 'ldap_base_dn' => '', 'ldap_bind_dn' => '', 'ldap_bind_password' => '', 'ldap_search_attribute' => '', 'ldap_configured' => '0', 'ldap_case_sensitive' => '1' ]; $sql = 'SELECT authentication_type,ldap_host,ldap_port,ldap_base_dn,ldap_bind_dn,ldap_bind_password,'. 'ldap_search_attribute,ldap_configured,ldap_case_sensitive,http_auth_enabled,http_login_form,'. 'http_strip_domains,http_case_sensitive'. ' FROM config'; $result = CDBHelper::getRow($sql); $this->assertEquals(array_merge($defautl_values, $data['db_check']), $result); $this->page->logout(); } /** * Open page with username and password in url. */ private function openAsHttpUser($user, $password, $url) { $parts = explode('//', PHPUNIT_URL.$url, 2); $full_url = $parts[0].'//'.urlencode($user).':'.urlencode($password).'@'.$parts[1]; $this->webDriver->get($full_url); } /** * Remove domain part of the username. * * @param string $alias username * * @return string */ private function getUsernameWithoutDomain($alias) { $separator = strpos($alias, '@'); if ($separator !== false) { $alias = substr($alias, 0, $separator); } else { $separator = strpos($alias, '\\'); if ($separator !== false) { $alias = substr($alias, $separator + 1); } } return $alias; } /** * Remove file after every test case. */ public function removeConfigurationFiles() { if (file_exists(PHPUNIT_BASEDIR.'/ui/.htaccess')) { unlink(PHPUNIT_BASEDIR.'/ui/.htaccess'); } if (file_exists(PHPUNIT_BASEDIR.'/ui/.pwd')) { unlink(PHPUNIT_BASEDIR.'/ui/.pwd'); } // Cleanup is required to avoid browser sending Basic auth header. self::closePage(); } /** * Guest user needs to be out of "Disabled" group to have access to frontend. */ public static function removeGuestFromDisabledGroup() { DBexecute('DELETE FROM users_groups WHERE userid=2 AND usrgrpid=9'); } public function addGuestToDisabledGroup() { DBexecute('INSERT INTO users_groups (id, usrgrpid, userid) VALUES (150, 9, 2)'); } }