Skip to content

Integration with Redis for Legend Session Store #197

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions legend-shared-pac4j/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import io.dropwizard.Configuration;
import io.dropwizard.configuration.ConfigurationException;
import io.dropwizard.configuration.ConfigurationSourceProvider;
Expand All @@ -28,22 +24,23 @@
import io.dropwizard.setup.Environment;
import javax.security.auth.Subject;
import javax.servlet.DispatcherType;
import org.apache.commons.lang.StringUtils;
import org.bson.Document;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ServletHandler;
import org.finos.legend.server.pac4j.internal.AcceptHeaderAjaxRequestResolver;
import org.finos.legend.server.pac4j.internal.SecurityFilterHandler;
import org.finos.legend.server.pac4j.internal.UsernameFilter;
import org.finos.legend.server.pac4j.kerberos.SubjectExecutor;
import org.finos.legend.server.pac4j.mongostore.MongoDbSessionStore;
import org.finos.legend.server.pac4j.session.config.SessionStoreConfiguration;
import org.finos.legend.server.pac4j.session.consumer.SessionConsumer;
import org.finos.legend.server.pac4j.session.context.SessionContext;
import org.finos.legend.server.pac4j.session.store.SessionStore;
import org.finos.legend.server.pac4j.session.store.SessionStoreFactory;
import org.pac4j.core.client.Client;
import org.pac4j.core.config.Config;
import org.pac4j.core.context.J2EContext;
import org.pac4j.core.context.session.J2ESessionStore;
import org.pac4j.core.engine.DefaultSecurityLogic;
import org.pac4j.core.engine.decision.AlwaysUseSessionProfileStorageDecision;
import org.pac4j.core.http.url.DefaultUrlResolver;
import org.pac4j.core.matching.Matcher;
import org.pac4j.core.matching.PathMatcher;
Expand Down Expand Up @@ -137,15 +134,15 @@ public Pac4jFactory getPac4jFactory(C configuration)
final SubjectExecutor subjectExecutor = new SubjectExecutor(
Objects.isNull(this.subjectSupplierSupplier) ? null : this.subjectSupplierSupplier.apply(configuration));

MongoDatabase db = null;
if (StringUtils.isNotEmpty(legendConfig.getMongoDb())
&& StringUtils.isNotEmpty(legendConfig.getMongoUri()))
SessionStore sessionStore = null;

SessionStoreConfiguration sessionStoreConfiguration = legendConfig.getSessionStoreConfiguration();
if (sessionStoreConfiguration != null && sessionStoreConfiguration.isEnabled())
{
MongoClient client = new MongoClient(new MongoClientURI(legendConfig.getMongoUri()));
db = subjectExecutor.execute(() -> client.getDatabase(legendConfig.getMongoDb()));
sessionStore = subjectExecutor.execute(() -> SessionStoreFactory.INSTANCE.getInstance(legendConfig.getSessionStoreConfiguration()));
}
SessionStore finalSessionStore = sessionStore;

MongoDatabase finalDb = db;
Pac4jFactory factory =
new Pac4jFactory()
{
Expand All @@ -154,28 +151,19 @@ public Config build()
{
Config config = super.build();

if (legendConfig.getMongoSession() != null
&& legendConfig.getMongoSession().isEnabled())
if (Objects.isNull(finalSessionStore))
{
throw new RuntimeException("Session store needs to be configured if enabled");
}

if (Objects.isNull(finalDb))
{
throw new RuntimeException(
"MongoDB needs to be configured if MongoSession is used");
}
config.setSessionStore(
new SessionContext(
sessionStoreConfiguration.getCryptoAlgorithm(),
sessionStoreConfiguration.getMaxSessionLength(),
finalSessionStore, ImmutableMap.of(J2EContext.class, new J2ESessionStore(),
JaxRsContext.class, new ServletSessionStore()),
subjectExecutor, legendConfig.getTrustedPackages()));

MongoCollection<Document> userSessions = subjectExecutor.execute(
() -> finalDb.getCollection(legendConfig.getMongoSession().getCollection()));

config.setSessionStore(
new MongoDbSessionStore(
legendConfig.getMongoSession().getCryptoAlgorithm(),
legendConfig.getMongoSession().getMaxSessionLength(),
userSessions, ImmutableMap.of(
J2EContext.class, new J2ESessionStore(),
JaxRsContext.class, new ServletSessionStore()),
subjectExecutor, legendConfig.getTrustedPackages()));
}
return config;
}
};
Expand Down Expand Up @@ -208,8 +196,8 @@ JaxRsContext.class, new ServletSessionStore()),
servletConfiguration.setLogout(Collections.singletonList(logoutConfiguration));

legendConfig.getAuthorizers().stream()
.filter(a -> a instanceof MongoDbConsumer)
.forEach(a -> ((MongoDbConsumer) a).setupDb(finalDb));
.filter(a -> a instanceof SessionConsumer)
.forEach(a -> ((SessionConsumer) a).configureDatabase(finalSessionStore.getDatabaseClient(), sessionStoreConfiguration));

factory.setAuthorizers(legendConfig.getAuthorizers().stream()
.collect(Collectors.toMap(a -> a.getClass().getName(), a -> a)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
import io.dropwizard.configuration.YamlConfigurationFactory;
import java.io.IOException;
import java.util.List;

import org.finos.legend.server.pac4j.session.config.SessionStoreConfiguration;
import org.pac4j.core.authorization.authorizer.Authorizer;
import org.pac4j.core.client.Client;
import org.pac4j.core.client.finder.ClientFinder;
import org.pac4j.core.client.finder.DefaultSecurityClientFinder;

@SuppressWarnings({"unused", "WeakerAccess"})
public final class LegendPac4jConfiguration
Expand All @@ -34,9 +35,9 @@ public final class LegendPac4jConfiguration
private List<Authorizer> authorizers = ImmutableList.of();
private List<Client> clients;
private String defaultClient;
private String mongoUri;
private String mongoDb;
private MongoSessionConfiguration mongoSession = new MongoSessionConfiguration();

private SessionStoreConfiguration sessionStoreConfiguration = new SessionStoreConfiguration();

private String callbackPrefix = "";
private List<String> bypassPaths = ImmutableList.of();
private List<String> bypassBranches = ImmutableList.of();
Expand Down Expand Up @@ -137,62 +138,26 @@ private void defaultAuthorizers(List<Authorizer> authorizers)
}
}

public MongoSessionConfiguration getMongoSession()
public SessionStoreConfiguration getSessionStoreConfiguration()
{
return mongoSession;
return sessionStoreConfiguration;
}

public void setMongoSession(MongoSessionConfiguration mongoSession)
public void setSessionStoreConfiguration(SessionStoreConfiguration sessionStoreConfiguration)
{
this.mongoSession = mongoSession;
this.sessionStoreConfiguration = sessionStoreConfiguration;
}

private void defaultMongoSession(MongoSessionConfiguration mongoSession)
private void defaultSessionStoreConfiguration(SessionStoreConfiguration sessionStoreConfiguration)
{
this.mongoSession.defaults(mongoSession);
}

public String getMongoUri()
{
return mongoUri;
this.sessionStoreConfiguration.defaults(sessionStoreConfiguration);
}

public void setDefaultClient(String defaultClient)
{
this.defaultClient = defaultClient;
}

public void setMongoUri(String mongoUri)
{
this.mongoUri = mongoUri;
}

private void defaultMongoUri(String mongoUri)
{
if (Strings.isNullOrEmpty(this.mongoUri))
{
this.mongoUri = mongoUri;
}
}

public String getMongoDb()
{
return mongoDb;
}

public void setMongoDb(String mongoDb)
{
this.mongoDb = mongoDb;
}

private void defaultMongoDb(String mongoDb)
{
if (Strings.isNullOrEmpty(this.mongoDb))
{
this.mongoDb = mongoDb;
}
}

public String getCallbackPrefix()
{
return callbackPrefix;
Expand Down Expand Up @@ -227,96 +192,8 @@ public void loadDefaults(ConfigurationSourceProvider configurationSourceProvider
this.defaultBypassPaths(other.getBypassPaths());
this.defaultCallbackPrefix(other.getCallbackPrefix());
this.defaultClients(other.getClients());
this.defaultMongoDb(other.getMongoDb());
this.defaultMongoSession(other.getMongoSession());
this.defaultMongoUri(other.getMongoUri());
this.defaultSessionStoreConfiguration(other.getSessionStoreConfiguration());
}
}

public static class MongoSessionConfiguration
{
private static final String DEFAULT_CRYPTO_ALGORITHM = "AES";
private static final int DEFAULT_MAX_SESSION_LENGTH = 7200;
private boolean enabled;
private String collection;
private String cryptoAlgorithm = DEFAULT_CRYPTO_ALGORITHM;
private int maxSessionLength = DEFAULT_MAX_SESSION_LENGTH;

public boolean isEnabled()
{
return enabled;
}

public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}

public String getCollection()
{
return collection;
}

public void setCollection(String collection)
{
this.collection = collection;
}

public String getCryptoAlgorithm()
{
return cryptoAlgorithm;
}

public void setCryptoAlgorithm(String cryptoAlgorithm)
{
this.cryptoAlgorithm = cryptoAlgorithm;
}

private void defaultCryptoAlgorithm(String cryptoAlgorithm)
{
if (this.cryptoAlgorithm.equals(DEFAULT_CRYPTO_ALGORITHM))
{
this.cryptoAlgorithm = cryptoAlgorithm;
}
}

public int getMaxSessionLength()
{
return maxSessionLength;
}

public void setMaxSessionLength(int maxSessionLength)
{
this.maxSessionLength = maxSessionLength;
}

private void defaultMaxSessionLength(int maxSessionLength)
{
if (this.maxSessionLength == DEFAULT_MAX_SESSION_LENGTH)
{
this.maxSessionLength = maxSessionLength;
}
}

private void defaultEnabled(boolean enabled)
{
this.enabled = this.enabled || enabled;
}

private void defaultCollection(String collection)
{
if (Strings.isNullOrEmpty(this.collection))
{
this.collection = collection;
}
}

private void defaults(MongoSessionConfiguration other)
{
this.defaultCollection(other.getCollection());
this.defaultCryptoAlgorithm(other.getCryptoAlgorithm());
this.defaultEnabled(other.isEnabled());
this.defaultMaxSessionLength(other.getMaxSessionLength());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
public class HttpSessionStore implements SessionStore<WebContext>
{

private final Map<Class<? extends WebContext>, SessionStore<? extends WebContext>>
private final Map<Class<? extends WebContext>, SessionStore>
underlyingStores;

public HttpSessionStore(
Map<Class<? extends WebContext>, SessionStore<? extends WebContext>> underlyingStores)
Map<Class<? extends WebContext>, SessionStore> underlyingStores)
{
this.underlyingStores = underlyingStores;
}
Expand Down
Loading