Skip to content

Commit

Permalink
roles: added password policy utilities to ldap role
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Lavu committed Dec 3, 2024
1 parent 36ad492 commit e63f374
Showing 1 changed file with 123 additions and 0 deletions.
123 changes: 123 additions & 0 deletions sssd_test_framework/roles/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"LDAPAutomount",
"LDAPAutomountMap",
"LDAPAutomountKey",
"LDAPPasswordPolicy",
]


Expand Down Expand Up @@ -84,6 +85,9 @@ def __init__(self, *args, **kwargs) -> None:
self.aci: LDAPACI = LDAPACI(self)
"""Manage LDAP ACI records."""

self.password: LDAPPasswordPolicy = LDAPPasswordPolicy(self)
"""Manage LDAP password policies."""

self.automount: LDAPAutomount[LDAPHost, LDAP] = LDAPAutomount[LDAPHost, LDAP](self)
"""
Manage automount maps and keys.
Expand Down Expand Up @@ -846,6 +850,19 @@ def expire(self, expiration: str = "19700101000000") -> LDAPUser:

return self

@property
def password_change_at_logon(self) -> LDAPUser:
"""
Force user to change password next logon.
:return: Self.
:rtype: LDAPUser
"""

self.role.ldap.modify("cn=config", replace={"passwordMustChange": "on"})

return self

def passkey_add(self, passkey_mapping: str) -> LDAPUser:
"""
Add passkey mapping to the user.
Expand Down Expand Up @@ -1759,3 +1776,109 @@ def __get_info(self, info: str | NFSExport | LDAPAutomountMap | DeleteAttribute
return info.name

return info


class LDAPPasswordPolicy(object):
"""
Password policy management.
"""

def __init__(self, role: LDAP) -> None:
"""
:param role: LDAP role object.
:type role: LDAP
"""
self.role: LDAP = role
self.ldap: LDAPUtils = self.role.ldap
self.config: str = "cn=config"

role.aci.add('(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)')

def get(self, name: str) -> str:
"""
Return password policy value.
:param name: Password policy setting name.
:type name: str
:return: Password policy value.
:rtype: str
"""
result = (
self.ldap.conn.search_s(self.config, ldap.SCOPE_BASE, attrlist=[name])
.pop()[1]
.get(name)[0]
.decode("utf-8")
)
return result

def set(self, policy: dict[str, str]) -> None:
"""
Set password policy value.
:param policy: Password policy key and values.
:type policy: dict[str, str]
"""
for k, v in policy.items():
if self.get(k) != v:
self.ldap.modify(self.config, replace={k: v})

def complexity(self, enable: bool) -> LDAPPasswordPolicy:
"""
Enable or disable password complexity.
:param enable: Enable or disable password complexity.
:type enable: bool
:return: LDAPPasswordPolicy object.
:rtype: LDAPPasswordPolicy
"""
if enable:
self.set({"passwordCheckSyntax": "on"})
return self

def lockout(self, duration: int, attempts: int) -> LDAPPasswordPolicy:
"""
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: LDAPPasswordPolicy object.
:rtype: LDAPPasswordPolicy
"""
self.set(
{"passwordLockout": "on", "passwordMaxFailure": str(attempts), "passwordLockoutDuration": str(duration)}
)
return self

def age(self, minimum: int, maximum: int) -> LDAPPasswordPolicy:
"""
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: LDAPPasswordPolicy object.
:rtype: LDAPPasswordPolicy
"""
self.set(
{
"passwordExp": "on",
"passwordMaxAge": str(maximum),
"passwordMinAge": str(minimum),
},
)
return self

def requirements(self, length: int) -> LDAPPasswordPolicy:
"""
Set password requirements, like length.
:param length: Required password character count.
:type length: int
:return: LDAPPasswordPolicy object.
:rtype: LDAPPasswordPolicy
"""
self.set({"passwordCheckSyntax": "on", "passwordMinLength": str(length)})
return self

0 comments on commit e63f374

Please sign in to comment.