"""LDAP helpers and the fake directory; no domain controller needed.""" from __future__ import annotations import uuid from pathlib import Path import pytest from fakedir import FAKE_PASSWORD, FakeDirectory from pshelpers import make_settings from packetstation.auth import groups from packetstation.auth.ldap import Directory, LdapUnavailable, guid_filter, parse_guid, user_from_entry GUID = uuid.UUID("01234567-89ab-cdef-0123-456789abcdef") def test_parse_guid_bytes_and_string() -> None: raw = GUID.bytes_le assert parse_guid(raw) == GUID assert parse_guid([raw]) == GUID assert parse_guid("{01234567-89ab-cdef-0123-456789abcdef}") == GUID assert parse_guid("01234567-89AB-CDEF-0123-456789ABCDEF") == GUID with pytest.raises(ValueError): parse_guid(b"short") def test_guid_filter_escapes_every_byte() -> None: flt = guid_filter(GUID) assert flt.startswith("(objectGUID=\\67\\45\\23\\01") and flt.endswith(")") assert flt.count("\\") == 16 def test_user_from_entry() -> None: entry = { "dn": "CN=Andy,DC=x", "raw_attributes": {"objectGUID": [GUID.bytes_le]}, "attributes": { "sAMAccountName": ["weld.andy"], "userPrincipalName": ["weld.andy@pstest.local"], "displayName": ["Andy Welder"], "employeeID": ["0303"], "mail": [], "userAccountControl": ["514"], "distinguishedName": ["CN=Andy,DC=x"], }, } u = user_from_entry(entry) assert u.guid == GUID and u.sam_account == "weld.andy" and u.display_name == "Andy Welder" assert u.emp_no == "0303" # text, leading zero kept assert u.email is None and u.disabled is True and u.dn == "CN=Andy,DC=x" def test_plain_ldap_refused_without_starttls(tmp_path: Path) -> None: pw = tmp_path / "pw" pw.write_text("x") s = make_settings(tmp_path, ldap_url="ldap://dc.example:389", ldap_bind_dn="CN=svc", ldap_password_file=pw) with pytest.raises(LdapUnavailable, match="plain LDAP"): Directory(s).find_user("someone") def test_empty_password_never_binds(tmp_path: Path) -> None: s = make_settings(tmp_path, ldap_url="ldaps://dc.invalid:636") assert Directory(s).verify_password("CN=x,DC=y", "") is False def test_missing_service_secret_is_unavailable(tmp_path: Path) -> None: s = make_settings( tmp_path, ldap_url="ldaps://dc.invalid:636", ldap_bind_dn="CN=svc", ldap_password_file=tmp_path / "none" ) with pytest.raises(LdapUnavailable, match="LDAP_PASSWORD_FILE"): Directory(s).list_groups() def test_fake_directory_nested_and_ou() -> None: d = FakeDirectory() ned = d.find_user("NESTED.NED") assert ned is not None assert groups.roles_from_groups(d.groups_of(ned.dn)) == ["shop:10:worker"] bo = d.find_user("both.bo@pstest.local") assert bo is not None assert groups.roles_from_groups(d.groups_of(bo.dn)) == ["shop:03:supervisor"] assert "PS-14-Electrical-Lead" not in d.list_groups() and "PS-Extra-Legacy" in d.list_groups() sams = {u.sam_account for u in d.members_of("PS-03-WeldParts-Worker")} assert {"weld.andy", "both.bo", "dup.dave", "disabled.dan"} <= sams assert d.verify_password(bo.dn, FAKE_PASSWORD) and not d.verify_password(bo.dn, "nope") assert d.verify_password(bo.dn, "") is False