167 lines
7.1 KiB
Java
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);
|
|
}
|
|
}
|
|
|
|
}
|