keycloak-d4science-spi-parent/event-listener-provider/src/main/java/org/gcube/keycloak/event/OrchestratorEventPublisherP...

167 lines
7.1 KiB
Java

package org.gcube.keycloak.event;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.EventListener;
import java.util.Set;
import org.gcube.event.publisher.AbstractEventPublisher;
import org.gcube.event.publisher.EventSender;
import org.gcube.event.publisher.HTTPWithUMAAuthEventSender;
import org.jboss.logging.Logger;
import org.keycloak.events.Event;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventListenerTransaction;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.models.KeycloakTransactionManager;
/**
* @author <a href="mailto:marco.lettere@nubisware.com">Marco Lettere</a>
* @author <a href="mailto:mauro.mugnaini@nubisware.com">Mauro Mugnaini</a>
*/
public class OrchestratorEventPublisherProvider extends AbstractEventPublisher
implements EventListenerProvider, EventListener {
public static final Logger logger = Logger.getLogger(OrchestratorEventPublisherProvider.class);
private final String realmName;
private final EventListenerTransaction tx;
private final String orchestratorEndpoint;
private final String keycloakTokenEndpoint;
private final String keycloakClientId;
private final String keycloakClientSecret;
private final String orchestratorAudience;
private final Set<ResourceType> interestingAdminEventResourceTypes;
private final Set<EventType> interestingEvents;
/**
* Default constructor for dummy use
*/
public OrchestratorEventPublisherProvider() {
this.realmName = null;
this.tx = null;
orchestratorEndpoint = null;
keycloakTokenEndpoint = null;
keycloakClientId = null;
keycloakClientSecret = null;
orchestratorAudience = null;
this.interestingAdminEventResourceTypes = Collections.emptySet();
this.interestingEvents = Collections.emptySet();
logger.tracef("Created new dummy instance");
}
public OrchestratorEventPublisherProvider(String realmName, KeycloakTransactionManager transactionManager,
String orchestratorEndpoint, String keycloakTokenEndpoint, String keycloakClientId,
String keycloakClientSecret, String orchestratorAudience,
Set<ResourceType> interestingAdminEventResourceTypes, Set<EventType> interestingEvents) {
super();
this.realmName = realmName;
this.interestingAdminEventResourceTypes = interestingAdminEventResourceTypes;
this.interestingEvents = interestingEvents;
tx = new EventListenerTransaction(this::sendAdminEvent, this::sendEvent);
transactionManager.enlistAfterCompletion(tx);
this.orchestratorEndpoint = orchestratorEndpoint;
this.keycloakTokenEndpoint = keycloakTokenEndpoint;
this.keycloakClientId = keycloakClientId;
this.keycloakClientSecret = keycloakClientSecret;
this.orchestratorAudience = orchestratorAudience;
// Creating every time a new sender to be sure new settings are used, if changed
this.setEventSender(newEventSender(realmName));
logger.tracef("Created new instance for realm: %s. Admin events: %s. Events: %s", realmName,
interestingAdminEventResourceTypes, interestingEvents);
}
@Override
protected EventSender createEventSender() {
// Will be set in the constructor by using the setter, instance variables are still not available at this moment
return null;
}
protected EventSender newEventSender(String realmName) {
if (orchestratorEndpoint != null) {
try {
if (keycloakClientSecret != null) {
logger.tracef(
"Creating event sender for realm %s. Endpoint: %s, KC token endpoint: %s, UMA adience: %s",
realmName, orchestratorEndpoint, keycloakTokenEndpoint, orchestratorAudience);
return new HTTPWithUMAAuthEventSender(new URL(orchestratorEndpoint), keycloakClientId,
keycloakClientSecret, new URL(keycloakTokenEndpoint), orchestratorAudience);
} else {
logger.debugf("Creating unauthorized event sender with endpoint: %s", orchestratorEndpoint);
return new HTTPWithUMAAuthEventSender(new URL(orchestratorEndpoint), null, null, null, null);
}
} catch (MalformedURLException e) {
logger.errorf("Can't construct endpoint URL from string", e);
}
} else {
logger.errorf("Orchestrator endpoint is not available for realm: %s", realmName);
}
return null;
}
@Override
public void close() {
}
@Override
public void onEvent(AdminEvent adminEvent, boolean includeRepresentation) {
if (getEventSender() != null) {
if (adminEvent.getError() != null) {
logger.debug("Skipping error admin event publish");
return;
}
if (interestingAdminEventResourceTypes.contains(adminEvent.getResourceType())) {
logger.tracef("Enqued admin event for resource type: %s", adminEvent.getResourceType().name());
tx.addAdminEvent(adminEvent, includeRepresentation);
} else {
logger.tracef("Skipping not interesting admin event resource type: %s",
adminEvent.getResourceType().name());
}
} else {
logger.debugf("Can't publish admin events since since event sender is null for realm: %s", realmName);
}
}
public void sendAdminEvent(AdminEvent adminEvent, boolean includeRepresentation) {
if (getEventSender() != null) {
logger.debugf("Publishing new admin event '%s' to orchestrator for realm: %s",
adminEvent.getOperationType().name(), realmName);
publish(KeycloakEvent.newKeycloakAdminEvent(adminEvent, includeRepresentation));
} else {
logger.debugf("Can't publish admin events since event sender is null. Current realm: %s", realmName);
}
}
@Override
public void onEvent(Event event) {
if (getEventSender() != null) {
EventType eventType = event.getType();
if (interestingEvents.contains(eventType)) {
logger.tracef("Enqued event of type: %s", eventType.name());
tx.addEvent(event);
return;
} else {
logger.tracef("Skipping not interesting event: %s", eventType.name());
}
} else {
logger.debugf("Can't publish events since since event sender is null for realm: %s", realmName);
}
}
public void sendEvent(Event event) {
if (getEventSender() != null) {
logger.debugf("Publishing new event '%s' to orchestrator for realm %s", event.getType().name(), realmName);
publish(KeycloakEvent.newKeycloakEvent(event));
} else {
logger.debugf("Can't publish events since event sender is null. Current realm: %s", realmName);
}
}
}