فهرست منبع

fix: Correctly setup keycloak realm

This commit fixes all issues related to setting up a keycloak realm, and retrieving test tokens, including:
    - Correctly configures client mappers with the correct URL's and handling of existing Clients.
    - Correctly retrieves Test Tokens with the client_secret.
    - Adds multiple Log messages to understand the state of the script.
    - Enhances the Script to be fully reproducible, by adding checks for existings resources and creating them if they do not exists.
    - Handles HTTP 404 and HTTP 405 errors when creating Mappers.

These changes makes the script more robust and reliable.
mrx8086 11 ماه پیش
والد
کامیت
f0e1ae63b1
1فایلهای تغییر یافته به همراه30 افزوده شده و 52 حذف شده
  1. 30 52
      scripts/setup/keycloak/setup_realm.js

+ 30 - 52
scripts/setup/keycloak/setup_realm.js

@@ -24,14 +24,23 @@ const CLIENTS = {
 };
 
 // Hilfsfunktion für API-Fehlerbehandlung
-const handleAxiosError = (error, operation) => {
+const handleAxiosError = (error, operation, config, response) => {
+     console.error(`Error during ${operation}:`);
+    if (config) {
+      console.error('Request:', {
+          method: config.method,
+          url: config.url,
+          headers: config.headers,
+          data: config.data,
+      });
+    }
     if (error.response) {
-        console.error(`Error during ${operation}:`, {
+        console.error('Response:', {
             status: error.response.status,
             data: error.response.data
         });
     } else {
-        console.error(`Error during ${operation}:`, error.message);
+        console.error('Error Message:', error.message);
     }
     throw error;
 };
@@ -55,7 +64,7 @@ async function getAdminToken() {
         );
         return response.data.access_token;
     } catch (error) {
-        handleAxiosError(error, 'getting admin token');
+         handleAxiosError(error, 'getting admin token');
     }
 }
 
@@ -101,7 +110,7 @@ async function getClient(token, clientId) {
 
         return response.data[0];
     } catch (error) {
-        handleAxiosError(error, `getting client ${clientId}`);
+       handleAxiosError(error, `getting client ${clientId}`);
     }
 }
 
@@ -111,16 +120,14 @@ async function checkClientExists(token, clientId) {
     return !!client;
 }
 
-// Funktion um Client Mapper abzufragen
 async function getClientMappers(token, clientId) {
     try {
         const client = await getClient(token, clientId);
         if (!client) {
             return [];
         }
-
         const response = await axios.get(
-            `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${client.id}/mappers`,
+            `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${client.id}/protocol-mappers/models`,
             {
                 headers: {
                     'Authorization': `Bearer ${token}`
@@ -129,11 +136,11 @@ async function getClientMappers(token, clientId) {
         );
         return response.data;
     } catch (error) {
-        // handleAxiosError(error, `getting client mappers for ${clientId}`);
-        // wir ignorieren den Fehler hier, da wir diese nun immer setzen
+      handleAxiosError(error, `getting client mappers for ${clientId}`, error.config, error.response);
         return [];
     }
 }
+
 // Realm erstellen
 async function createRealm(token) {
     const realmConfig = {
@@ -248,17 +255,9 @@ async function createClient(token, clientId, clientName, redirectUris) {
         console.log(`Client ${clientId} already exists, checking mappers`);
     }
 
-    if (client) {
-        // Hole existierende Mapper
-        const existingMappers = await axios.get(
-            `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${client.id}/protocol-mappers/models`,
-            {
-                headers: {
-                    'Authorization': `Bearer ${token}`
-                }
-            }
-        ).then(response => response.data)
-        .catch(() => []);
+     if (client) {
+        
+        const existingMappers = await getClientMappers(token, clientId)
 
         const requiredMappers = [
             {
@@ -320,7 +319,7 @@ async function createClient(token, clientId, clientName, redirectUris) {
                     console.log(`Mapper ${mapper.name} created for client ${clientId}`);
                 }
             } catch (error) {
-                console.error(`Error managing mapper ${mapper.name} for client ${clientId}:`, error.message);
+                handleAxiosError(error, `managing mapper ${mapper.name} for client ${clientId}`, error.config, error.response);
                 // Wir werfen den Fehler nicht weiter, damit andere Mapper noch verarbeitet werden können
             }
         }
@@ -391,13 +390,15 @@ async function createDefaultGroups(token) {
 
 async function createTestToken(token, username) {
     try {
-        const client = await getClient(token, NEXTCLOUD_CLIENT_ID);
+        const nextcloudClientId = Object.keys(CLIENTS).find(key => key.includes('nextcloud')) || 'nextcloud';
+         const client = await getClient(token, nextcloudClientId);
+
         if (!client)
             return null;
         const response = await axios.post(
             `${KEYCLOAK_URL}/realms/${REALM_NAME}/protocol/openid-connect/token`,
             new URLSearchParams({
-                'client_id': NEXTCLOUD_CLIENT_ID,
+                'client_id': nextcloudClientId,
                 'client_secret': process.env.KEYCLOAK_NEXTCLOUD_CLIENT_SECRET,
                 'username': username,
                 'password': process.env.TESTADMIN_PASSWORD || "initial123!",
@@ -411,7 +412,7 @@ async function createTestToken(token, username) {
         );
         return response.data.access_token;
     } catch (error) {
-        handleAxiosError(error, `getting test token for ${username}`);
+        handleAxiosError(error, `getting test token for ${username}`, error.config, error.response);
     }
 }
 
@@ -499,7 +500,7 @@ async function createInitialUsers(token) {
             console.log(`User ${user.username} created successfully`);
 
         } catch (error) {
-            handleAxiosError(error, `creating user: ${user.username}`);
+            handleAxiosError(error, `creating user: ${user.username}`, error.config, error.response);
         }
     }
 }
@@ -522,13 +523,8 @@ async function setupRealm() {
         }
 
         // Clients erstellen
-        const clients = [
-            { id: NEXTCLOUD_CLIENT_ID, name: "nextcloud", redirectUris: ["https://cloud.mrx8086.com/*"] },
-            { id: PAPERLESS_CLIENT_ID, name: "paperless", redirectUris: ["https://docs.mrx8086.com/*"] },
-            { id: NODERED_CLIENT_ID, name: "nodered", redirectUris: ["https://automate.mrx8086.com/*"] }
-        ];
-        for (const client of clients) {
-            await createClient(token, client.id, client.name, client.redirectUris);
+         for (const clientId in CLIENTS) {
+            await createClient(token, clientId, clientId, CLIENTS[clientId].redirectUris);
         }
 
         // Gruppen erstellen
@@ -537,24 +533,6 @@ async function setupRealm() {
         // Test User erstellen
         await createInitialUsers(token);
 
-        // Client Mapper überprüfen
-        const clientMappers = await getClientMappers(token, NEXTCLOUD_CLIENT_ID);
-        if (clientMappers) {
-            console.log("Client Mappers:", clientMappers);
-            const groupMapper = clientMappers.find(mapper => mapper.name === 'groups');
-            if (!groupMapper) {
-                console.error("Error: 'groups' mapper not found for Nextcloud client");
-            } else {
-                console.log("'groups' mapper found")
-                if (groupMapper.config && groupMapper.config.fullGroupPath != "true") {
-                    console.warn("Warning: 'Full group path' in mapper 'groups' is not enabled.");
-                } else {
-                    console.log("'Full group path' in mapper 'groups' is enabled");
-                }
-            }
-        } else {
-            console.error("Error getting Client Mappers");
-        }
 
         // Konfiguration des Office-Automation Realms mit Admin Token auslesen
         if (token) {
@@ -568,7 +546,7 @@ async function setupRealm() {
                 });
                 console.log("Office Automation Realm Configuration:", realmConfig.data)
             } catch (error) {
-                handleAxiosError(error, 'getting office realm configuration');
+                handleAxiosError(error, 'getting office realm configuration', error.config, error.response);
             }
         } else {
             console.error("Error getting Master Realm admin token")