From 6367833ca44f7270dca3723b68d28d42e71f0774 Mon Sep 17 00:00:00 2001 From: Masaki Yatsu Date: Wed, 15 Oct 2025 22:59:45 +0900 Subject: [PATCH] feat(keycloak): add keycloak::enable-service-account --- keycloak/justfile | 10 ++++ keycloak/scripts/enable-service-account.ts | 61 ++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 keycloak/scripts/enable-service-account.ts diff --git a/keycloak/justfile b/keycloak/justfile index 5ad6ab5..28abda9 100644 --- a/keycloak/justfile +++ b/keycloak/justfile @@ -268,6 +268,16 @@ delete-client realm client_id: export KEYCLOAK_CLIENT_ID={{ client_id }} dotenvx run -q -f ../.env.local -- tsx ./scripts/delete-client.ts +# Enable service account for Keycloak client +enable-service-account realm client_id: + #!/bin/bash + set -euo pipefail + export KEYCLOAK_ADMIN_USER=$(just admin-username) + export KEYCLOAK_ADMIN_PASSWORD=$(just admin-password) + export KEYCLOAK_REALM={{ realm }} + export KEYCLOAK_CLIENT_ID={{ client_id }} + dotenvx run -q -f ../.env.local -- tsx ./scripts/enable-service-account.ts + # Add attribute mapper for Keycloak client add-attribute-mapper client_id attribute_name display_name='' claim_name='' options='' default_value='' mapper_name='' view_perms='admin,user' edit_perms='admin': #!/bin/bash diff --git a/keycloak/scripts/enable-service-account.ts b/keycloak/scripts/enable-service-account.ts new file mode 100644 index 0000000..5fd3a90 --- /dev/null +++ b/keycloak/scripts/enable-service-account.ts @@ -0,0 +1,61 @@ +import KcAdminClient from "@keycloak/keycloak-admin-client"; +import invariant from "tiny-invariant"; + +const main = async () => { + const keycloakHost = process.env.KEYCLOAK_HOST; + invariant(keycloakHost, "KEYCLOAK_HOST environment variable is required."); + + const adminUsername = process.env.KEYCLOAK_ADMIN_USER; + invariant(adminUsername, "KEYCLOAK_ADMIN_USER environment variable is required."); + + const adminPassword = process.env.KEYCLOAK_ADMIN_PASSWORD; + invariant(adminPassword, "KEYCLOAK_ADMIN_PASSWORD environment variable is required"); + + const realmName = process.env.KEYCLOAK_REALM; + invariant(realmName, "KEYCLOAK_REALM environment variable is required"); + + const clientId = process.env.KEYCLOAK_CLIENT_ID; + invariant(clientId, "KEYCLOAK_CLIENT_ID environment variable is required"); + + const kcAdminClient = new KcAdminClient({ + baseUrl: `https://${keycloakHost}`, + realmName: "master", + }); + + try { + await kcAdminClient.auth({ + username: adminUsername, + password: adminPassword, + grantType: "password", + clientId: "admin-cli", + }); + console.log("Authentication successful."); + + kcAdminClient.setConfig({ realmName }); + + const existingClients = await kcAdminClient.clients.find({ clientId }); + if (existingClients.length === 0) { + console.error(`Client '${clientId}' not found.`); + process.exit(1); + } + + const client = existingClients[0]; + invariant(client.id, "Client ID is missing"); + + await kcAdminClient.clients.update( + { id: client.id }, + { + ...client, + serviceAccountsEnabled: true, + authorizationServicesEnabled: false, + } + ); + + console.log(`Service Accounts enabled for client '${clientId}'`); + } catch (error) { + console.error("An error occurred:", error); + process.exit(1); + } +}; + +main();