Setup-Skript: echten API-Token für den Service-Account anlegen

Authentik legt für Service-Accounts nur ein App-Passwort an, das die API als
Bearer-Token ablehnt (403 "Token invalid/expired"). Branding wird erst gesetzt,
wenn das Portal erreichbar ist, damit die Login-Seite kein kaputtes Logo zeigt.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kerimatilganandClaude Opus 5.5 committed 2026-09-27 12:41:49 +02:00
1 parent 7aea32d59c
commit 5c1174ff90
1 file changed
+16 -5
+16 -5
View File
@@ -148,7 +148,6 @@ def ensure_service_account(groups):
print(f" = Service-Account '{SERVICE_ACCOUNT}' vorhanden") print(f" = Service-Account '{SERVICE_ACCOUNT}' vorhanden")
else: else:
res = call("POST", "/core/users/service_account/", {"name": SERVICE_ACCOUNT, "create_group": False, "expiring": False}) res = call("POST", "/core/users/service_account/", {"name": SERVICE_ACCOUNT, "create_group": False, "expiring": False})
token_key = res.get("token")
user = {"pk": res.get("user_pk")} user = {"pk": res.get("user_pk")}
print(f" + Service-Account '{SERVICE_ACCOUNT}' angelegt") print(f" + Service-Account '{SERVICE_ACCOUNT}' angelegt")
@@ -170,15 +169,27 @@ def ensure_service_account(groups):
else: else:
print(f" = Gruppe '{SERVICE_GROUP}' vorhanden") print(f" = Gruppe '{SERVICE_GROUP}' vorhanden")
if not token_key and APPLY: # Der Service-Account bekommt von Authentik nur ein App-Passwort (intent=app_password),
tokens = [t for t in results(f"/core/tokens/?user__username={SERVICE_ACCOUNT}") if t["intent"] == "api"] # das die API nicht als Bearer-Token akzeptiert. Deshalb eigener API-Token.
if tokens: if APPLY and user.get("pk"):
token_key = call("GET", f"/core/tokens/{tokens[0]['identifier']}/view_key/")["key"] ident = f"{SERVICE_ACCOUNT}-api"
if not results(f"/core/tokens/?identifier={ident}"):
call("POST", "/core/tokens/", {
"identifier": ident, "user": user["pk"], "intent": "api", "expiring": False,
"description": "Portal: App-Liste pro Benutzer lesen",
})
print(f" + API-Token '{ident}' angelegt")
token_key = call("GET", f"/core/tokens/{ident}/view_key/")["key"]
return user, token_key return user, token_key
def branding(): def branding():
step("4. Branding") step("4. Branding")
try:
urllib.request.urlopen(f"{PORTAL_URL}/icon-192.png", timeout=10)
except Exception:
print(f" - übersprungen: {PORTAL_URL} ist noch nicht erreichbar (sonst kaputtes Logo auf der Login-Seite)")
return
brand = next((b for b in results("/core/brands/") if b.get("default")), None) or results("/core/brands/")[0] brand = next((b for b in results("/core/brands/") if b.get("default")), None) or results("/core/brands/")[0]
call("PATCH", f"/core/brands/{brand['brand_uuid']}/", { call("PATCH", f"/core/brands/{brand['brand_uuid']}/", {
"branding_title": "Handy-Insel", "branding_title": "Handy-Insel",