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

145 lines
6.2 KiB
Java

package org.gcube.keycloak.event;
import java.net.MalformedURLException;
import java.net.URL;
import org.jboss.logging.Logger;
import org.keycloak.Config.Scope;
import org.keycloak.events.EventListenerProviderFactory;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
/**
* @author <a href="mailto:marco.lettere@nubisware.com">Marco Lettere</a>
* @author <a href="mailto:mauro.mugnaini@nubisware.com">Mauro Mugnaini</a>
*/
public class OrchestratorEventPublisherProviderFactory implements EventListenerProviderFactory {
private static final Logger logger = Logger.getLogger(OrchestratorEventPublisherProviderFactory.class);
public static final String MASTER_REALM_NAME = "master";
public static final String ORCHESTRATOR_CLIENT_ID = "orchestrator";
public static final String ORCHESTRATOR_AUDIENCE_ID = "conductor-server";
public static final String KEYCLOAK_CLIENT_ID = "keycloak-client";
private static final int CHECK_DELAY = 60 * 1000; // One minute
public static URL ORCHESTRATOR_ENDPOINT;
public static URL KEYCLOAK_ENDPOINT;
public static String KEYCLOAK_CLIENT_SECRET;
protected Long lastEndpointCheck = new Long(0);
protected OrchestratorEventPublisherProvider oepp;
public OrchestratorEventPublisherProviderFactory() {
logger.info("New OrchestratorEventPublisherProviderFactory has been created");
}
@Override
public void close() {
}
@Override
public synchronized OrchestratorEventPublisherProvider create(KeycloakSession keycloakSession) {
Long now = System.currentTimeMillis();
Long elapsed = now - lastEndpointCheck;
if (oepp == null || elapsed > CHECK_DELAY) {
lastEndpointCheck = now;
ClientModel orchestratorClient = getClientInActualOrMasterRealm(keycloakSession, ORCHESTRATOR_CLIENT_ID);
URL newOrchestratorEndpoint;
if (orchestratorClient != null) {
logger.trace("Getting configured orchestrator endpoint address from client's base URL");
try {
newOrchestratorEndpoint = new URL(orchestratorClient.getBaseUrl());
} catch (MalformedURLException e) {
logger.errorf("Can't create new orchestrator endpoint address: %s", orchestratorClient.getBaseUrl());
oepp = new NoOpEventPublisherProvider();
return oepp;
}
} else {
logger.debugf("Can't go ahead without a configured '%f' client", ORCHESTRATOR_CLIENT_ID);
oepp = null;
return oepp;
}
ClientModel keycloakClient = getClientInActualOrMasterRealm(keycloakSession, KEYCLOAK_CLIENT_ID);
URL newKeycloakEndpoint;
String keycloakClientSecret;
if (keycloakClient != null) {
try {
logger.debug("Getting configured keycloak endpoint address from client's base URL");
newKeycloakEndpoint = new URL(keycloakClient.getBaseUrl());
// Only do it if URL has been configured properly
logger.debug("Getting configured keycloak client client-secret from client");
keycloakClientSecret = keycloakClient.getSecret();
} catch (MalformedURLException e) {
logger.errorf("Can't create new keycloak token address: %s", keycloakClient.getBaseUrl(), e);
oepp = new NoOpEventPublisherProvider();
return oepp;
}
} else {
logger.debugf("Can't go ahead without a configured '%f' client", KEYCLOAK_CLIENT_ID);
oepp = new NoOpEventPublisherProvider();
return oepp;
}
if (oepp == null || !newOrchestratorEndpoint.equals(ORCHESTRATOR_ENDPOINT)
|| !newKeycloakEndpoint.equals(KEYCLOAK_ENDPOINT)
|| !keycloakClientSecret.equals(KEYCLOAK_CLIENT_SECRET)) {
logger.info("Creating new orchestrator event publisher provider");
// Address and other fileds will be then read from static fields in this class by
// the createEventSender() called by the superclass' constructor, overridden in the impl.
ORCHESTRATOR_ENDPOINT = newOrchestratorEndpoint;
KEYCLOAK_ENDPOINT = newKeycloakEndpoint;
KEYCLOAK_CLIENT_SECRET = keycloakClientSecret;
oepp = new OrchestratorEventPublisherProvider();
}
} else {
logger.tracef("Next check is in %d millis", CHECK_DELAY - elapsed);
}
return oepp;
}
protected ClientModel getClientInActualOrMasterRealm(KeycloakSession keycloakSession, String clientId) {
logger.debug("Getting actual realm from session's context");
RealmModel realm = keycloakSession.getContext().getRealm();
logger.debugf("Trying getting '%s' client in current realm: '%s'", clientId, realm.getName());
ClientModel client = realm.getClientByClientId(clientId);
if (client == null) {
if (!MASTER_REALM_NAME.equals(realm.getName())) {
logger.debugf("Not found. Now trying getting '%s' in '%s' realm", clientId, MASTER_REALM_NAME);
realm = keycloakSession.realms().getRealmByName(MASTER_REALM_NAME);
client = realm.getClientByClientId(clientId);
if (client == null) {
logger.warnf("Cannot find '%s' client not even in '%s' realm", clientId, realm.getName(),
MASTER_REALM_NAME);
return null;
}
} else {
logger.trace("Not found.");
}
}
logger.debugf("Client '%s' found", clientId);
return client;
}
@Override
public String getId() {
return "orchestrator-event-publisher";
}
@Override
public void init(Scope scope) {
}
@Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
}
}