Only refresh SCIM endpoints when a SCIM configuration is deleted

This commit is contained in:
Alex Morel 2024-07-19 10:36:34 +02:00
parent 4defbc2f6a
commit a36fe19adc
4 changed files with 16 additions and 10 deletions

View file

@ -45,7 +45,6 @@ public class ScimEndpointConfigurationStorageProviderFactory
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);
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))) { 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));
} }

View file

@ -182,7 +182,7 @@ public abstract class AbstractScimService<K extends RoleMapperModel, S extends R
if (optionalMapping.isPresent()) { if (optionalMapping.isPresent()) {
ScimResourceMapping mapping = optionalMapping.get(); ScimResourceMapping mapping = optionalMapping.get();
if (entityExists(mapping.getIdAsKeycloakId())) { if (entityExists(mapping.getIdAsKeycloakId())) {
LOGGER.debug("[SCIM] Valid mapping found, skipping"); LOGGER.info("[SCIM] Valid mapping found, skipping");
return true; return true;
} else { } else {
LOGGER.info("[SCIM] Delete a dangling mapping"); LOGGER.info("[SCIM] Delete a dangling mapping");

View file

@ -71,7 +71,7 @@ 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) { if (logAllRequests) {
LOGGER.warn("[SCIM] Sending " + scimForCreation.toPrettyString() + "\n to " + getScimEndpoint()); LOGGER.info("[SCIM] Sending CREATE " + scimForCreation.toPrettyString() + "\n to " + getScimEndpoint());
} }
ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder
.create(getResourceClass(), getScimEndpoint()) .create(getResourceClass(), getScimEndpoint())
@ -92,7 +92,7 @@ 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) { if (logAllRequests) {
LOGGER.warn("[SCIM] Server response " + response.getHttpStatus() + "\n" + response.getResponseBody()); LOGGER.info("[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());
@ -111,7 +111,7 @@ public class ScimClient<S extends ResourceNode> implements AutoCloseable {
Retry retry = retryRegistry.retry("replace-%s".formatted(externalId.asString())); Retry retry = retryRegistry.retry("replace-%s".formatted(externalId.asString()));
try { try {
if (logAllRequests) { if (logAllRequests) {
LOGGER.warn("[SCIM] Sending Update " + scimForReplace.toPrettyString() + "\n to " + getScimEndpoint()); LOGGER.info("[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())
@ -128,7 +128,7 @@ 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) { if (logAllRequests) {
LOGGER.warn("[SCIM] Sending DELETE to " + getScimEndpoint()); LOGGER.info("[SCIM] Sending DELETE to " + getScimEndpoint());
} }
try { try {
ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder ServerResponse<S> response = retry.executeSupplier(() -> scimRequestBuilder

View file

@ -1,6 +1,7 @@
package sh.libre.scim.event; package sh.libre.scim.event;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.component.ComponentModel;
import org.keycloak.events.Event; import org.keycloak.events.Event;
import org.keycloak.events.EventListenerProvider; import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventType; import org.keycloak.events.EventType;
@ -11,6 +12,7 @@ import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import sh.libre.scim.core.ScimDispatcher; import sh.libre.scim.core.ScimDispatcher;
import sh.libre.scim.core.ScimEndpointConfigurationStorageProviderFactory;
import sh.libre.scim.core.service.KeycloakDao; import sh.libre.scim.core.service.KeycloakDao;
import sh.libre.scim.core.service.KeycloakId; import sh.libre.scim.core.service.KeycloakId;
import sh.libre.scim.core.service.ScimResourceType; import sh.libre.scim.core.service.ScimResourceType;
@ -18,6 +20,7 @@ import sh.libre.scim.core.service.ScimResourceType;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Stream;
/** /**
* An Event listener reacting to Keycloak models modification * An Event listener reacting to Keycloak models modification
@ -204,18 +207,22 @@ public class ScimEventListenerProvider implements EventListenerProvider {
} }
private void handleScimEndpointConfigurationEvent(AdminEvent event, String id) { private void handleScimEndpointConfigurationEvent(AdminEvent event, String id) {
LOGGER.infof("[SCIM] SCIM Endpoint configuration %s - %s ", event.getOperationType(), id);
// In case of a component deletion // In case of a component deletion
if (event.getOperationType() == OperationType.DELETE) { if (event.getOperationType() == OperationType.DELETE) {
// Check if it was a Scim endpoint configuration, and forward deletion if so // Check if it was a Scim endpoint configuration, and forward deletion if so
// TODO : determine if deleted element is of ScimStorageProvider class and only refresh in that case Stream<ComponentModel> scimEndpointConfigurationsWithDeletedId = session.getContext().getRealm().getComponentsStream()
dispatcher.refreshActiveScimEndpoints(); .filter(m -> ScimEndpointConfigurationStorageProviderFactory.ID.equals(m.getProviderId())
&& id.equals(m.getId()));
if (scimEndpointConfigurationsWithDeletedId.iterator().hasNext()) {
LOGGER.infof("[SCIM] SCIM Endpoint configuration DELETE - %s ", id);
dispatcher.refreshActiveScimEndpoints();
}
} else { } else {
// In case of CREATE or UPDATE, we can directly use the string representation // In case of CREATE or UPDATE, we can directly use the string representation
// to check if it defines a SCIM endpoint (faster) // to check if it defines a SCIM endpoint (faster)
if (event.getRepresentation() != null if (event.getRepresentation() != null
&& event.getRepresentation().contains("\"providerId\":\"scim\"")) { && event.getRepresentation().contains("\"providerId\":\"scim\"")) {
LOGGER.infof("[SCIM] SCIM Endpoint configuration CREATE - %s ", id);
dispatcher.refreshActiveScimEndpoints(); dispatcher.refreshActiveScimEndpoints();
} }
} }