Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ runs:
run: |
sudo apt-get remove --purge man-db
sudo apt-get update
sudo apt-get install --no-install-recommends -y libpq-dev openssl libxmlsec1-dev pkg-config gettext libkrb5-dev krb5-kdc krb5-user krb5-admin-server
sudo apt-get install --no-install-recommends -y libpq-dev openssl libxmlsec1-dev pkg-config gettext krb5-multidev libkrb5-dev heimdal-multidev libclang-dev krb5-kdc krb5-user krb5-admin-server
- name: Install uv
if: ${{ contains(inputs.dependencies, 'python') }}
uses: astral-sh/setup-uv@2ddd2b9cb38ad8efd50337e8ab201519a34c9f24 # v5
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/v
# postgresql
libpq-dev \
# python-kadmin-rs
clang libkrb5-dev sccache \
krb5-multidev libkrb5-dev heimdal-multidev libclang-dev \
# xmlsec
libltdl-dev && \
curl https://sh.rustup.rs -sSf | sh -s -- -y
Expand Down Expand Up @@ -156,7 +156,7 @@ WORKDIR /
RUN apt-get update && \
apt-get upgrade -y && \
# Required for runtime
apt-get install -y --no-install-recommends libpq5 libmaxminddb0 ca-certificates libkrb5-3 libkadm5clnt-mit12 libkdb5-10 libltdl7 libxslt1.1 && \
apt-get install -y --no-install-recommends libpq5 libmaxminddb0 ca-certificates libkrb5-3 libkadm5clnt-mit12 libkadm5clnt7t64-heimdal libkdb5-10 libltdl7 libxslt1.1 && \
# Required for bootstrap & healtcheck
apt-get install -y --no-install-recommends runit && \
pip3 install --no-cache-dir --upgrade pip && \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 5.2.7 on 2025-10-31 15:27

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("authentik_sources_kerberos", "0003_migrate_userkerberossourceconnection_identifier"),
]

operations = [
migrations.AlterField(
model_name="kerberossource",
name="kadmin_type",
field=models.TextField(
choices=[("MIT", "Mit"), ("Heimdal", "Heimdal")],
default="MIT",
help_text="KAdmin server type",
),
),
]
25 changes: 14 additions & 11 deletions authentik/sources/kerberos/models.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
"""authentik Kerberos Source Models"""

import os
from base64 import b64decode
from pathlib import Path
from tempfile import gettempdir
from typing import Any

import gssapi
import pglock
from django.db import connection, models
from django.db.models.fields import b64decode
from django.http import HttpRequest
from django.shortcuts import reverse
from django.templatetags.static import static
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from kadmin import KAdmin, KAdminApiVersion
from kadmin.exceptions import PyKAdminException
from kadmin import KAdm5Variant, KAdmin, KAdminApiVersion
from kadmin import exceptions as kadmin_exceptions
from rest_framework.serializers import Serializer
from structlog.stdlib import get_logger

Expand Down Expand Up @@ -43,7 +43,6 @@
class KAdminType(models.TextChoices):
MIT = "MIT"
HEIMDAL = "Heimdal"
OTHER = "other"


class KerberosSource(ScheduledModel, Source):
Expand All @@ -55,7 +54,7 @@ class KerberosSource(ScheduledModel, Source):
help_text=_("Custom krb5.conf to use. Uses the system one by default"),
)
kadmin_type = models.TextField(
choices=KAdminType.choices, default=KAdminType.OTHER, help_text=_("KAdmin server type")
choices=KAdminType.choices, default=KAdminType.MIT, help_text=_("KAdmin server type")
)

sync_users = models.BooleanField(
Expand Down Expand Up @@ -239,20 +238,22 @@ def krb5_conf_path(self) -> str | None:
return str(conf_path)

def _kadmin_init(self) -> KAdmin | None:
api_version = None
variant = KAdm5Variant.MitClient
api_version = KAdminApiVersion.Version2
match self.kadmin_type:
case KAdminType.MIT:
variant = KAdm5Variant.MitClient
api_version = KAdminApiVersion.Version4
case KAdminType.HEIMDAL:
api_version = KAdminApiVersion.Version2
case KAdminType.OTHER:
variant = KAdm5Variant.HeimdalClient
api_version = KAdminApiVersion.Version2
# 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.with_password(
variant,
self.sync_principal,
self.sync_password,
api_version=api_version,
Expand All @@ -265,12 +266,14 @@ def _kadmin_init(self) -> KAdmin | None:
keytab_path.write_bytes(b64decode(self.sync_keytab))
keytab = f"FILE:{keytab_path}"
return KAdmin.with_keytab(
variant,
self.sync_principal,
keytab,
api_version=api_version,
)
if self.sync_ccache:
return KAdmin.with_ccache(
variant,
self.sync_principal,
self.sync_ccache,
api_version=api_version,
Expand All @@ -285,9 +288,9 @@ def connection(self) -> KAdmin | None:
_kadmin_connections[str(self.pk)] = self._kadmin_init()
return _kadmin_connections.get(str(self.pk), None)

def check_connection(self) -> dict[str, str]:
def check_connection(self) -> dict[str, str | bool]:
"""Check Kerberos Connection"""
status = {"status": "ok"}
status: dict[str, str | bool] = {"status": "ok"}
if not self.sync_users:
return status
with Krb5ConfContext(self):
Expand All @@ -297,7 +300,7 @@ def check_connection(self) -> dict[str, str]:
status["status"] = "no connection"
return status
status["principal_exists"] = kadm.principal_exists(self.sync_principal)
except PyKAdminException as exc:
except kadmin_exceptions.PyKAdminException as exc:
status["status"] = str(exc)
return status

Expand Down
4 changes: 2 additions & 2 deletions authentik/sources/kerberos/signals.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""authentik kerberos source signals"""

from django.dispatch import receiver
from kadmin.exceptions import PyKAdminException
from kadmin import exceptions as kadmin_exceptions
from rest_framework.serializers import ValidationError
from structlog.stdlib import get_logger

Expand Down Expand Up @@ -38,7 +38,7 @@ def kerberos_sync_password(sender, user: User, password: str, **_):
kadm,
password,
)
except PyKAdminException as exc:
except kadmin_exceptions.PyKAdminException as exc:
LOGGER.warning("failed to set Kerberos password", exc=exc, source=source)
Event.new(
EventAction.CONFIGURATION_ERROR,
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ django-channels-postgres = { workspace = true }
django-dramatiq-postgres = { workspace = true }
django-postgres-cache = { workspace = true }
opencontainers = { git = "https://github.com/vsoch/oci-python", rev = "ceb4fcc090851717a3069d78e85ceb1e86c2740c" }
python-kadmin-rs = { git = "https://github.com/authentik-community/kadmin-rs.git", rev = "2e82b7a59466b6267890f937054a97b8be006c99" }

[tool.uv.workspace]
members = [
Expand Down
21 changes: 3 additions & 18 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading