Add option to activate full SCIM requests logs
This commit is contained in:
parent
d8cba394b2
commit
97a3e13bc6
3 changed files with 31 additions and 5 deletions
|
@ -39,16 +39,17 @@ public class ScimEndpointConfigurationStorageProviderFactory
|
||||||
public SynchronizationResult sync(KeycloakSessionFactory sessionFactory, String realmId,
|
public SynchronizationResult sync(KeycloakSessionFactory sessionFactory, String realmId,
|
||||||
UserStorageProviderModel model) {
|
UserStorageProviderModel model) {
|
||||||
// Manually Launch a synchronization between keycloack and the SCIM endpoint described in the given 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();
|
SynchronizationResult result = new SynchronizationResult();
|
||||||
KeycloakModelUtils.runJobInTransaction(sessionFactory, session -> {
|
KeycloakModelUtils.runJobInTransaction(sessionFactory, session -> {
|
||||||
RealmModel realm = session.realms().getRealm(realmId);
|
RealmModel realm = session.realms().getRealm(realmId);
|
||||||
session.getContext().setRealm(realm);
|
session.getContext().setRealm(realm);
|
||||||
ScimDispatcher dispatcher = new ScimDispatcher(session);
|
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));
|
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.dispatchGroupModificationToOne(model, client -> client.sync(result));
|
||||||
}
|
}
|
||||||
dispatcher.close();
|
dispatcher.close();
|
||||||
|
@ -139,6 +140,10 @@ public class ScimEndpointConfigurationStorageProviderFactory
|
||||||
.name(ScrimEndPointConfiguration.CONF_KEY_SYNC_REFRESH)
|
.name(ScrimEndPointConfiguration.CONF_KEY_SYNC_REFRESH)
|
||||||
.type(ProviderConfigProperty.BOOLEAN_TYPE)
|
.type(ProviderConfigProperty.BOOLEAN_TYPE)
|
||||||
.label("Enable refresh during sync")
|
.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()
|
.add()
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ public class ScrimEndPointConfiguration {
|
||||||
public static final String CONF_KEY_SYNC_REFRESH = "sync-refresh";
|
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_USER = "propagation-user";
|
||||||
public static final String CONF_KEY_PROPAGATION_GROUP = "propagation-group";
|
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 endPoint;
|
||||||
private final String id;
|
private final String id;
|
||||||
|
@ -24,6 +25,7 @@ public class ScrimEndPointConfiguration {
|
||||||
private final ImportAction importAction;
|
private final ImportAction importAction;
|
||||||
private final boolean pullFromScimSynchronisationActivated;
|
private final boolean pullFromScimSynchronisationActivated;
|
||||||
private final boolean pushToScimSynchronisationActivated;
|
private final boolean pushToScimSynchronisationActivated;
|
||||||
|
private final boolean logAllScimRequests;
|
||||||
|
|
||||||
public ScrimEndPointConfiguration(ComponentModel scimProviderConfiguration) {
|
public ScrimEndPointConfiguration(ComponentModel scimProviderConfiguration) {
|
||||||
try {
|
try {
|
||||||
|
@ -47,6 +49,7 @@ public class ScrimEndPointConfiguration {
|
||||||
importAction = ImportAction.valueOf(scimProviderConfiguration.get(CONF_KEY_SYNC_IMPORT_ACTION));
|
importAction = ImportAction.valueOf(scimProviderConfiguration.get(CONF_KEY_SYNC_IMPORT_ACTION));
|
||||||
pullFromScimSynchronisationActivated = scimProviderConfiguration.get(CONF_KEY_SYNC_IMPORT, false);
|
pullFromScimSynchronisationActivated = scimProviderConfiguration.get(CONF_KEY_SYNC_IMPORT, false);
|
||||||
pushToScimSynchronisationActivated = scimProviderConfiguration.get(CONF_KEY_SYNC_REFRESH, false);
|
pushToScimSynchronisationActivated = scimProviderConfiguration.get(CONF_KEY_SYNC_REFRESH, false);
|
||||||
|
logAllScimRequests = scimProviderConfiguration.get(CONF_KEY_LOG_ALL_SCIM_REQUESTS, false);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw new IllegalArgumentException("authMode '" + scimProviderConfiguration.get(CONF_KEY_AUTH_MODE) + "' is not supported");
|
throw new IllegalArgumentException("authMode '" + scimProviderConfiguration.get(CONF_KEY_AUTH_MODE) + "' is not supported");
|
||||||
}
|
}
|
||||||
|
@ -84,6 +87,10 @@ public class ScrimEndPointConfiguration {
|
||||||
return endPoint;
|
return endPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLogAllScimRequests() {
|
||||||
|
return logAllScimRequests;
|
||||||
|
}
|
||||||
|
|
||||||
public enum AuthMode {
|
public enum AuthMode {
|
||||||
BEARER, BASIC_AUTH, NONE
|
BEARER, BASIC_AUTH, NONE
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,9 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
|
||||||
private final ScimRequestBuilder scimRequestBuilder;
|
private final ScimRequestBuilder scimRequestBuilder;
|
||||||
|
|
||||||
private final ScimResourceType scimResourceType;
|
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.scimRequestBuilder = scimRequestBuilder;
|
||||||
this.scimResourceType = scimResourceType;
|
this.scimResourceType = scimResourceType;
|
||||||
RetryConfig retryConfig = RetryConfig.custom()
|
RetryConfig retryConfig = RetryConfig.custom()
|
||||||
|
@ -38,6 +39,7 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
|
||||||
.retryExceptions(ProcessingException.class)
|
.retryExceptions(ProcessingException.class)
|
||||||
.build();
|
.build();
|
||||||
retryRegistry = RetryRegistry.of(retryConfig);
|
retryRegistry = RetryRegistry.of(retryConfig);
|
||||||
|
this.logAllRequests = detailedLogs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ScimClient open(ScrimEndPointConfiguration scimProviderConfiguration, ScimResourceType scimResourceType) {
|
public static ScimClient open(ScrimEndPointConfiguration scimProviderConfiguration, ScimResourceType scimResourceType) {
|
||||||
|
@ -56,7 +58,7 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
|
||||||
scimApplicationBaseUrl,
|
scimApplicationBaseUrl,
|
||||||
scimClientConfig
|
scimClientConfig
|
||||||
);
|
);
|
||||||
return new ScimClient(scimRequestBuilder, scimResourceType);
|
return new ScimClient(scimRequestBuilder, scimResourceType, scimProviderConfiguration.isLogAllScimRequests());
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityOnRemoteScimId create(KeycloakId id, S scimForCreation) throws InvalidResponseFromScimEndpointException {
|
public EntityOnRemoteScimId create(KeycloakId id, S scimForCreation) throws InvalidResponseFromScimEndpointException {
|
||||||
|
@ -68,6 +70,9 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Retry retry = retryRegistry.retry("create-%s".formatted(id.asString()));
|
Retry retry = retryRegistry.retry("create-%s".formatted(id.asString()));
|
||||||
|
if (logAllRequests) {
|
||||||
|
LOGGER.warn("[SCIM] Sending " + scimForCreation.toPrettyString() + "\n to " + getScimEndpoint());
|
||||||
|
}
|
||||||
ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
|
ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
|
||||||
.create(getResourceClass(), getScimEndpoint())
|
.create(getResourceClass(), getScimEndpoint())
|
||||||
.setResource(scimForCreation)
|
.setResource(scimForCreation)
|
||||||
|
@ -86,6 +91,9 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkResponseIsSuccess(ServerResponse<S> response) throws InvalidResponseFromScimEndpointException {
|
private void checkResponseIsSuccess(ServerResponse<S> response) throws InvalidResponseFromScimEndpointException {
|
||||||
|
if (logAllRequests) {
|
||||||
|
LOGGER.warn("[SCIM] Server response " + response.getHttpStatus() + "\n" + response.getResponseBody());
|
||||||
|
}
|
||||||
if (!response.isSuccess()) {
|
if (!response.isSuccess()) {
|
||||||
throw new InvalidResponseFromScimEndpointException(response, "Server answered with status " + response.getResponseBody() + ": " + response.getResponseBody());
|
throw new InvalidResponseFromScimEndpointException(response, "Server answered with status " + response.getResponseBody() + ": " + response.getResponseBody());
|
||||||
}
|
}
|
||||||
|
@ -102,6 +110,9 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
|
||||||
public void update(EntityOnRemoteScimId externalId, S scimForReplace) throws InvalidResponseFromScimEndpointException {
|
public void update(EntityOnRemoteScimId externalId, S scimForReplace) throws InvalidResponseFromScimEndpointException {
|
||||||
Retry retry = retryRegistry.retry("replace-%s".formatted(externalId.asString()));
|
Retry retry = retryRegistry.retry("replace-%s".formatted(externalId.asString()));
|
||||||
try {
|
try {
|
||||||
|
if (logAllRequests) {
|
||||||
|
LOGGER.warn("[SCIM] Sending Update " + scimForReplace.toPrettyString() + "\n to " + getScimEndpoint());
|
||||||
|
}
|
||||||
ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
|
ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
|
||||||
.update(getResourceClass(), getScimEndpoint(), externalId.asString())
|
.update(getResourceClass(), getScimEndpoint(), externalId.asString())
|
||||||
.setResource(scimForReplace)
|
.setResource(scimForReplace)
|
||||||
|
@ -116,6 +127,9 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
|
||||||
|
|
||||||
public void delete(EntityOnRemoteScimId externalId) throws InvalidResponseFromScimEndpointException {
|
public void delete(EntityOnRemoteScimId externalId) throws InvalidResponseFromScimEndpointException {
|
||||||
Retry retry = retryRegistry.retry("delete-%s".formatted(externalId.asString()));
|
Retry retry = retryRegistry.retry("delete-%s".formatted(externalId.asString()));
|
||||||
|
if (logAllRequests) {
|
||||||
|
LOGGER.warn("[SCIM] Sending DELETE to " + getScimEndpoint());
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
|
ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
|
||||||
.delete(getResourceClass(), getScimEndpoint(), externalId.asString())
|
.delete(getResourceClass(), getScimEndpoint(), externalId.asString())
|
||||||
|
|
Loading…
Reference in a new issue