xpeditis2.0/infra/prod/scripts/harden-seed-data.sh
2026-09-07 21:40:50 +02:00

152 lines
5.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# =============================================================================
# Neutralisation des comptes de demonstration -- OUTIL DE SECOURS ET D'AUDIT
# =============================================================================
#
# LE CAS NOMINAL N'A PLUS BESOIN DE CE SCRIPT.
#
# Le traitement est desormais fait par les migrations, donc automatiquement et
# sans risque d'oubli :
#
# 1730000000007-SeedTestUsers ne s'execute plus si
# NODE_ENV=production
# 1756000000000-NeutralizeSeedAccountsInProduction filet de securite
# 1756000000001-BootstrapAdminFromEnv cree VOTRE administrateur
#
# Ce script reste utile dans trois situations :
#
# - une base de production migree AVANT l'ajout de la garde NODE_ENV ;
# - un deploiement ou NODE_ENV n'etait pas correctement positionne (le journal
# du Job de migration affiche alors "Seeded test users successfully") ;
# - une verification manuelle : il affiche l'etat des comptes sans rien
# changer s'il n'y a rien a changer.
#
# ssh deploy@<db-01>
# sudo bash /opt/xpeditis/infra-prod/scripts/harden-seed-data.sh
#
# RAPPEL DU PROBLEME
#
# La migration 1730000000007-SeedTestUsers cree trois comptes dont le mot de
# passe est ecrit en clair dans le depot :
#
# admin@xpeditis.com role ADMIN Password123!
# manager@xpeditis.com role MANAGER Password123!
# user@xpeditis.com role USER Password123!
#
# Sur une base de production, cela donne un acces complet a la plateforme a
# quiconque a lu le depot.
#
# Ce script ne SUPPRIME pas les lignes (des cles etrangeres peuvent y pointer,
# et une suppression en cascade dans audit_logs serait pire). Il :
# 1. renomme les adresses vers un domaine invalide -- ce qui libere au passage
# admin@xpeditis.com pour votre vrai compte ;
# 2. remplace le mot de passe par une valeur aleatoire inutilisable ;
# 3. desactive les comptes (is_active = false).
#
# Idempotent : peut etre relance sans risque.
set -euo pipefail
COMPOSE_DIR="${COMPOSE_DIR:-/opt/xpeditis/data-node}"
ENV_FILE="${ENV_FILE:-${COMPOSE_DIR}/.env.data}"
[[ -f "$ENV_FILE" ]] || { echo "Fichier d'environnement introuvable : $ENV_FILE" >&2; exit 1; }
# shellcheck disable=SC1090
set -a; source "$ENV_FILE"; set +a
psql_run() {
docker compose -f "${COMPOSE_DIR}/docker-compose.data.yml" --env-file "$ENV_FILE" \
exec -T -u postgres postgres psql -v ON_ERROR_STOP=1 -d "$POSTGRES_DB" "$@"
}
echo ">>> Etat avant intervention"
psql_run -c "
SELECT email, role, is_active
FROM users
WHERE email IN ('admin@xpeditis.com','manager@xpeditis.com','user@xpeditis.com');
"
echo
echo ">>> Neutralisation"
psql_run <<'SQL'
BEGIN;
-- Mot de passe remplace par une valeur aleatoire : le format reste un hash
-- Argon2 valide en apparence, mais aucun mot de passe ne peut y correspondre.
UPDATE users
SET
email = 'seed-desactive-' || substr(id::text, 1, 8) || '@invalid.local',
-- md5(random()) plutot que gen_random_bytes : pas besoin de l'extension
-- pgcrypto, qui n'est pas installee sur cette base.
password_hash = '$argon2id$v=19$m=65536,t=3,p=4$' || md5(random()::text)
|| '$' || md5(random()::text) || md5(clock_timestamp()::text),
is_active = false,
updated_at = NOW()
WHERE email IN ('admin@xpeditis.com', 'manager@xpeditis.com', 'user@xpeditis.com');
COMMIT;
SQL
echo
echo ">>> Etat apres intervention"
psql_run -c "
SELECT email, role, is_active
FROM users
WHERE email LIKE 'seed-desactive-%@invalid.local';
"
echo
echo ">>> Controle : aucun compte de demonstration ne doit subsister"
RESTE=$(psql_run -tAc "
SELECT count(*) FROM users
WHERE email IN ('admin@xpeditis.com','manager@xpeditis.com','user@xpeditis.com');
")
if [[ "$RESTE" != "0" ]]; then
echo "ECHEC : ${RESTE} compte(s) de demonstration encore actifs." >&2
exit 1
fi
echo "OK : aucun compte de demonstration actif."
echo
echo ">>> Organisations de demonstration presentes (a examiner, non modifiees)"
# Non supprimees automatiquement : les comptes desactives y sont rattaches, et
# une suppression en cascade toucherait aussi audit_logs.
psql_run -c "
SELECT id, name, created_at
FROM organizations
WHERE name IN ('Test Freight Forwarder Inc.','Demo Shipping Company','Sample Shipper Ltd.');
"
cat <<'NEXT'
-----------------------------------------------------------------------------
Etape suivante : disposer d'un administrateur.
La migration 1756000000001-BootstrapAdminFromEnv s'en charge normalement, a
partir de BOOTSTRAP_ADMIN_EMAIL (ConfigMap). Si elle a ete ignoree parce qu'un
ADMIN actif existait alors -- typiquement le compte de demonstration que ce
script vient de neutraliser -- relancez simplement le Job de migration :
kubectl -n xpeditis-prod delete job -l app.kubernetes.io/name=xpeditis-migrate
# puis redeployez, ou rejouez le Job pour le tag courant
Elle ne rejouera pas les migrations deja appliquees ; pour forcer uniquement
l'amorcage, creez votre compte a la main :
1. Inscrivez-vous sur https://app.xpeditis.com/fr/register
2. Promouvez le compte :
UPDATE users SET role = 'ADMIN' WHERE email = '<votre adresse>';
Dans les deux cas, verifiez qu'il n'existe qu'un seul ADMIN actif :
SELECT email, role, is_active FROM users WHERE role = 'ADMIN';
Puis controlez depuis l'exterieur que l'ancien compte est bien mort :
curl -s -o /dev/null -w '%{http_code}\n' -X POST \
https://api.xpeditis.com/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"admin@xpeditis.com","password":"Password123!"}'
# Attendu : 401 (et surtout pas 200 ni 201)
-----------------------------------------------------------------------------
NEXT