#!/bin/bash # Configuration Keycloak pour UnionFlow # Auteur: UnionFlow Team echo "🔐 Configuration automatique de Keycloak pour UnionFlow" echo "=======================================================" # Variables de configuration KEYCLOAK_URL="http://localhost:8180" ADMIN_USER="admin" ADMIN_PASSWORD="admin" REALM_NAME="unionflow" CLIENT_ID="unionflow-server" CLIENT_SECRET="unionflow-secret-2025" # Couleurs pour l'affichage RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Fonction pour obtenir le token d'accès admin get_admin_token() { echo -e "${YELLOW}📡 Obtention du token d'administration...${NC}" TOKEN_RESPONSE=$(curl -s -X POST "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=$ADMIN_USER&password=$ADMIN_PASSWORD&grant_type=password&client_id=admin-cli") if [ $? -eq 0 ]; then ACCESS_TOKEN=$(echo $TOKEN_RESPONSE | grep -o '"access_token":"[^"]*' | cut -d'"' -f4) if [ -n "$ACCESS_TOKEN" ]; then echo -e "${GREEN}✅ Token obtenu avec succès${NC}" return 0 fi fi echo -e "${RED}❌ Erreur lors de l'obtention du token${NC}" echo "Réponse: $TOKEN_RESPONSE" exit 1 } # Fonction pour créer le realm UnionFlow create_realm() { echo -e "${YELLOW}🏛️ Création du realm '$REALM_NAME'...${NC}" # Vérifier si le realm existe déjà REALM_CHECK=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -w "%{http_code}") if [[ "$REALM_CHECK" == *"200"* ]]; then echo -e "${YELLOW}⚠️ Le realm '$REALM_NAME' existe déjà. Suppression...${NC}" curl -s -X DELETE "$KEYCLOAK_URL/admin/realms/$REALM_NAME" \ -H "Authorization: Bearer $ACCESS_TOKEN" sleep 2 fi # Créer le nouveau realm REALM_CONFIG='{ "realm": "'$REALM_NAME'", "displayName": "UnionFlow", "enabled": true, "registrationAllowed": true, "registrationEmailAsUsername": true, "rememberMe": true, "verifyEmail": false, "loginWithEmailAllowed": true, "duplicateEmailsAllowed": false, "resetPasswordAllowed": true, "editUsernameAllowed": false, "sslRequired": "external", "defaultLocale": "fr", "internationalizationEnabled": true, "supportedLocales": ["fr", "en"] }' RESPONSE=$(curl -s -X POST "$KEYCLOAK_URL/admin/realms" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "$REALM_CONFIG" \ -w "%{http_code}") if [[ "$RESPONSE" == *"201"* ]]; then echo -e "${GREEN}✅ Realm '$REALM_NAME' créé avec succès${NC}" sleep 2 else echo -e "${RED}❌ Erreur lors de la création du realm${NC}" echo "Réponse: $RESPONSE" exit 1 fi } # Fonction pour créer le client create_client() { echo -e "${YELLOW}🔧 Création du client '$CLIENT_ID'...${NC}" CLIENT_CONFIG='{ "clientId": "'$CLIENT_ID'", "name": "UnionFlow Server API", "description": "Client pour l API serveur UnionFlow", "enabled": true, "clientAuthenticatorType": "client-secret", "secret": "'$CLIENT_SECRET'", "protocol": "openid-connect", "publicClient": false, "serviceAccountsEnabled": true, "authorizationServicesEnabled": true, "standardFlowEnabled": true, "implicitFlowEnabled": false, "directAccessGrantsEnabled": true, "redirectUris": ["http://localhost:8080/*", "http://localhost:3000/*"], "webOrigins": ["http://localhost:8080", "http://localhost:3000", "*"], "fullScopeAllowed": true, "attributes": { "access.token.lifespan": "3600" } }' RESPONSE=$(curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "$CLIENT_CONFIG" \ -w "%{http_code}") if [[ "$RESPONSE" == *"201"* ]]; then echo -e "${GREEN}✅ Client '$CLIENT_ID' créé avec succès${NC}" echo -e "${CYAN}🔑 Secret du client: $CLIENT_SECRET${NC}" else echo -e "${RED}❌ Erreur lors de la création du client${NC}" echo "Réponse: $RESPONSE" exit 1 fi } # Fonction pour créer les rôles create_roles() { echo -e "${YELLOW}👥 Création des rôles...${NC}" ROLES=("ADMIN" "PRESIDENT" "SECRETAIRE" "TRESORIER" "GESTIONNAIRE_MEMBRE" "ORGANISATEUR_EVENEMENT" "MEMBRE") DESCRIPTIONS=("Administrateur système avec tous les droits" "Président de l'union avec droits de gestion complète" "Secrétaire avec droits de gestion des membres et événements" "Trésorier avec droits de gestion financière" "Gestionnaire des membres avec droits de CRUD sur les membres" "Organisateur d'événements avec droits de gestion des événements" "Membre standard avec droits de consultation") for i in "${!ROLES[@]}"; do ROLE_NAME="${ROLES[$i]}" ROLE_DESC="${DESCRIPTIONS[$i]}" ROLE_CONFIG='{ "name": "'$ROLE_NAME'", "description": "'$ROLE_DESC'" }' RESPONSE=$(curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "$ROLE_CONFIG" \ -w "%{http_code}") if [[ "$RESPONSE" == *"201"* ]]; then echo -e " ${GREEN}✅ Rôle '$ROLE_NAME' créé${NC}" else echo -e " ${YELLOW}⚠️ Rôle '$ROLE_NAME' existe déjà ou erreur${NC}" fi done } # Fonction pour créer un utilisateur create_user() { local username=$1 local email=$2 local firstname=$3 local lastname=$4 local password=$5 shift 5 local roles=("$@") USER_CONFIG='{ "username": "'$username'", "email": "'$email'", "firstName": "'$firstname'", "lastName": "'$lastname'", "enabled": true, "emailVerified": true, "credentials": [{ "type": "password", "value": "'$password'", "temporary": false }] }' RESPONSE=$(curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "$USER_CONFIG" \ -w "%{http_code}") if [[ "$RESPONSE" == *"201"* ]]; then echo -e " ${GREEN}✅ Utilisateur '$username' créé${NC}" # Récupérer l'ID de l'utilisateur USER_ID=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users?username=$username" \ -H "Authorization: Bearer $ACCESS_TOKEN" | \ grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f4) if [ -n "$USER_ID" ]; then # Assigner les rôles for role in "${roles[@]}"; do # Récupérer les détails du rôle ROLE_DATA=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles/$role" \ -H "Authorization: Bearer $ACCESS_TOKEN") if [[ "$ROLE_DATA" == *'"name"'* ]]; then ROLE_ASSIGNMENT="[$ROLE_DATA]" curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users/$USER_ID/role-mappings/realm" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "$ROLE_ASSIGNMENT" > /dev/null echo -e " ${GREEN}✅ Rôle '$role' assigné à '$username'${NC}" fi done fi else echo -e " ${YELLOW}⚠️ Utilisateur '$username' existe déjà ou erreur${NC}" fi } # Fonction pour créer les utilisateurs de test create_test_users() { echo -e "${YELLOW}👤 Création des utilisateurs de test...${NC}" create_user "admin" "admin@unionflow.dev" "Administrateur" "Système" "admin123" "ADMIN" "PRESIDENT" create_user "president" "president@unionflow.dev" "Jean" "Dupont" "president123" "PRESIDENT" "MEMBRE" create_user "secretaire" "secretaire@unionflow.dev" "Marie" "Martin" "secretaire123" "SECRETAIRE" "GESTIONNAIRE_MEMBRE" "MEMBRE" create_user "tresorier" "tresorier@unionflow.dev" "Pierre" "Durand" "tresorier123" "TRESORIER" "MEMBRE" create_user "membre1" "membre1@unionflow.dev" "Sophie" "Bernard" "membre123" "MEMBRE" } # Script principal main() { # Obtenir le token d'administration get_admin_token # Créer le realm create_realm # Créer le client create_client # Créer les rôles create_roles # Créer les utilisateurs de test create_test_users echo "" echo -e "${GREEN}🎉 Configuration Keycloak terminée avec succès !${NC}" echo -e "${GREEN}=======================================${NC}" echo -e "${CYAN}📋 Informations de configuration :${NC}" echo -e " • Realm: $REALM_NAME" echo -e " • Client ID: $CLIENT_ID" echo -e " • Client Secret: $CLIENT_SECRET" echo -e " • URL Auth Server: $KEYCLOAK_URL/realms/$REALM_NAME" echo "" echo -e "${CYAN}👤 Utilisateurs de test créés :${NC}" echo -e " • admin / admin123 (ADMIN, PRESIDENT)" echo -e " • president / president123 (PRESIDENT, MEMBRE)" echo -e " • secretaire / secretaire123 (SECRETAIRE, GESTIONNAIRE_MEMBRE, MEMBRE)" echo -e " • tresorier / tresorier123 (TRESORIER, MEMBRE)" echo -e " • membre1 / membre123 (MEMBRE)" echo "" echo -e "${YELLOW}🔧 Prochaine étape: Mettre à jour application.properties${NC}" } # Exécuter le script principal main