diff --git a/doc/05-Authentication.md b/doc/05-Authentication.md index bc7ff288d..ab69fb2aa 100644 --- a/doc/05-Authentication.md +++ b/doc/05-Authentication.md @@ -177,12 +177,14 @@ Icinga Web provides a built-in policy called `Common` with the following require You can create custom password policies by developing a module with a provided hook. **Create Module Structure** + ```bash mkdir -p /usr/share/icingaweb2/modules/mypasswordpolicy/library/Mypasswordpolicy/ProvidedHook cd /usr/share/icingaweb2/modules/mypasswordpolicy ``` Create `module.info`: + ```ini Module: mypasswordpolicy Name: My Password Policy @@ -259,8 +261,6 @@ Enable the module: icingacli module enable mypasswordpolicy ``` -You can choose in the settings the preferred password policy. - The custom policy will now appear in **Configuration > Application > General** under Password Policy. ## Groups diff --git a/library/Icinga/Application/Hook/PasswordPolicyHook.php b/library/Icinga/Application/Hook/PasswordPolicyHook.php index 35e17dc31..73cce02d6 100644 --- a/library/Icinga/Application/Hook/PasswordPolicyHook.php +++ b/library/Icinga/Application/Hook/PasswordPolicyHook.php @@ -11,9 +11,7 @@ use Icinga\Authentication\PasswordPolicy; */ abstract class PasswordPolicyHook implements PasswordPolicy { - /** - * Hook name - */ + /** @var string Hook name *( protected const HOOK_NAME = 'PasswordPolicy'; /** @@ -29,7 +27,7 @@ abstract class PasswordPolicyHook implements PasswordPolicy /** * Return all registered password policies sorted by name * - * @return array + * @return array */ public static function all(): array { diff --git a/library/Icinga/Application/ProvidedHook/AnyPasswordPolicy.php b/library/Icinga/Application/ProvidedHook/AnyPasswordPolicy.php index 5b6913337..9a11360e5 100644 --- a/library/Icinga/Application/ProvidedHook/AnyPasswordPolicy.php +++ b/library/Icinga/Application/ProvidedHook/AnyPasswordPolicy.php @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later namespace Icinga\Application\ProvidedHook; diff --git a/library/Icinga/Authentication/PasswordPolicy.php b/library/Icinga/Authentication/PasswordPolicy.php index bc30d40bf..6f62e5e86 100644 --- a/library/Icinga/Authentication/PasswordPolicy.php +++ b/library/Icinga/Authentication/PasswordPolicy.php @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later namespace Icinga\Authentication; @@ -28,9 +30,10 @@ interface PasswordPolicy * Validate a given password against the defined policy * * @param string $newPassword - * @param string|null $oldPassword + * @param ?string $oldPassword + * * @return string[] Returns an empty array if the password is valid, - * otherwise returns error messages describing the violations + * otherwise returns error messages describing the violations */ public function validate(string $newPassword, ?string $oldPassword = null): array; } diff --git a/library/Icinga/Authentication/PasswordPolicyHelper.php b/library/Icinga/Authentication/PasswordPolicyHelper.php index 2116415d8..c64148f8c 100644 --- a/library/Icinga/Authentication/PasswordPolicyHelper.php +++ b/library/Icinga/Authentication/PasswordPolicyHelper.php @@ -15,19 +15,13 @@ use LogicException; class PasswordPolicyHelper { - /* - * Default class for password policy - */ + /** @var class-string Default password policy class */ const DEFAULT_PASSWORD_POLICY = AnyPasswordPolicy::class; - /** - * Configuration section for password policy in the configuration file - */ + /** @var string INI configuration section for password policy */ const CONFIG_SECTION = 'global'; - /** - * Configuration key for password policy in the configuration file - */ + /** @var string INI configuration key for password policy */ const CONFIG_KEY = 'password_policy'; /** @@ -42,6 +36,7 @@ class PasswordPolicyHelper if ($oldPasswordElementName !== null && $form->getElement($oldPasswordElementName) === null) { throw new LogicException(); } + try { $passwordPolicyClass = Config::app()->get( 'global', @@ -83,10 +78,16 @@ class PasswordPolicyHelper ); } } -/** - * Create and validate a password policy instance from the given class name and ensure it implements the - * password policy interface. - */ + + /** + * Create a {@link PasswordPolicy} instance from the given class name + * + * @param class-string $passwordPolicyClass + * + * @return PasswordPolicy + * + * @throws ConfigurationError If class does not exist or does not implement {@link PasswordPolicy} + */ public static function createPolicy(string $passwordPolicyClass): PasswordPolicy { if ($passwordPolicyClass === static::DEFAULT_PASSWORD_POLICY) { diff --git a/library/Icinga/Authentication/PasswordPolicyValidator.php b/library/Icinga/Authentication/PasswordPolicyValidator.php index 1dbf37ebf..7513ef42b 100644 --- a/library/Icinga/Authentication/PasswordPolicyValidator.php +++ b/library/Icinga/Authentication/PasswordPolicyValidator.php @@ -1,14 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-or-later namespace Icinga\Authentication; use Zend_Validate_Abstract; /** - * Use the provided password policy to validate the new password. + * Validate passwords against a configured policy + * * Optionally, retrieve the old password from the form context using the configured form element name - * and pass it to the policy for comparative validation. + * and pass it to the policy for validation. * Delegate all validation logic to the policy instance and expose any returned violation messages. */ class PasswordPolicyValidator extends Zend_Validate_Abstract @@ -23,7 +26,7 @@ class PasswordPolicyValidator extends Zend_Validate_Abstract * Create a new PasswordPolicyValidator * * @param PasswordPolicy $passwordPolicy - * @param string|null $oldPasswordElementName + * @param ?string $oldPasswordElementName */ public function __construct(PasswordPolicy $passwordPolicy, ?string $oldPasswordElementName = null) { diff --git a/test/php/library/Icinga/Application/CommonPasswordPolicyTest.php b/test/php/library/Icinga/Application/CommonPasswordPolicyTest.php index 03cc957a1..dd364fe65 100644 --- a/test/php/library/Icinga/Application/CommonPasswordPolicyTest.php +++ b/test/php/library/Icinga/Application/CommonPasswordPolicyTest.php @@ -75,14 +75,14 @@ class CommonPasswordPolicyTest extends TestCase public function testValidatePasswordWithLengthAndUpperCaseLetters(): void { - $expectedResult = [ + $expected = [ 'Password must be at least 12 characters long', 'Password must contain at least one number', 'Password must contain at least one special character', - 'Password must contain at least one lowercase letter', + 'Password must contain at least one lowercase letter' ]; $this->assertSame( - $expectedResult, + $expected, $this->instance->validate('ICINGAADMIN') ); }