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.

405 lines
14 KiB

<?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.
**/
require_once dirname(__FILE__).'/../include/CAPITest.php';
/**
* @backup userdirectory, userdirectory_ldap, userdirectory_saml, userdirectory_idpgroup, userdirectory_usrgrp, userdirectory_media, config, usrgrp
*/
class testAuthentication extends CAPITest {
public const TEST_DATA_TO_RESOLVE = [
'disabled_usrgrpid' => 'Disabled user group for API tests'
];
public static $data = [
'disabled_usrgrpid' => null
];
public static function authentication_get_data() {
return [
'Test getting authentication general data' => [
'authentication' => [
'output' => ['authentication_type', 'http_auth_enabled', 'http_login_form', 'http_strip_domains',
'http_case_sensitive', 'ldap_auth_enabled', 'ldap_case_sensitive', 'saml_auth_enabled',
'saml_case_sensitive', 'passwd_min_length', 'passwd_check_rules', 'jit_provision_interval',
'saml_jit_status', 'ldap_jit_status', 'disabled_usrgrpid'
]
],
'get_result' => [
// General fields.
'authentication_type' => [ZBX_AUTH_INTERNAL, ZBX_AUTH_LDAP],
'passwd_min_length' => ['min' => 1, 'max' => 70],
'passwd_check_rules' => [
'min' => 0x00,
'max' => (PASSWD_CHECK_CASE | PASSWD_CHECK_DIGITS | PASSWD_CHECK_SPECIAL | PASSWD_CHECK_SIMPLE)
],
// HTTP auth fields.
'http_auth_enabled' => [ZBX_AUTH_HTTP_DISABLED, ZBX_AUTH_HTTP_ENABLED],
'http_login_form' => [ZBX_AUTH_FORM_ZABBIX, ZBX_AUTH_FORM_HTTP],
'http_strip_domains' => '',
'http_case_sensitive' => [ZBX_AUTH_CASE_INSENSITIVE, ZBX_AUTH_CASE_SENSITIVE],
// LDAP fields.
'ldap_auth_enabled' => [ZBX_AUTH_LDAP_DISABLED, ZBX_AUTH_LDAP_ENABLED],
'ldap_case_sensitive' => [ZBX_AUTH_CASE_INSENSITIVE, ZBX_AUTH_CASE_SENSITIVE],
'ldap_jit_status' => [JIT_PROVISIONING_DISABLED, JIT_PROVISIONING_ENABLED],
'jit_provision_interval' => '1h',
// SAML fields.
'saml_auth_enabled' => [ZBX_AUTH_SAML_DISABLED, ZBX_AUTH_SAML_ENABLED],
'saml_case_sensitive' => [ZBX_AUTH_CASE_INSENSITIVE, ZBX_AUTH_CASE_SENSITIVE],
'saml_jit_status' => [JIT_PROVISIONING_DISABLED, JIT_PROVISIONING_ENABLED]
],
'expected_error' => null
]
];
}
/**
* @dataProvider authentication_get_data
*/
public function testAuthentication_Get($authentication, $get_result, $expected_error) {
$result = $this->call('authentication.get', $authentication);
if ($expected_error === null) {
$result = $result['result'];
// General fields.
$this->assertContains($result['authentication_type'], $get_result['authentication_type']);
$this->assertGreaterThanOrEqual($get_result['passwd_min_length']['min'], $result['passwd_min_length']);
$this->assertLessThanOrEqual($get_result['passwd_min_length']['max'], $result['passwd_min_length']);
$this->assertGreaterThanOrEqual($get_result['passwd_check_rules']['min'], $result['passwd_check_rules']);
$this->assertLessThanOrEqual($get_result['passwd_check_rules']['max'], $result['passwd_check_rules']);
// HTTP auth fields.
$this->assertContains($result['http_auth_enabled'], $get_result['http_auth_enabled']);
$this->assertContains($result['http_login_form'], $get_result['http_login_form']);
$this->assertContains('http_strip_domains', array_keys($result));
$this->assertContains($result['http_case_sensitive'], $get_result['http_case_sensitive']);
// LDAP fields.
$this->assertContains($result['ldap_auth_enabled'], $get_result['ldap_auth_enabled']);
$this->assertContains($result['ldap_case_sensitive'], $get_result['ldap_case_sensitive']);
$this->assertContains($result['ldap_jit_status'], $get_result['ldap_jit_status']);
$this->assertEquals($get_result['jit_provision_interval'], $result['jit_provision_interval']);
// SAML fields.
$this->assertContains($result['saml_auth_enabled'], $get_result['saml_auth_enabled']);
$this->assertContains($result['saml_case_sensitive'], $get_result['saml_case_sensitive']);
$this->assertContains($result['saml_jit_status'], $get_result['saml_jit_status']);
}
}
public static function authentication_update_data_invalid() {
return [
// Invalid general auth tests.
'Test invalid authentication type' => [
'authentication' => [
'authentication_type' => 999
],
'expected_error' => 'Invalid parameter "/authentication_type": value must be one of '.
implode(', ', [ZBX_AUTH_INTERNAL, ZBX_AUTH_LDAP]).'.'
],
'Test invalid password min length' => [
'authentication' => [
'passwd_min_length' => 999
],
'expected_error' => 'Invalid parameter "/passwd_min_length": value must be one of 1-70.'
],
'Test invalid password rules' => [
'authentication' => [
'passwd_check_rules' => 999
],
'expected_error' => 'Invalid parameter "/passwd_check_rules": value must be one of 0-'.
(PASSWD_CHECK_CASE | PASSWD_CHECK_DIGITS | PASSWD_CHECK_SPECIAL | PASSWD_CHECK_SIMPLE).'.'
],
'Test authentication set to LDAP but having LDAP disabled at the same time' => [
'authentication' => [
'authentication_type' => ZBX_AUTH_LDAP,
'ldap_auth_enabled' => ZBX_AUTH_LDAP_DISABLED
],
'expected_error' => 'Incorrect value for field "/authentication_type": LDAP must be enabled.'
],
// Invalid HTTP auth tests.
'Test invalid HTTP auth' => [
'authentication' => [
'http_auth_enabled' => 999
],
'expected_error' => 'Invalid parameter "/http_auth_enabled": value must be one of '.
implode(', ', [ZBX_AUTH_HTTP_DISABLED, ZBX_AUTH_HTTP_ENABLED]).'.'
],
'Test invalid HTTP form' => [
'authentication' => [
'http_login_form' => 999
],
'expected_error' => 'Invalid parameter "/http_login_form": value must be one of '.
implode(', ', [ZBX_AUTH_FORM_ZABBIX, ZBX_AUTH_FORM_HTTP]).'.'
],
'Test invalid case sensitive for HTTP auth' => [
'authentication' => [
'http_case_sensitive' => 999
],
'expected_error' => 'Invalid parameter "/http_case_sensitive": value must be one of '.
implode(', ', [ZBX_AUTH_CASE_INSENSITIVE, ZBX_AUTH_CASE_SENSITIVE]).'.'
],
// Invalid LDAP auth tests.
'Test invalid LDAP auth' => [
'authentication' => [
'ldap_auth_enabled' => 999
],
'expected_error' => 'Invalid parameter "/ldap_auth_enabled": value must be one of '.
implode(', ', [ZBX_AUTH_LDAP_DISABLED, ZBX_AUTH_LDAP_ENABLED]).'.'
],
'Test invalid userdirectoryid' => [
'authentication' => [
'ldap_userdirectoryid' => 'userdirectory_invalidid_1'
],
'expected_error' => 'Invalid parameter "/ldap_userdirectoryid": a number is expected.'
],
'Cannot set default authentication ldap when ldap is disabled' => [
'authentication' => [
'authentication_type' => ZBX_AUTH_LDAP,
'ldap_auth_enabled' => ZBX_AUTH_LDAP_DISABLED
],
'expected_error' => 'Incorrect value for field "/authentication_type": LDAP must be enabled.'
],
'Test invalid LDAP enabled without LDAP servers' => [
'authentication' => [
'ldap_auth_enabled' => ZBX_AUTH_LDAP_ENABLED
],
'expected_error' => 'At least one LDAP server must exist.'
],
// Invalid SAML auth tests.
'Test invalid SAML auth' => [
'authentication' => [
'saml_auth_enabled' => 999
],
'expected_error' => 'Invalid parameter "/saml_auth_enabled": value must be one of '.
implode(', ', [ZBX_AUTH_SAML_DISABLED, ZBX_AUTH_SAML_ENABLED]).'.'
],
'Test invalid case sensitive for SAML auth' => [
'authentication' => [
'saml_case_sensitive' => 999
],
'expected_error' => 'Invalid parameter "/saml_case_sensitive": value must be one of '.
implode(', ', [ZBX_AUTH_CASE_INSENSITIVE, ZBX_AUTH_CASE_SENSITIVE]).'.'
],
'Test setting up the SAML JIT status without specifying deprovisioned user group' => [
'authentication' => [
'saml_auth_enabled' => ZBX_AUTH_SAML_ENABLED,
'saml_jit_status' => JIT_PROVISIONING_ENABLED,
'disabled_usrgrpid' => 0
],
'expected_error' => 'Deprovisioned users group cannot be empty.'
]
];
}
public static function authentication_update_data_valid() {
return [
// Cannot test valid authentication change, because that will log out the current user.
// Valid general auth tests.
'Test valid password min length' => [
'authentication' => [
'passwd_min_length' => 32
],
'expected_error' => null
],
'Test valid password rules' => [
'authentication' => [
'passwd_check_rules' => (PASSWD_CHECK_DIGITS | PASSWD_CHECK_SPECIAL)
],
'expected_error' => null
],
'Test valid deprovisioning group setup' => [
'authentication' => [
'disabled_usrgrpid' => self::TEST_DATA_TO_RESOLVE['disabled_usrgrpid']
],
'expected_error' => null
],
// Valid HTTP auth tests.
'Test valid HTTP auth' => [
'authentication' => [
'http_auth_enabled' => ZBX_AUTH_HTTP_ENABLED
],
'expected_error' => null
],
'Test valid HTTP form' => [
'authentication' => [
'http_login_form' => ZBX_AUTH_FORM_HTTP
],
'expected_error' => null
],
'Test update remove domains' => [
'authentication' => [
'http_strip_domains' => 'text.string'
],
'expected_error' => null
],
'Test valid case sensitive for HTTP auth' => [
'authentication' => [
'http_case_sensitive' => ZBX_AUTH_CASE_SENSITIVE
],
'expected_error' => null
],
// Valid LDAP auth tests.
'Test valid LDAP JIT status' => [
'authentication' => [
'ldap_jit_status' => JIT_PROVISIONING_ENABLED,
'disabled_usrgrpid' => self::TEST_DATA_TO_RESOLVE['disabled_usrgrpid']
],
'expected_error' => null
],
'Test valid LDAP JIT interval' => [
'authentication' => [
'jit_provision_interval' => '3h'
],
'expected_error' => null
],
'Test valid case sensitive for LDAP auth' => [
'authentication' => [
'ldap_case_sensitive' => ZBX_AUTH_CASE_SENSITIVE
],
'expected_error' => null
],
// Valid SAML auth tests.
'Test valid SAML auth' => [
'authentication' => [
'saml_auth_enabled' => ZBX_AUTH_SAML_ENABLED
],
'expected_error' => null
],
'Test valid case sensitive for SAML auth' => [
'authentication' => [
'saml_case_sensitive' => ZBX_AUTH_CASE_SENSITIVE
],
'expected_error' => null
],
'Test valid SAML JIT status' => [
'authentication' => [
'saml_jit_status' => JIT_PROVISIONING_ENABLED,
'disabled_usrgrpid' => self::TEST_DATA_TO_RESOLVE['disabled_usrgrpid']
],
'expected_error' => null
],
'Test setting up the deprovisioned user group without unchecking disabled SAML JIT status' => [
'authentication' => [
'saml_auth_enabled' => ZBX_AUTH_SAML_DISABLED,
'saml_jit_status' => JIT_PROVISIONING_ENABLED,
'disabled_usrgrpid' => 0
],
'expected_error' => null
],
'Test setting up the deprovisioned user group without unchecking disabled LDAP JIT status' => [
'authentication' => [
'ldap_auth_enabled' => ZBX_AUTH_LDAP_DISABLED,
'ldap_jit_status' => JIT_PROVISIONING_ENABLED,
'disabled_usrgrpid' => 0
],
'expected_error' => null
]
];
}
/**
* @dataProvider authentication_update_data_invalid
* @dataProvider authentication_update_data_valid
*/
public function testAuthentication_Update($authentication, $expected_error) {
$authentication = self::resolveInstanceData($authentication);
if ($expected_error === null) {
// Before updating, collect old authentication data.
$fields = '';
foreach ($authentication as $field => $value) {
$fields = 'c.'.$field.',';
}
$fields = substr($fields, 0, -1);
$sql = 'SELECT '.$fields.' FROM config c WHERE c.configid=1';
$db_authentication = CDBHelper::getAll($sql)[0];
$this->call('authentication.update', $authentication, $expected_error);
$db_upd_authentication = CDBHelper::getAll($sql)[0];
$updated = array_intersect_key($authentication, $db_upd_authentication);
$unchanged = array_diff_key($db_upd_authentication, $authentication);
// Check if field values have been updated.
foreach ($updated as $field => $value) {
if (is_numeric($value)) {
$this->assertEquals($value, $db_upd_authentication[$field]);
}
else {
$this->assertSame($value, $db_upd_authentication[$field]);
}
}
// Check if fields that were not given, remain the same.
foreach ($unchanged as $field => $value) {
if (is_numeric($value)) {
$this->assertEquals($value, $db_authentication[$field]);
}
else {
$this->assertSame($value, $db_authentication[$field]);
}
}
}
else {
// Call method and make sure it really returns the error.
$this->call('authentication.update', $authentication, $expected_error);
}
}
public static function resolveInstanceData(array $test_data): array {
foreach (self::TEST_DATA_TO_RESOLVE as $field => $value_not_set) {
if (array_key_exists($field, $test_data) && $test_data[$field] === $value_not_set) {
switch ($field) {
case 'disabled_usrgrpid':
if (!self::$data['disabled_usrgrpid']) {
$params = [[
'name' => 'Disabled user group for API tests',
'users_status' => GROUP_STATUS_DISABLED
]];
$response = CDataHelper::call('usergroup.create', $params);
self::$data['disabled_usrgrpid'] = reset($response['usrgrpids']);
}
$test_data['disabled_usrgrpid'] = self::$data['disabled_usrgrpid'];
break;
}
}
}
return $test_data;
}
}