keycloak: cleanup LDAP federation
This commit is contained in:
parent
b509234aee
commit
503a9264c5
@ -2,7 +2,7 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: keycloak-ldap-federation-3
|
||||
name: keycloak-ldap-federation-4
|
||||
namespace: sso
|
||||
spec:
|
||||
backoffLimit: 2
|
||||
@ -60,6 +60,7 @@ spec:
|
||||
import os
|
||||
import time
|
||||
import urllib.parse
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
|
||||
base_url = os.environ["KEYCLOAK_SERVER"].rstrip("/")
|
||||
@ -176,11 +177,21 @@ spec:
|
||||
raise SystemExit(f"Unexpected components response: {status}")
|
||||
components = components or []
|
||||
|
||||
ldap_component = None
|
||||
for c in components:
|
||||
if c.get("providerId") == "ldap" and c.get("name") in ("openldap", "ldap"):
|
||||
ldap_component = c
|
||||
break
|
||||
ldap_components = [c for c in components if c.get("providerId") == "ldap" and c.get("id")]
|
||||
|
||||
# Select a canonical LDAP federation provider deterministically.
|
||||
# Duplicate LDAP providers can cause Keycloak admin/user queries to fail if any one of them is misconfigured.
|
||||
candidates = []
|
||||
for c in ldap_components:
|
||||
if c.get("name") not in ("openldap", "ldap"):
|
||||
continue
|
||||
cfg = c.get("config") or {}
|
||||
if (cfg.get("connectionUrl") or [None])[0] == ldap_url:
|
||||
candidates.append(c)
|
||||
if not candidates:
|
||||
candidates = [c for c in ldap_components if c.get("name") in ("openldap", "ldap")]
|
||||
candidates.sort(key=lambda x: x.get("id", ""))
|
||||
ldap_component = candidates[0] if candidates else None
|
||||
ldap_component_id = ldap_component["id"] if ldap_component else None
|
||||
|
||||
desired = {
|
||||
@ -296,4 +307,56 @@ spec:
|
||||
)
|
||||
if status not in (201, 204):
|
||||
raise SystemExit(f"Unexpected group mapper create status: {status}")
|
||||
|
||||
# Cleanup duplicate LDAP federation providers and their child components (mappers, etc).
|
||||
# Keep only the canonical provider we updated/created above.
|
||||
try:
|
||||
status, fresh_components, _ = http_json(
|
||||
"GET",
|
||||
f"{base_url}/admin/realms/{realm}/components",
|
||||
token,
|
||||
)
|
||||
if status != 200:
|
||||
raise Exception(f"unexpected components status {status}")
|
||||
fresh_components = fresh_components or []
|
||||
|
||||
dup_provider_ids = []
|
||||
for c in fresh_components:
|
||||
if c.get("providerId") != "ldap":
|
||||
continue
|
||||
if c.get("providerType") != "org.keycloak.storage.UserStorageProvider":
|
||||
continue
|
||||
cid = c.get("id")
|
||||
if not cid or cid == ldap_component_id:
|
||||
continue
|
||||
dup_provider_ids.append(cid)
|
||||
|
||||
if dup_provider_ids:
|
||||
for pid in dup_provider_ids:
|
||||
# Delete child components first.
|
||||
for child in fresh_components:
|
||||
if child.get("parentId") != pid:
|
||||
continue
|
||||
child_id = child.get("id")
|
||||
if not child_id:
|
||||
continue
|
||||
try:
|
||||
http_json(
|
||||
"DELETE",
|
||||
f"{base_url}/admin/realms/{realm}/components/{child_id}",
|
||||
token,
|
||||
)
|
||||
except urllib.error.HTTPError as e:
|
||||
print(f"WARNING: failed to delete LDAP child component {child_id} (status={e.code})")
|
||||
try:
|
||||
http_json(
|
||||
"DELETE",
|
||||
f"{base_url}/admin/realms/{realm}/components/{pid}",
|
||||
token,
|
||||
)
|
||||
except urllib.error.HTTPError as e:
|
||||
print(f"WARNING: failed to delete duplicate LDAP provider {pid} (status={e.code})")
|
||||
print(f"Cleaned up {len(dup_provider_ids)} duplicate LDAP federation providers")
|
||||
except Exception as e:
|
||||
print(f"WARNING: LDAP cleanup failed (continuing): {e}")
|
||||
PY
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user