From 2a2d8ba0556347f102a0f2223e25183f3d419ba3 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 14 Aug 2026 18:53:37 +0200 Subject: [PATCH] Align provisioned identities with OIDC subjects --- identity-provisioner/provisioner.py | 15 +++++++++++++-- identity-provisioner/server.py | 4 ++-- sso-mfa/k8s/user-engine/runtime.yaml | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/identity-provisioner/provisioner.py b/identity-provisioner/provisioner.py index e2d6bcd..c350aa1 100644 --- a/identity-provisioner/provisioner.py +++ b/identity-provisioner/provisioner.py @@ -68,9 +68,10 @@ mutation CreateUser($id: String!, $email: String!, $display: String!) { except Exception: pass raise - return Result("netkingdom-lldap", username, "password_setup_required", resumed) + return Result("netkingdom-lldap", _oidc_subject(username), "password_setup_required", resumed) def suspend(self, subject: str) -> Result: + subject = _directory_username(subject) token = self._login() _, groups = self._directory(token) group_id = self._ensure_group(token, groups, "netkingdom-suspended") @@ -78,6 +79,7 @@ mutation CreateUser($id: String!, $email: String!, $display: String!) { return Result("netkingdom-lldap", subject, "suspended", False) def reactivate(self, subject: str) -> Result: + subject = _directory_username(subject) token = self._login() _, groups = self._directory(token) group = next((item for item in groups if item.get("displayName") == "netkingdom-suspended"), None) @@ -89,6 +91,7 @@ mutation Remove($userId: String!, $groupId: Int!) { return Result("netkingdom-lldap", subject, "active", False) def deprovision(self, subject: str) -> Result: + subject = _directory_username(subject) token = self._login() if self._user(token, subject) is None: return Result("netkingdom-lldap", subject, "deprovisioned", True) @@ -249,7 +252,7 @@ def dispatch( if path == "/v1/identities/reconcile": return provisioner.reconcile(payload) _required(payload, "external_subject", "idempotency_key", "correlation_id") - subject = str(payload["external_subject"]) + subject = _directory_username(str(payload["external_subject"])) if path == "/v1/identities/suspend": return provisioner.suspend(subject) if path == "/v1/identities/reactivate": @@ -305,3 +308,11 @@ def _desired(payload: dict[str, Any]) -> tuple[str, str, set[str], str]: if desired_status == "suspended": groups.add("netkingdom-suspended") return subject, email, groups, desired_status + + +def _directory_username(subject: str) -> str: + return subject[4:].split(",", 1)[0] if subject.startswith("uid=") else subject + + +def _oidc_subject(username: str) -> str: + return f"uid={username},ou=people,dc=netkingdom,dc=local" diff --git a/identity-provisioner/server.py b/identity-provisioner/server.py index 6eb04bc..596b3e7 100644 --- a/identity-provisioner/server.py +++ b/identity-provisioner/server.py @@ -6,7 +6,7 @@ import os from urllib.parse import parse_qs, urlsplit import secrets -from provisioner import LLDAPProvisioner, dispatch +from provisioner import LLDAPProvisioner, _directory_username, dispatch from password_setup import LLDAPPasswordSetter, PasswordSetupGrants @@ -46,7 +46,7 @@ class Handler(BaseHTTPRequestHandler): response = asdict(result) if path == "/v1/identities/provision" and result.status == "password_setup_required": response["password_setup_url"] = self.password_setups.issue( - result.external_subject + _directory_username(result.external_subject) ) self._send(200, response) diff --git a/sso-mfa/k8s/user-engine/runtime.yaml b/sso-mfa/k8s/user-engine/runtime.yaml index 199e8f8..2fde21c 100644 --- a/sso-mfa/k8s/user-engine/runtime.yaml +++ b/sso-mfa/k8s/user-engine/runtime.yaml @@ -45,7 +45,7 @@ spec: seccompProfile: {type: RuntimeDefault} containers: - name: portal - image: forgejo.coulomb.social/coulomb/user-engine@sha256:6e1909fab6546ba5ee7c23fbdcd5b8b8a6550a8e509bff36ea37391c9d684083 + image: forgejo.coulomb.social/coulomb/user-engine@sha256:e3b5f65bafc1c0260dfdf2567a52766e67506ceb878a51759a2e9a307c4b5eb8 imagePullPolicy: IfNotPresent ports: [{name: http, containerPort: 8080}] env: