diff --git a/sssd_test_framework/roles/samba.py b/sssd_test_framework/roles/samba.py index fc61cdf..8e0fe3a 100644 --- a/sssd_test_framework/roles/samba.py +++ b/sssd_test_framework/roles/samba.py @@ -134,6 +134,30 @@ def fqn(self, name: str) -> str: """ return f"{name}@{self.domain}" + @property + def password(self) -> SambaPasswordPolicy: + """ + Domain password policy management. + + .. code-block:: python + :caption: Example usage + + @pytest.mark.topology(KnownTopology.Samba + def test_example(client: Client, samba: Samba): + # Enable password complexity + samba.password.complexity(enable=True) + + # Set 3 login attempts and 30 lockout duration + samba.password.lockout(attempts=3, duration=30) + + # Set password length requirement to 12 characters + samba.password.requirement(length=12) + + # Set password max age to 30 seconds + samba.password.age(max=30 + """ + return SambaPasswordPolicy(self) + def user(self, name: str) -> SambaUser: """ Get user object. @@ -673,6 +697,17 @@ def modify( self._modify(attrs) return self + @property + def password_change_at_logon(self) -> SambaUser: + """ + Force user to change password next logon. + + :return: Self. + :rtype: SambaUser + """ + self._modify({"pwdLastSet": "0"}) + return self + def passkey_add(self, passkey_mapping: str) -> SambaUser: """ Add passkey mapping to the user. @@ -1061,6 +1096,99 @@ def policy(self, logon_rights: dict[str, list[SambaObject]], cfg: dict[str, Any] return self +class SambaPasswordPolicy(BaseObject): + """ + Password policy management. + """ + + def __init__(self, role: Samba): + """ + :param role: Samba host object. + :type role: SambaHost + """ + super().__init__(role) + + def complexity(self, enable: bool) -> SambaPasswordPolicy: + """ + Enable or disable password complexity. + + :param enable: Enable or disable password complexity. + :type enable: bool + :return SambaPasswordPolicy object. + :rtype: SambaPasswordPolicy + """ + complexity: str = "off" + if enable: + complexity = "on" + + args: CLIBuilderArgs = { + "complexity": (self.cli.option.VALUE, complexity), + } + + self.host.conn.run(self.cli.command("samba-tool domain passwordsettings set", args)) + + return self + + def lockout(self, duration: int, attempts: int) -> SambaPasswordPolicy: + """ + Set lockout duration and login attempts. + + :param duration: Duration of lockout in seconds, converted to minutes. + :type duration: int + :param attempts: Number of login attempts. + :type attempts: int + :return: SambaPasswordPolicy object. + :rtype: SambaPasswordPolicy + """ + minutes = divmod(duration, 60)[0] + + args: CLIBuilderArgs = { + "account-lockout-duration": (self.cli.option.VALUE, str(minutes)), + "account-lockout-threshold": (self.cli.option.VALUE, str(attempts)), + } + self.host.conn.run(self.cli.command("samba-tool domain passwordsettings set", args)) + + return self + + def age(self, minimum: int, maximum: int) -> SambaPasswordPolicy: + """ + Set maximum and minimum password age. + + :param minimum: Minimum password age in seconds, converted to days. + :type minimum: int + :param maximum: Maximum password age in seconds, converted to days. + :type maximum: int + :return: SambaPasswordPolicy object. + :rtype: SambaPasswordPolicy + """ + _minimum: int = divmod(minimum, 3600)[0] + _maximum: int = divmod(maximum, 3600)[0] + + args: CLIBuilderArgs = { + "min-pwd-age": (self.cli.option.VALUE, str(_minimum)), + "max-pwd-age": (self.cli.option.VALUE, str(_maximum)), + } + self.host.conn.run(self.cli.command("samba-tool domain passwordsettings set", args)) + + return self + + def requirements(self, length: int) -> SambaPasswordPolicy: + """ + Set password requirements, like length. + + :param length: Required password character count. + :type length: int + :return: SambaPasswordPolicy object. + :rtype: SambaPasswordPolicy + """ + args: CLIBuilderArgs = { + "min-pwd-length": (self.cli.option.VALUE, str(length)), + } + self.host.conn.run(self.cli.command("samba-tool domain passwordsettings set", args)) + + return self + + SambaOrganizationalUnit: TypeAlias = LDAPOrganizationalUnit[SambaHost, Samba] SambaAutomount: TypeAlias = LDAPAutomount[SambaHost, Samba] SambaSudoRule: TypeAlias = LDAPSudoRule[SambaHost, Samba, SambaUser, SambaGroup]