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:
@@ -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"]
|
||||
|
||||
117
init/sync.sh
117
init/sync.sh
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user