Switch admin to jovann@e-cosplay.fr + disable default admin

- Rename the bootstrap human admin from jovann@siteconseil.fr to
  jovann@e-cosplay.fr in docker-compose env vars and in the realm
  import JSON. Keycloak identifies users by username so a new user
  is created on the next sync run; the old jovann@siteconseil.fr
  is left in place and can be deleted manually from the admin UI.
- Introduce a service account client `sync-bot` in the master
  realm (confidential, service accounts enabled, direct grants off)
  granted the `admin` realm role. sync.sh now authenticates via
  client_credentials, falling back to the bootstrap admin only on
  the very first run — so reconciliation keeps working after the
  default admin is disabled.
- Add disable_default_admin() at the end of the sync script. It
  first verifies that sync-bot can authenticate, then flips the
  `admin` user's `enabled` flag to false. Idempotent and safe:
  refuses to run if sync-bot auth is broken, and is a no-op if
  admin is already disabled.
- SYNC_BOT_CLIENT / SYNC_BOT_SECRET env vars added to the init
  container for both bootstrap authentication and service client
  secret reconciliation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-04-10 16:15:46 +02:00
parent 1ed5c020b1
commit 832be361c7
3 changed files with 117 additions and 8 deletions

View File

@@ -69,10 +69,12 @@ services:
SMTP_PASSWORD: BBdgb6KxRQ8mNcpWFJsZCJxbSGNdgLhKFiITMErfBlQP
LOGIN_THEME: ecosplay
ECOSPLAY_GROUPS: "gp_asso gp_contest gp_mail gp_mailling gp_member gp_ndd gp_sign gp_ticket super_admin_asso superadmin"
ADMIN_USER_USERNAME: jovann@siteconseil.fr
ADMIN_USER_USERNAME: jovann@e-cosplay.fr
ADMIN_USER_PASSWORD: Shoko1997@
ADMIN_USER_FIRSTNAME: Jovann
ADMIN_USER_LASTNAME: Serreau
SYNC_BOT_CLIENT: sync-bot
SYNC_BOT_SECRET: dev-sync-bot-9f3b2a7c1e8d4f6a0b5c2e1d7f8a4b3c
volumes:
- ./init/sync.sh:/opt/init/sync.sh:ro
entrypoint: ["/bin/bash", "/opt/init/sync.sh"]

View File

@@ -16,6 +16,7 @@
# ECOSPLAY_GROUPS (space-separated list)
# ADMIN_USER_USERNAME, ADMIN_USER_PASSWORD,
# ADMIN_USER_FIRSTNAME, ADMIN_USER_LASTNAME
# SYNC_BOT_CLIENT, SYNC_BOT_SECRET
# =============================================================
set -euo pipefail
@@ -29,16 +30,44 @@ warn() { printf ' \033[1;33m! %s\033[0m\n' "$*"; }
# -------------------------------------------------------------
# Wait for Keycloak and authenticate
# -------------------------------------------------------------
log "Waiting for Keycloak at ${KC_SERVER}"
until $KC config credentials \
# Two authentication paths:
# 1. sync-bot service account (preferred, used after bootstrap).
# 2. Default bootstrap admin (used on first run, before sync-bot
# has been created and granted the admin role).
# -------------------------------------------------------------
KC_LOGIN_MODE=none
login_as_sync_bot() {
[ -n "${SYNC_BOT_SECRET:-}" ] || return 1
$KC config credentials \
--server "$KC_SERVER" \
--realm master \
--client "$SYNC_BOT_CLIENT" \
--secret "$SYNC_BOT_SECRET" >/dev/null 2>&1
}
login_as_admin() {
$KC config credentials \
--server "$KC_SERVER" \
--realm master \
--user "$KC_ADMIN" \
--password "$KC_ADMIN_PASSWORD" >/dev/null 2>&1; do
info "not ready yet, retrying in 5s..."
--password "$KC_ADMIN_PASSWORD" >/dev/null 2>&1
}
log "Authenticating to Keycloak at ${KC_SERVER}"
while true; do
if login_as_sync_bot; then
KC_LOGIN_MODE=sync-bot
break
fi
if login_as_admin; then
KC_LOGIN_MODE=bootstrap
break
fi
info "Keycloak not ready / no valid credentials yet, retrying in 5s..."
sleep 5
done
info "Keycloak ready."
info "Authenticated (mode=$KC_LOGIN_MODE)"
# -------------------------------------------------------------
# Helpers
@@ -171,6 +200,72 @@ ensure_client() {
info "+ client $2 ($1)"
}
ensure_sync_bot() {
# Create (or keep in sync) the automation service client in master.
# Grants its service account the master 'admin' realm role so that
# sync.sh can authenticate with client_credentials after the default
# admin user is disabled.
local cid
cid=$(client_internal_id master "$SYNC_BOT_CLIENT")
if [ -z "$cid" ]; then
$KC create clients -r master \
-s "clientId=$SYNC_BOT_CLIENT" \
-s "name=Sync Bot" \
-s "description=Service account used by init/sync.sh for unattended config reconciliation" \
-s 'protocol=openid-connect' \
-s 'enabled=true' \
-s 'publicClient=false' \
-s "secret=$SYNC_BOT_SECRET" \
-s 'standardFlowEnabled=false' \
-s 'implicitFlowEnabled=false' \
-s 'directAccessGrantsEnabled=false' \
-s 'serviceAccountsEnabled=true' >/dev/null
cid=$(client_internal_id master "$SYNC_BOT_CLIENT")
info "+ service client $SYNC_BOT_CLIENT (master)"
else
$KC update "clients/$cid" -r master \
-s 'enabled=true' \
-s 'serviceAccountsEnabled=true' \
-s 'standardFlowEnabled=false' \
-s 'directAccessGrantsEnabled=false' \
-s "secret=$SYNC_BOT_SECRET" >/dev/null
info "= service client $SYNC_BOT_CLIENT (master)"
fi
# Grant 'admin' realm role to the auto-generated service account user
$KC add-roles -r master \
--uusername "service-account-${SYNC_BOT_CLIENT}" \
--rolename admin >/dev/null 2>&1 || true
info " service-account-${SYNC_BOT_CLIENT} -> realm role admin"
}
disable_default_admin() {
# Only disable once we're sure sync-bot can authenticate (otherwise
# next run would be locked out).
if ! login_as_sync_bot; then
warn "sync-bot auth not working, refusing to disable default admin"
login_as_admin >/dev/null 2>&1 || true
return
fi
# Re-login as admin to perform the disable action (sync-bot's token
# was used only for verification)
login_as_admin >/dev/null 2>&1 || true
local admin_id current
admin_id=$(user_id master "$KC_ADMIN")
if [ -z "$admin_id" ]; then
info "no '$KC_ADMIN' user in master, nothing to disable"
return
fi
current=$($KC get "users/$admin_id" -r master --fields enabled 2>/dev/null \
| sed -n 's/.*"enabled"[ ]*:[ ]*\(true\|false\).*/\1/p' | head -n1)
if [ "$current" = "false" ]; then
info "= default admin user '$KC_ADMIN' already disabled"
return
fi
$KC update "users/$admin_id" -r master -s enabled=false >/dev/null
info "+ default admin user '$KC_ADMIN' disabled"
}
# =============================================================
# Master realm: SMTP, theme, locale
# =============================================================
@@ -191,6 +286,12 @@ $KC update realms/master \
-s "defaultLocale=fr"
info "master realm updated"
# =============================================================
# Master realm: automation service account (sync-bot)
# =============================================================
log "Ensuring sync-bot service client in master realm"
ensure_sync_bot
# =============================================================
# Master realm: global Keycloak admin user
# =============================================================
@@ -236,4 +337,10 @@ else
warn "ecosplay realm not found — will be imported on next boot"
fi
# =============================================================
# Disable default bootstrap admin (only after sync-bot is proven)
# =============================================================
log "Disabling default bootstrap admin user"
disable_default_admin
log "Sync complete"

View File

@@ -69,8 +69,8 @@
"users": [
{
"username": "jovann@siteconseil.fr",
"email": "jovann@siteconseil.fr",
"username": "jovann@e-cosplay.fr",
"email": "jovann@e-cosplay.fr",
"firstName": "Jovann",
"lastName": "Serreau",
"enabled": true,