diff --git a/authentik/sources/kerberos/models.py b/authentik/sources/kerberos/models.py index b5656e46409c..5d679d4480cd 100644 --- a/authentik/sources/kerberos/models.py +++ b/authentik/sources/kerberos/models.py @@ -6,7 +6,6 @@ from typing import Any import gssapi -import kadmin import pglock from django.db import connection, models from django.db.models.fields import b64decode @@ -14,6 +13,8 @@ from django.shortcuts import reverse from django.templatetags.static import static from django.utils.translation import gettext_lazy as _ +from kadmin import KAdmin +from kadmin.exceptions import PyKAdminException from rest_framework.serializers import Serializer from structlog.stdlib import get_logger @@ -30,9 +31,8 @@ LOGGER = get_logger() -# python-kadmin leaks file descriptors. As such, this global is used to reuse -# existing kadmin connections instead of creating new ones, which results in less to no file -# descriptors leaks +# Creating kadmin connections is expensive. As such, this global is used to reuse +# existing kadmin connections instead of creating new ones _kadmin_connections: dict[str, Any] = {} @@ -198,13 +198,13 @@ def krb5_conf_path(self) -> str | None: conf_path.write_text(self.krb5_conf) return str(conf_path) - def _kadmin_init(self) -> "kadmin.KAdmin | None": + def _kadmin_init(self) -> KAdmin | None: # kadmin doesn't use a ccache for its connection # as such, we don't need to create a separate ccache for each source if not self.sync_principal: return None if self.sync_password: - return kadmin.init_with_password( + return KAdmin.with_password( self.sync_principal, self.sync_password, ) @@ -215,18 +215,18 @@ def _kadmin_init(self) -> "kadmin.KAdmin | None": keytab_path.touch(mode=0o600) keytab_path.write_bytes(b64decode(self.sync_keytab)) keytab = f"FILE:{keytab_path}" - return kadmin.init_with_keytab( + return KAdmin.with_keytab( self.sync_principal, keytab, ) if self.sync_ccache: - return kadmin.init_with_ccache( + return KAdmin.with_ccache( self.sync_principal, self.sync_ccache, ) return None - def connection(self) -> "kadmin.KAdmin | None": + def connection(self) -> KAdmin | None: """Get kadmin connection""" if str(self.pk) not in _kadmin_connections: kadm = self._kadmin_init() @@ -246,7 +246,7 @@ def check_connection(self) -> dict[str, str]: status["status"] = "no connection" return status status["principal_exists"] = kadm.principal_exists(self.sync_principal) - except kadmin.KAdminError as exc: + except PyKAdminException as exc: status["status"] = str(exc) return status diff --git a/authentik/sources/kerberos/signals.py b/authentik/sources/kerberos/signals.py index af3306a7a1e3..7c1db64be8fa 100644 --- a/authentik/sources/kerberos/signals.py +++ b/authentik/sources/kerberos/signals.py @@ -1,8 +1,8 @@ """authentik kerberos source signals""" -import kadmin from django.db.models.signals import post_save from django.dispatch import receiver +from kadmin.exceptions import PyKAdminException from rest_framework.serializers import ValidationError from structlog.stdlib import get_logger @@ -48,7 +48,7 @@ def kerberos_sync_password(sender, user: User, password: str, **_): source.connection().getprinc(user_source_connection.identifier).change_password( password ) - except kadmin.KAdminError as exc: + except PyKAdminException as exc: LOGGER.warning("failed to set Kerberos password", exc=exc, source=source) Event.new( EventAction.CONFIGURATION_ERROR, diff --git a/authentik/sources/kerberos/sync.py b/authentik/sources/kerberos/sync.py index 6fcd87c5380c..2de77bb71731 100644 --- a/authentik/sources/kerberos/sync.py +++ b/authentik/sources/kerberos/sync.py @@ -2,9 +2,9 @@ from typing import Any -import kadmin from django.core.exceptions import FieldError from django.db import IntegrityError, transaction +from kadmin import KAdmin from structlog.stdlib import BoundLogger, get_logger from authentik.core.expression.exceptions import ( @@ -30,7 +30,7 @@ class KerberosSync: _source: KerberosSource _logger: BoundLogger - _connection: "kadmin.KAdmin" + _connection: KAdmin mapper: SourceMapper user_manager: PropertyMappingManager group_manager: PropertyMappingManager @@ -161,7 +161,7 @@ def sync(self) -> int: user_count = 0 with Krb5ConfContext(self._source): - for principal in self._connection.principals(): + for principal in self._connection.list_principals("*"): if self._handle_principal(principal): user_count += 1 return user_count diff --git a/authentik/sources/kerberos/tests/test_auth.py b/authentik/sources/kerberos/tests/test_auth.py index 72db23e7192a..a3996d680687 100644 --- a/authentik/sources/kerberos/tests/test_auth.py +++ b/authentik/sources/kerberos/tests/test_auth.py @@ -23,6 +23,7 @@ def setUp(self): ) self.user = User.objects.create(username=generate_id()) self.user.set_unusable_password() + self.user.save() UserKerberosSourceConnection.objects.create( source=self.source, user=self.user, identifier=self.realm.user_princ ) diff --git a/poetry.lock b/poetry.lock index 201bf6b702b9..9fc15bf00661 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -3191,8 +3191,6 @@ files = [ {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:960db0e31c4e52fa0fc3ecbaea5b2d3b58f379e32a95ae6b0ebeaa25b93dfd34"}, {file = "orjson-3.10.6-cp312-none-win32.whl", hash = "sha256:a6ea7afb5b30b2317e0bee03c8d34c8181bc5a36f2afd4d0952f378972c4efd5"}, {file = "orjson-3.10.6-cp312-none-win_amd64.whl", hash = "sha256:874ce88264b7e655dde4aeaacdc8fd772a7962faadfb41abe63e2a4861abc3dc"}, - {file = "orjson-3.10.6-cp313-none-win32.whl", hash = "sha256:efdf2c5cde290ae6b83095f03119bdc00303d7a03b42b16c54517baa3c4ca3d0"}, - {file = "orjson-3.10.6-cp313-none-win_amd64.whl", hash = "sha256:8e190fe7888e2e4392f52cafb9626113ba135ef53aacc65cd13109eb9746c43e"}, {file = "orjson-3.10.6-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:66680eae4c4e7fc193d91cfc1353ad6d01b4801ae9b5314f17e11ba55e934183"}, {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caff75b425db5ef8e8f23af93c80f072f97b4fb3afd4af44482905c9f588da28"}, {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3722fddb821b6036fd2a3c814f6bd9b57a89dc6337b9924ecd614ebce3271394"}, @@ -3951,19 +3949,53 @@ files = [ cli = ["click (>=5.0)"] [[package]] -name = "python-kadmin" -version = "0.2.0" -description = "Python module for kerberos admin (kadm5)" -optional = false -python-versions = ">=3.8" -files = [] -develop = false - -[package.source] -type = "git" -url = "https://github.com/authentik-community/python-kadmin.git" -reference = "v0.2.0" -resolved_reference = "6f9ce6ee2427e3488b403a900a9211166c7569e1" +name = "python-kadmin-rs" +version = "0.0.4" +description = "Python interface to the Kerberos administration interface (kadm5)" +optional = false +python-versions = "<=3.13,>=3.8" +files = [ + {file = "python_kadmin_rs-0.0.4-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:d46775665f18ed9c9b72c9d7c6ec6a1f499aac23c37fb8fb09b3d74a284a486c"}, + {file = "python_kadmin_rs-0.0.4-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:674ce1c6a6a98f4304aac33d853a8fc22a27e5ee1d786199c6c145a37bc6b9d8"}, + {file = "python_kadmin_rs-0.0.4-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:528998407f4c51f5ffb5c450bbc490410062dbc3296bfcde47c7c200bfdc7ebf"}, + {file = "python_kadmin_rs-0.0.4-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b067b9353ab6122b43e73f8b79246730ed12d54d48a186062e3118523b005ba9"}, + {file = "python_kadmin_rs-0.0.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:04ac04e2aae6ed000c0feb5b4d420391fa314a1258f7ab6afea706a244d90de5"}, + {file = "python_kadmin_rs-0.0.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2de1564097f8fb6afca57be6ae888edf977855c6f869b6e6336f6c014561ba78"}, + {file = "python_kadmin_rs-0.0.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:da04f408616db8d09b2e853bd9657cb29549527375fef431a32f348e59e1e315"}, + {file = "python_kadmin_rs-0.0.4-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:ed3d8201776820c152eff8dfc3c98e425b43bd41a0f32bcf50d6b9d41d2d9a4d"}, + {file = "python_kadmin_rs-0.0.4-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:efb1dd635c1293c5b0952b892cfa5d76763fde5b9561bfe353e207c230f9e3f9"}, + {file = "python_kadmin_rs-0.0.4-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:bf6332ddd0fd11b1b52fbeef46ae39d34d618b187193ab292210273c00f14943"}, + {file = "python_kadmin_rs-0.0.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:32a083fd8699ec657e12428fee04f0bb8cf4e2aabb8a0ddf71da658763469fa6"}, + {file = "python_kadmin_rs-0.0.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:944bcf3ad789966ad214f85cbf2eda59f51346792d14550272b627759d6959a5"}, + {file = "python_kadmin_rs-0.0.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3a6934f03e5d2b8d3bbcc8076e73cc09d6bf79e370c71a1b911db5ae9d4bfe59"}, + {file = "python_kadmin_rs-0.0.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:00c1e3c4293249cd8bf687e3f227bd7f0aebcc2d883f70f7262a456cc28f2809"}, + {file = "python_kadmin_rs-0.0.4-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:5ee36f4e97c0d4a329308877039192f0749b5ce33942d0ec3cc4dbdba6bde939"}, + {file = "python_kadmin_rs-0.0.4-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9ed1064d12fbef010a7143194d3a7e3c9bd00c1078344bdc757dce143683018d"}, + {file = "python_kadmin_rs-0.0.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d1473fa1dcca9b11ab17160b9bb1f75639617417dd79ddd943df7b904d041e43"}, + {file = "python_kadmin_rs-0.0.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:07953beae610f1bc2bd0f861773d69a93603f48983e936338830d90bbcf0d514"}, + {file = "python_kadmin_rs-0.0.4-cp38-cp38-macosx_14_0_arm64.whl", hash = "sha256:f2390e76b853a5a12935f8d1cdd72ef1f33a950292f27aef9f57d8e6ee23dd0b"}, + {file = "python_kadmin_rs-0.0.4-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:c7bba5d82616b943bde667599a2052a0ceb5ff8851720e1e63806969142ba8bb"}, + {file = "python_kadmin_rs-0.0.4-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:414cd0b73200baf8c5597595ceb2f547307d6009148730e663c6c40608ba94d3"}, + {file = "python_kadmin_rs-0.0.4-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:8a002c6740e1f36e45b79b639898d0b45d28243b427e7e50c8342abf5422c5b1"}, + {file = "python_kadmin_rs-0.0.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f64300b8c607a860b545ce2fc3f5ca655a86fb1f6af2f59e211a92abd380b63d"}, + {file = "python_kadmin_rs-0.0.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d31e9cb6794471bab483356f3bb92ce018c256049e84fcbb19d49bc219cde387"}, + {file = "python_kadmin_rs-0.0.4-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:139c44ebfc4d4c08c0c3f18c5c4d1b4fd7554d323eb895ad83826e4c071dcf57"}, + {file = "python_kadmin_rs-0.0.4-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:5ee15b4426b3fd9504a2509f4d66c99af5b4c3df96837f9759f88bc9d588d3bc"}, + {file = "python_kadmin_rs-0.0.4-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:069845753e46a8829395d9389978e1562c504601c0cd4cdfcff26214d008f125"}, + {file = "python_kadmin_rs-0.0.4-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:7fac68afcc531a52622ff8b5bb48a28d2b77d216ba9d4808cb312d0e972bac01"}, + {file = "python_kadmin_rs-0.0.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d39dac7e86c60d223777e195e5df798897b38f3479c33488ee52bd915b828b66"}, + {file = "python_kadmin_rs-0.0.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ff4c3dd95ae570b64dad68465b6279988f0e6bed4692a9faf26626953c8bc05a"}, + {file = "python_kadmin_rs-0.0.4-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:cad3da377fe4d261e9c3cf1f16e6aeb3d8a223d03a58b96fbdde02305bfb2969"}, + {file = "python_kadmin_rs-0.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:97e3810eca242692f481a042588f6411c5e1cd866837404be531b1d3caa2ac0d"}, + {file = "python_kadmin_rs-0.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c03e6a8bca92551fd6b1a0b55fd83daee12f058e4e135a30fa7059369067258f"}, + {file = "python_kadmin_rs-0.0.4-pp38-pypy38_pp73-macosx_14_0_x86_64.whl", hash = "sha256:74fce6669900e845337a09760e34a243cdb6d429b235cc1c5fdf8cb8097823f7"}, + {file = "python_kadmin_rs-0.0.4-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d9ca1359232b8fabdf1bcd03148c4e328f4c37fedaa6bbbd472c8863ae16f7f0"}, + {file = "python_kadmin_rs-0.0.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e78b95a9e9fb8669421a7e5538718cae6426c5eb4d9759277775e4fc5aaa5639"}, + {file = "python_kadmin_rs-0.0.4-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:41912c50ad625927ad8a15f31a934b0c1181a63928ec2b4f389a00312e8afc5a"}, + {file = "python_kadmin_rs-0.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4fefa8a6f6ea46dc65017df1c183926c6768aab7cb69d3af5327b67635f89f2e"}, + {file = "python_kadmin_rs-0.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7e03ff3b449729f4e915f30c45015de284393418a19f37c15415a2c01f0375ca"}, + {file = "python_kadmin_rs-0.0.4.tar.gz", hash = "sha256:5f0e1c315df5f9d861dd7097cbc7b7018c354213f586bc343ef9dc750b6872a7"}, +] [[package]] name = "pytz" @@ -5567,4 +5599,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "~3.12" -content-hash = "10aa88f2f0e56cddd91adba8c39c52de92763429fb615a27c3dc218952cff808" +content-hash = "8811382f8972e6d8ff504f1a042fb365ba64f40075607ed4f3a795ffa1c96a06" diff --git a/pyproject.toml b/pyproject.toml index 5fdcca5e501f..2f0a6e577ed5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -131,8 +131,7 @@ pydantic-scim = "*" pyjwt = "*" pyrad = "*" python = "~3.12" -# Fork of python-kadmin with compilation fixes as it's unmaintained -python-kadmin = { git = "https://github.com/authentik-community/python-kadmin.git", tag = "v0.2.0" } +python-kadmin-rs = "0.0.4" pyyaml = "*" requests-oauthlib = "*" scim2-filter-parser = "*"