| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- // setup_realm.js
- import dotenv from 'dotenv';
- import axios from 'axios';
- // Lade Umgebungsvariablen
- dotenv.config();
- // Konfigurationskonstanten
- const KEYCLOAK_URL = process.env.KEYCLOAK_URL || 'https://auth.mrx8086.com';
- const ADMIN_USERNAME = process.env.KEYCLOAK_ADMIN_USER;
- const ADMIN_PASSWORD = process.env.KEYCLOAK_ADMIN_PASSWORD;
- const REALM_NAME = 'office-automation';
- // Client IDs aus Umgebungsvariablen
- const NEXTCLOUD_CLIENT_ID = process.env.NEXTCLOUD_CLIENT_ID || 'nextcloud';
- const PAPERLESS_CLIENT_ID = process.env.PAPERLESS_CLIENT_ID || 'paperless';
- const NODERED_CLIENT_ID = process.env.NODERED_CLIENT_ID || 'nodered';
- // Hilfsfunktion für API-Fehlerbehandlung
- const handleAxiosError = (error, operation) => {
- if (error.response) {
- console.error(`Error during ${operation}:`, {
- status: error.response.status,
- data: error.response.data
- });
- } else {
- console.error(`Error during ${operation}:`, error.message);
- }
- throw error;
- };
- // Admin Token abrufen
- async function getAdminToken() {
- try {
- const response = await axios.post(
- `${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token`,
- new URLSearchParams({
- 'client_id': 'admin-cli',
- 'username': ADMIN_USERNAME,
- 'password': ADMIN_PASSWORD,
- 'grant_type': 'password'
- }),
- {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded'
- }
- }
- );
- return response.data.access_token;
- } catch (error) {
- handleAxiosError(error, 'getting admin token');
- }
- }
- // Prüfen ob Realm existiert
- async function checkRealmExists(token) {
- try {
- await axios.get(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}`,
- {
- headers: {
- 'Authorization': `Bearer ${token}`
- }
- }
- );
- return true;
- } catch (error) {
- if (error.response?.status === 404) {
- return false;
- }
- handleAxiosError(error, 'checking realm existence');
- }
- }
- // Prüfen ob Client existiert
- async function checkClientExists(token, clientId) {
- try {
- const response = await axios.get(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients`,
- {
- headers: {
- 'Authorization': `Bearer ${token}`
- },
- params: {
- clientId: clientId
- }
- }
- );
- return response.data.length > 0;
- } catch (error) {
- handleAxiosError(error, `checking client existence: ${clientId}`);
- }
- }
- // Realm erstellen
- async function createRealm(token) {
- const realmConfig = {
- realm: REALM_NAME,
- enabled: true,
- displayName: "Office Automation",
- displayNameHtml: "<div class=\"kc-logo-text\">Office Automation</div>",
- sslRequired: "external",
- registrationAllowed: false,
- loginWithEmailAllowed: true,
- duplicateEmailsAllowed: false,
- resetPasswordAllowed: true,
- editUsernameAllowed: false,
- bruteForceProtected: true,
- permanentLockout: false,
- maxFailureWaitSeconds: 900,
- minimumQuickLoginWaitSeconds: 60,
- waitIncrementSeconds: 60,
- quickLoginCheckMilliSeconds: 1000,
- maxDeltaTimeSeconds: 43200,
- failureFactor: 3,
- defaultSignatureAlgorithm: "RS256",
- offlineSessionMaxLifespan: 5184000,
- offlineSessionMaxLifespanEnabled: true,
- webAuthnPolicySignatureAlgorithms: ["ES256"],
- webAuthnPolicyAttestationConveyancePreference: "none",
- webAuthnPolicyAuthenticatorAttachment: "cross-platform",
- webAuthnPolicyRequireResidentKey: "not specified",
- webAuthnPolicyUserVerificationRequirement: "preferred",
- webAuthnPolicyCreateTimeout: 0,
- webAuthnPolicyAvoidSameAuthenticatorRegister: false,
- defaultDefaultClientScopes: [
- "email",
- "profile",
- "roles",
- "web-origins"
- ],
- defaultOptionalClientScopes: [
- "address",
- "phone",
- "offline_access",
- "microprofile-jwt"
- ]
- };
- try {
- await axios.post(
- `${KEYCLOAK_URL}/admin/realms`,
- realmConfig,
- {
- headers: {
- 'Authorization': `Bearer ${token}`,
- 'Content-Type': 'application/json'
- }
- }
- );
- console.log('Realm created successfully');
- } catch (error) {
- handleAxiosError(error, 'creating realm');
- }
- }
- // Client erstellen
- async function createClient(token, clientId, clientName, redirectUris) {
- const clientConfig = {
- clientId: clientId,
- name: clientName,
- enabled: true,
- protocol: "openid-connect",
- publicClient: false,
- authorizationServicesEnabled: true,
- serviceAccountsEnabled: true,
- standardFlowEnabled: true,
- implicitFlowEnabled: false,
- directAccessGrantsEnabled: true,
- redirectUris: redirectUris,
- webOrigins: ["+"],
- defaultClientScopes: [
- "email",
- "profile",
- "roles",
- "web-origins"
- ],
- optionalClientScopes: [
- "address",
- "phone",
- "offline_access",
- "microprofile-jwt"
- ]
- };
- try {
- await axios.post(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients`,
- clientConfig,
- {
- headers: {
- 'Authorization': `Bearer ${token}`,
- 'Content-Type': 'application/json'
- }
- }
- );
- console.log(`Client ${clientId} created successfully`);
- } catch (error) {
- handleAxiosError(error, `creating client: ${clientId}`);
- }
- }
- // Gruppen erstellen
- async function createDefaultGroups(token) {
- const groups = [
- {
- name: "Administrators",
- path: "/Administrators",
- attributes: {
- "description": ["Full system access"]
- }
- },
- {
- name: "Users",
- path: "/Users",
- attributes: {
- "description": ["Regular system users"]
- }
- }
- ];
- for (const group of groups) {
- try {
- await axios.post(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/groups`,
- group,
- {
- headers: {
- 'Authorization': `Bearer ${token}`,
- 'Content-Type': 'application/json'
- }
- }
- );
- console.log(`Group ${group.name} created successfully`);
- } catch (error) {
- if (error.response?.status === 409) {
- console.log(`Group ${group.name} already exists`);
- } else {
- handleAxiosError(error, `creating group: ${group.name}`);
- }
- }
- }
- }
- // Test-User erstellen
- async function createInitialUsers(token) {
- const users = [
- {
- username: "testadmin",
- enabled: true,
- emailVerified: true,
- firstName: "Test",
- lastName: "Admin",
- email: "testadmin@mrx8086.com",
- credentials: [{
- type: "password",
- value: process.env.TESTADMIN_PASSWORD || "initial123!",
- temporary: true
- }],
- groups: ["/Administrators"]
- },
- {
- username: "testuser",
- enabled: true,
- emailVerified: true,
- firstName: "Test",
- lastName: "User",
- email: "testuser@mrx8086.com",
- credentials: [{
- type: "password",
- value: process.env.TESTUSER_PASSWORD || "initial123!",
- temporary: true
- }],
- groups: ["/Users"]
- }
- ];
- for (const user of users) {
- try {
- // Prüfen ob User existiert
- const existingUsers = await axios.get(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/users`,
- {
- headers: {
- 'Authorization': `Bearer ${token}`
- },
- params: {
- username: user.username,
- exact: true
- }
- }
- );
- if (existingUsers.data.length > 0) {
- console.log(`User ${user.username} already exists`);
- continue;
- }
- // User erstellen
- await axios.post(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/users`,
- user,
- {
- headers: {
- 'Authorization': `Bearer ${token}`,
- 'Content-Type': 'application/json'
- }
- }
- );
- console.log(`User ${user.username} created successfully`);
- } catch (error) {
- handleAxiosError(error, `creating user: ${user.username}`);
- }
- }
- }
- // Hauptfunktion
- async function setupRealm() {
- try {
- console.log('Starting Keycloak setup...');
- const token = await getAdminToken();
-
- // Prüfe ob Realm existiert
- const realmExists = await checkRealmExists(token);
-
- if (!realmExists) {
- console.log('Creating new realm...');
- await createRealm(token);
-
- // 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: "Node-RED", redirectUris: ["https://automate.mrx8086.com/*"] }
- ];
- for (const client of clients) {
- const clientExists = await checkClientExists(token, client.id);
- if (!clientExists) {
- await createClient(token, client.id, client.name, client.redirectUris);
- } else {
- console.log(`Client ${client.id} already exists`);
- }
- }
- // Gruppen erstellen
- await createDefaultGroups(token);
- } else {
- console.log('Realm already exists, skipping base setup');
- }
- // User erstellen/aktualisieren
- await createInitialUsers(token);
-
- console.log('Setup completed successfully');
- } catch (error) {
- console.error('Setup failed:', error);
- process.exit(1);
- }
- }
- // Script ausführen
- setupRealm();
|