From 97a3e13bc6c17b3e898b1e6b0120be312e32c17c Mon Sep 17 00:00:00 2001 From: Alex Morel Date: Fri, 19 Jul 2024 10:12:45 +0200 Subject: [PATCH] Add option to activate full SCIM requests logs --- ...intConfigurationStorageProviderFactory.java | 11 ++++++++--- .../scim/core/ScrimEndPointConfiguration.java | 7 +++++++ .../sh/libre/scim/core/service/ScimClient.java | 18 ++++++++++++++++-- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/main/java/sh/libre/scim/core/ScimEndpointConfigurationStorageProviderFactory.java b/src/main/java/sh/libre/scim/core/ScimEndpointConfigurationStorageProviderFactory.java index 60f61b8c6f..1197980b24 100644 --- a/src/main/java/sh/libre/scim/core/ScimEndpointConfigurationStorageProviderFactory.java +++ b/src/main/java/sh/libre/scim/core/ScimEndpointConfigurationStorageProviderFactory.java @@ -39,16 +39,17 @@ public class ScimEndpointConfigurationStorageProviderFactory public SynchronizationResult sync(KeycloakSessionFactory sessionFactory, String realmId, UserStorageProviderModel model) { // Manually Launch a synchronization between keycloack and the SCIM endpoint described in the given model - LOGGER.infof("[SCIM] Sync from ScimStorageProvider - Realm %s - Model %s", realmId, model.getId()); + LOGGER.infof("[SCIM] Sync from ScimStorageProvider - Realm %s - Model %s", realmId, model.getName()); SynchronizationResult result = new SynchronizationResult(); KeycloakModelUtils.runJobInTransaction(sessionFactory, session -> { RealmModel realm = session.realms().getRealm(realmId); session.getContext().setRealm(realm); ScimDispatcher dispatcher = new ScimDispatcher(session); - if (BooleanUtils.TRUE.equals(model.get("propagation-user"))) { + LOGGER.info("-->" + model.get(ScrimEndPointConfiguration.CONF_KEY_PROPAGATION_USER) + "//" + model.get(ScrimEndPointConfiguration.CONF_KEY_PROPAGATION_GROUP)); + if (BooleanUtils.TRUE.equals(model.get(ScrimEndPointConfiguration.CONF_KEY_PROPAGATION_USER))) { dispatcher.dispatchUserModificationToOne(model, client -> client.sync(result)); } - if (BooleanUtils.TRUE.equals(model.get("propagation-group"))) { + if (BooleanUtils.TRUE.equals(model.get(ScrimEndPointConfiguration.CONF_KEY_PROPAGATION_GROUP))) { dispatcher.dispatchGroupModificationToOne(model, client -> client.sync(result)); } dispatcher.close(); @@ -139,6 +140,10 @@ public class ScimEndpointConfigurationStorageProviderFactory .name(ScrimEndPointConfiguration.CONF_KEY_SYNC_REFRESH) .type(ProviderConfigProperty.BOOLEAN_TYPE) .label("Enable refresh during sync") + .name(ScrimEndPointConfiguration.CONF_KEY_LOG_ALL_SCIM_REQUESTS) + .type(ProviderConfigProperty.BOOLEAN_TYPE) + .label("Log SCIM requests and responses") + .helpText("If true, all sent SCIM requests and responses will be logged") .add() .build(); } diff --git a/src/main/java/sh/libre/scim/core/ScrimEndPointConfiguration.java b/src/main/java/sh/libre/scim/core/ScrimEndPointConfiguration.java index 23755fdfa0..6359b57153 100644 --- a/src/main/java/sh/libre/scim/core/ScrimEndPointConfiguration.java +++ b/src/main/java/sh/libre/scim/core/ScrimEndPointConfiguration.java @@ -15,6 +15,7 @@ public class ScrimEndPointConfiguration { public static final String CONF_KEY_SYNC_REFRESH = "sync-refresh"; public static final String CONF_KEY_PROPAGATION_USER = "propagation-user"; public static final String CONF_KEY_PROPAGATION_GROUP = "propagation-group"; + public static final String CONF_KEY_LOG_ALL_SCIM_REQUESTS = "log-all-scim-requests"; private final String endPoint; private final String id; @@ -24,6 +25,7 @@ public class ScrimEndPointConfiguration { private final ImportAction importAction; private final boolean pullFromScimSynchronisationActivated; private final boolean pushToScimSynchronisationActivated; + private final boolean logAllScimRequests; public ScrimEndPointConfiguration(ComponentModel scimProviderConfiguration) { try { @@ -47,6 +49,7 @@ public class ScrimEndPointConfiguration { importAction = ImportAction.valueOf(scimProviderConfiguration.get(CONF_KEY_SYNC_IMPORT_ACTION)); pullFromScimSynchronisationActivated = scimProviderConfiguration.get(CONF_KEY_SYNC_IMPORT, false); pushToScimSynchronisationActivated = scimProviderConfiguration.get(CONF_KEY_SYNC_REFRESH, false); + logAllScimRequests = scimProviderConfiguration.get(CONF_KEY_LOG_ALL_SCIM_REQUESTS, false); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("authMode '" + scimProviderConfiguration.get(CONF_KEY_AUTH_MODE) + "' is not supported"); } @@ -84,6 +87,10 @@ public class ScrimEndPointConfiguration { return endPoint; } + public boolean isLogAllScimRequests() { + return logAllScimRequests; + } + public enum AuthMode { BEARER, BASIC_AUTH, NONE } diff --git a/src/main/java/sh/libre/scim/core/service/ScimClient.java b/src/main/java/sh/libre/scim/core/service/ScimClient.java index 90bcfcf459..8a5cd738f5 100644 --- a/src/main/java/sh/libre/scim/core/service/ScimClient.java +++ b/src/main/java/sh/libre/scim/core/service/ScimClient.java @@ -28,8 +28,9 @@ public class ScimClient implements AutoCloseable { private final ScimRequestBuilder scimRequestBuilder; private final ScimResourceType scimResourceType; + private final boolean logAllRequests; - private ScimClient(ScimRequestBuilder scimRequestBuilder, ScimResourceType scimResourceType) { + private ScimClient(ScimRequestBuilder scimRequestBuilder, ScimResourceType scimResourceType, boolean detailedLogs) { this.scimRequestBuilder = scimRequestBuilder; this.scimResourceType = scimResourceType; RetryConfig retryConfig = RetryConfig.custom() @@ -38,6 +39,7 @@ public class ScimClient implements AutoCloseable { .retryExceptions(ProcessingException.class) .build(); retryRegistry = RetryRegistry.of(retryConfig); + this.logAllRequests = detailedLogs; } public static ScimClient open(ScrimEndPointConfiguration scimProviderConfiguration, ScimResourceType scimResourceType) { @@ -56,7 +58,7 @@ public class ScimClient implements AutoCloseable { scimApplicationBaseUrl, scimClientConfig ); - return new ScimClient(scimRequestBuilder, scimResourceType); + return new ScimClient(scimRequestBuilder, scimResourceType, scimProviderConfiguration.isLogAllScimRequests()); } public EntityOnRemoteScimId create(KeycloakId id, S scimForCreation) throws InvalidResponseFromScimEndpointException { @@ -68,6 +70,9 @@ public class ScimClient implements AutoCloseable { } try { Retry retry = retryRegistry.retry("create-%s".formatted(id.asString())); + if (logAllRequests) { + LOGGER.warn("[SCIM] Sending " + scimForCreation.toPrettyString() + "\n to " + getScimEndpoint()); + } ServerResponse response = retry.executeSupplier(() -> scimRequestBuilder .create(getResourceClass(), getScimEndpoint()) .setResource(scimForCreation) @@ -86,6 +91,9 @@ public class ScimClient implements AutoCloseable { } private void checkResponseIsSuccess(ServerResponse response) throws InvalidResponseFromScimEndpointException { + if (logAllRequests) { + LOGGER.warn("[SCIM] Server response " + response.getHttpStatus() + "\n" + response.getResponseBody()); + } if (!response.isSuccess()) { throw new InvalidResponseFromScimEndpointException(response, "Server answered with status " + response.getResponseBody() + ": " + response.getResponseBody()); } @@ -102,6 +110,9 @@ public class ScimClient implements AutoCloseable { public void update(EntityOnRemoteScimId externalId, S scimForReplace) throws InvalidResponseFromScimEndpointException { Retry retry = retryRegistry.retry("replace-%s".formatted(externalId.asString())); try { + if (logAllRequests) { + LOGGER.warn("[SCIM] Sending Update " + scimForReplace.toPrettyString() + "\n to " + getScimEndpoint()); + } ServerResponse response = retry.executeSupplier(() -> scimRequestBuilder .update(getResourceClass(), getScimEndpoint(), externalId.asString()) .setResource(scimForReplace) @@ -116,6 +127,9 @@ public class ScimClient implements AutoCloseable { public void delete(EntityOnRemoteScimId externalId) throws InvalidResponseFromScimEndpointException { Retry retry = retryRegistry.retry("delete-%s".formatted(externalId.asString())); + if (logAllRequests) { + LOGGER.warn("[SCIM] Sending DELETE to " + getScimEndpoint()); + } try { ServerResponse response = retry.executeSupplier(() -> scimRequestBuilder .delete(getResourceClass(), getScimEndpoint(), externalId.asString())