sources/ldap/freeipa: handle list-valued krbLastPwdChange (cherry-pick #20600 to version-2026.8) (#25561)

Co-authored-by: Oluwatobi Mustapha <oluwatobimustapha539@gmail.com>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
authentik-cherry-pick[bot]
2026-08-28 16:45:09 +02:00
committed by GitHub
parent 3791deb291
commit 27f7bdc1e6
2 changed files with 21 additions and 1 deletions

View File

@@ -27,7 +27,7 @@ class FreeIPA(BaseLDAPSynchronizer):
"""Check krbLastPwdChange"""
if "krbLastPwdChange" not in attributes:
return
pwd_last_set: datetime = attributes.get("krbLastPwdChange", datetime.now())
pwd_last_set: datetime = flatten(attributes.get("krbLastPwdChange", datetime.now()))
pwd_last_set = pwd_last_set.replace(tzinfo=UTC)
if created or pwd_last_set >= user.password_change_date:
self._task.info(f"'{user.username}': Reset user's password")

View File

@@ -1,5 +1,6 @@
"""LDAP Source tests"""
from datetime import UTC, datetime
from unittest.mock import MagicMock, patch
from django.db.models import Q
@@ -27,6 +28,7 @@ from authentik.sources.ldap.sync.membership import (
MembershipLDAPSynchronizer,
)
from authentik.sources.ldap.sync.users import UserLDAPSynchronizer
from authentik.sources.ldap.sync.vendor.freeipa import FreeIPA
from authentik.sources.ldap.tasks import ldap_sync, ldap_sync_page
from authentik.sources.ldap.tests.mock_ad import mock_ad_connection
from authentik.sources.ldap.tests.mock_freeipa import mock_freeipa_connection
@@ -446,6 +448,24 @@ class LDAPSyncTests(TestCase):
posix_group = Group.objects.filter(name="group-posix").first()
self.assertTrue(posix_group.users.filter(name="user-posix").exists())
def test_sync_users_freeipa_krb_last_pwd_change_list(self):
"""Ensure list-valued krbLastPwdChange is handled correctly."""
connection = MagicMock(return_value=mock_freeipa_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
user = User.objects.create(username=generate_id())
user.set_password("test-password")
user.save()
freeipa_sync = FreeIPA(self.source, Task())
freeipa_sync.check_pwd_last_set(
attributes={"krbLastPwdChange": [datetime.now(UTC)]},
user=user,
created=True,
)
user.refresh_from_db()
self.assertFalse(user.has_usable_password())
def test_sync_group_hierarchy_ad(self):
"""Test group hierarchy sync"""
self.source.base_dn = "dc=t,dc=goauthentik,dc=io"