From 9a35e8b00a26f9d6a5712e55bcff38866ca9722d Mon Sep 17 00:00:00 2001 From: "authentik-automation[bot]" <135050075+authentik-automation[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 14:42:16 +0200 Subject: [PATCH] enterprise/stages/mtls: attempt fix freezegun (cherry-pick #22474 to version-2026.2) (#22500) enterprise/stages/mtls: attempt fix freezegun (#22474) * enterprise/stages/mtls: attempt fix freezegun * emil's fix * Revert "enterprise/stages/mtls: attempt fix freezegun" This reverts commit 8963dac3bc52fba50f82676cdfccd1e6dddcbc7b. * format * Reapply "enterprise/stages/mtls: attempt fix freezegun" This reverts commit 090ab760b68007e19a861742a239a106671e1528. --------- Signed-off-by: Jens Langhammer Co-authored-by: Jens L. --- authentik/enterprise/stages/mtls/stage.py | 7 ++++--- authentik/root/test_plugin.py | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/authentik/enterprise/stages/mtls/stage.py b/authentik/enterprise/stages/mtls/stage.py index 421db4e2d6..3807fbf2d2 100644 --- a/authentik/enterprise/stages/mtls/stage.py +++ b/authentik/enterprise/stages/mtls/stage.py @@ -14,6 +14,7 @@ from cryptography.x509 import ( load_pem_x509_certificate, ) from cryptography.x509.verification import PolicyBuilder, Store, VerificationError +from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ from authentik.brands.models import Brand @@ -138,9 +139,9 @@ class MTLSStageView(ChallengeStageView): authorities_cert = [x.certificate for x in authorities] for _cert in certs: try: - PolicyBuilder().store(Store(authorities_cert)).build_client_verifier().verify( - _cert, [] - ) + PolicyBuilder().store(Store(authorities_cert)).time( + now() + ).build_client_verifier().verify(_cert, []) return _cert except ( InvalidSignature, diff --git a/authentik/root/test_plugin.py b/authentik/root/test_plugin.py index 64057f6aac..42288df74c 100644 --- a/authentik/root/test_plugin.py +++ b/authentik/root/test_plugin.py @@ -16,6 +16,18 @@ def pytest_sessionstart(*_, **__): """Clear the console ahead of the pytest output starting""" if not IS_CI: print("\x1b[2J\x1b[H") + # Pre-warm cryptography's PyO3 PyDateTime type cache with the real + # datetime class. If the first extraction happens under @freeze_time + # (e.g. in MTLSStageTests), PyO3 caches freezegun's FakeDatetime, + # which breaks every later test that passes a real datetime into + # cryptography ("TypeError: 'datetime' object is not an instance + # of 'FakeDatetime'"). The discard is intentional — only side + # effect needed is the type-cache initialization. + from datetime import UTC, datetime + + from cryptography.x509.verification import PolicyBuilder + + PolicyBuilder().time(datetime.now(tz=UTC)) yield