| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- import dotenv from 'dotenv';
- import axios from 'axios';
- // Load environment variables
- dotenv.config();
- // Configuration constants
- 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 ID for Paperless
- const PAPERLESS_CLIENT_ID = process.env.PAPERLESS_CLIENT_ID || 'paperless';
- // Helper function for API error handling
- 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('Response:', {
- status: error.response.status,
- data: error.response.data
- });
- } else {
- console.error('Error Message:', error.message);
- }
- throw error;
- };
- // Get Admin Token
- async function getAdminToken() {
- console.log('Getting admin token...');
- 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'
- }
- }
- );
- console.log('Admin token received.');
- return response.data.access_token;
- } catch (error) {
- handleAxiosError(error, 'getting admin token');
- }
- }
- // Function to get client information by clientId
- async function getClient(token, clientId) {
- console.log(`Getting client information for ${clientId}...`);
- try {
- const response = await axios.get(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients`,
- {
- headers: {
- 'Authorization': `Bearer ${token}`
- },
- params: {
- clientId: clientId
- }
- }
- );
- if (response.data.length === 0) {
- console.log(`Client ${clientId} not found`);
- return null;
- }
- console.log(`Client ${clientId} found.`);
- return response.data[0];
- } catch (error) {
- handleAxiosError(error, `getting client ${clientId}`);
- return null;
- }
- }
- // Function to get client secret
- async function getClientSecret(token, clientId) {
- console.log(`Getting client secret for ${clientId}...`);
- const client = await getClient(token, clientId);
- if (!client) {
- console.log(`Client ${clientId} not found, no secret to get.`);
- return null;
- }
- try {
- const response = await axios.get(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${client.id}`,
- {
- headers: { 'Authorization': `Bearer ${token}` }
- }
- );
- console.log(`Client secret for ${clientId} retrieved.`);
- return response.data.secret;
- } catch (error) {
- handleAxiosError(error, `getting client secret for ${clientId}`);
- return null;
- }
- }
- // Function to get redirect URIs
- async function getClientRedirectUris(token, clientId) {
- console.log(`Getting redirect URIs for ${clientId}...`);
- const client = await getClient(token, clientId);
- if (!client) {
- console.log(`Client ${clientId} not found, no redirect URIs to get.`);
- return null;
- }
- try {
- const response = await axios.get(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${client.id}`,
- {
- headers: { 'Authorization': `Bearer ${token}` }
- }
- );
- console.log(`Redirect URIs for ${clientId} retrieved.`);
- return response.data.redirectUris;
- } catch (error) {
- handleAxiosError(error, `getting redirect URIs for ${clientId}`);
- return null;
- }
- }
- // Function to get default client scopes
- async function getDefaultClientScopes(token, clientId) {
- console.log(`Getting default client scopes for ${clientId}...`);
- const client = await getClient(token, clientId);
- if (!client) {
- console.log(`Client ${clientId} not found, no default client scopes to get.`);
- return null;
- }
- try {
- const response = await axios.get(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${client.id}`,
- {
- headers: { 'Authorization': `Bearer ${token}` }
- }
- );
- console.log(`Default client scopes for ${clientId} retrieved.`);
- return response.data.defaultClientScopes;
- } catch (error) {
- handleAxiosError(error, `getting default client scopes for ${clientId}`);
- return null;
- }
- }
- // Function to get client mappers
- async function getClientMappers(token, clientId) {
- console.log(`Getting client mappers for ${clientId}...`);
- const client = await getClient(token, clientId);
- if (!client) {
- console.log(`Client ${clientId} not found, no mappers to get.`);
- return [];
- }
- try {
- const response = await axios.get(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${client.id}/protocol-mappers/models`,
- {
- headers: {
- 'Authorization': `Bearer ${token}`
- }
- }
- );
- console.log(`Client mappers for ${clientId} retrieved.`);
- return response.data;
- } catch (error) {
- handleAxiosError(error, `getting client mappers for ${clientId}`);
- return [];
- }
- }
- // Function to update redirect URIs
- async function updateClientRedirectUris(token, clientId, redirectUris) {
- console.log(`Updating redirect URIs for client ${clientId} to: ${JSON.stringify(redirectUris)}...`);
- const client = await getClient(token, clientId);
- if (!client) {
- console.log(`Client ${clientId} not found, cannot update redirect URIs.`);
- return;
- }
- try {
- await axios.put(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${client.id}`,
- { ...client, redirectUris: redirectUris },
- {
- headers: {
- 'Authorization': `Bearer ${token}`,
- 'Content-Type': 'application/json'
- }
- }
- );
- console.log(`Redirect URIs for client ${clientId} updated successfully.`);
- } catch (error) {
- handleAxiosError(error, `updating redirect URIs for client ${clientId}`);
- }
- }
- // Function to update default client scopes
- async function updateDefaultClientScopes(token, clientId, defaultClientScopes) {
- console.log(`Updating default client scopes for client ${clientId} to: ${JSON.stringify(defaultClientScopes)}...`);
- const client = await getClient(token, clientId);
- if (!client) {
- console.log(`Client ${clientId} not found, cannot update default client scopes.`);
- return;
- }
- try {
- await axios.put(
- `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${client.id}`,
- { ...client, defaultClientScopes: defaultClientScopes },
- {
- headers: {
- 'Authorization': `Bearer ${token}`,
- 'Content-Type': 'application/json'
- }
- }
- );
- console.log(`Default client scopes for client ${clientId} updated successfully.`);
- } catch (error) {
- handleAxiosError(error, `updating default client scopes for client ${clientId}`);
- }
- }
- // Main function to check client configuration
- async function checkClientConfig(token, clientId) {
- console.log(`Checking configuration for client ${clientId}...`);
- const clientSecret = await getClientSecret(token, clientId);
- const redirectUris = await getClientRedirectUris(token, clientId);
- const defaultClientScopes = await getDefaultClientScopes(token, clientId);
- const mappers = await getClientMappers(token, clientId);
- console.log(`Client Secret: ${clientSecret}`);
- console.log(`Redirect URIs: ${JSON.stringify(redirectUris)}`);
- console.log(`Default Client Scopes: ${JSON.stringify(defaultClientScopes)}`);
- console.log("Mappers:");
- mappers.forEach(mapper => console.log(` - name: ${mapper.name}, type: ${mapper.protocolMapper}`));
- // Check and update redirect URIs
- const expectedRedirectUris = ["https://docs.mrx8086.com/*"];
- if (JSON.stringify(redirectUris) !== JSON.stringify(expectedRedirectUris)) {
- console.log(`Redirect URIs do not match expected values. Updating...`);
- await updateClientRedirectUris(token, clientId, expectedRedirectUris);
- }
- // Check and update default client scopes
- const expectedDefaultClientScopes = ["profile", "groups-paperless"];
- if (JSON.stringify(defaultClientScopes) !== JSON.stringify(expectedDefaultClientScopes)) {
- console.log(`Default client scopes do not match expected values. Updating...`);
- await updateDefaultClientScopes(token, clientId, expectedDefaultClientScopes);
- }
- console.log(`Finished checking configuration for client ${clientId}.`);
- }
- // Main function
- async function main() {
- try {
- console.log('Starting Keycloak client configuration check...');
- const token = await getAdminToken();
- await checkClientConfig(token, PAPERLESS_CLIENT_ID);
- console.log('Keycloak client configuration check completed successfully.');
- } catch (error) {
- console.error('Keycloak client configuration check failed:', error);
- process.exit(1);
- }
- }
- // Execute the script
- main();
|