diff --git a/legend-sdlc-server/pom.xml b/legend-sdlc-server/pom.xml
index b9dbe804e7..bca561e4b1 100644
--- a/legend-sdlc-server/pom.xml
+++ b/legend-sdlc-server/pom.xml
@@ -129,6 +129,16 @@
+
+ org.finos.legend.shared
+ legend-shared-pac4j
+
+
+ com.zaxxer
+ HikariCP
+
+
+
org.finos.legend.shared
legend-shared-pac4j-kerberos
@@ -177,6 +187,11 @@
+
+ org.pac4j.jax-rs
+ core
+
+
com.google.inject
guice
diff --git a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/gitlab/auth/GitLabSessionBuilder.java b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/gitlab/auth/GitLabSessionBuilder.java
index e09d331677..556f11b5e1 100644
--- a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/gitlab/auth/GitLabSessionBuilder.java
+++ b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/gitlab/auth/GitLabSessionBuilder.java
@@ -25,7 +25,7 @@
import java.time.Instant;
import java.util.Objects;
-class GitLabSessionBuilder extends SessionBuilder
+public class GitLabSessionBuilder extends SessionBuilder
{
private final GitLabTokenManager tokenManager;
@@ -130,7 +130,7 @@ static boolean isSupportedProfile(CommonProfile profile)
return (profile instanceof KerberosProfile) || (profile instanceof OidcProfile) || (profile instanceof GitlabPersonalAccessTokenProfile);
}
- static GitLabSessionBuilder newBuilder(GitLabAppInfo appInfo)
+ public static GitLabSessionBuilder newBuilder(GitLabAppInfo appInfo)
{
return new GitLabSessionBuilder(GitLabTokenManager.newTokenManager(appInfo));
}
diff --git a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/gitlab/resources/GitLabAuthCheckResource.java b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/gitlab/resources/GitLabAuthCheckResource.java
index 7d769fdc09..6cb68ce8b7 100644
--- a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/gitlab/resources/GitLabAuthCheckResource.java
+++ b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/gitlab/resources/GitLabAuthCheckResource.java
@@ -21,7 +21,7 @@
import org.finos.legend.sdlc.server.gitlab.auth.GitLabSession;
import org.finos.legend.sdlc.server.gitlab.auth.GitLabUserContext;
import org.finos.legend.sdlc.server.resources.BaseResource;
-import org.finos.legend.sdlc.server.tools.SessionUtil;
+import org.finos.legend.sdlc.server.tools.SessionProvider;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
@@ -31,23 +31,30 @@
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
+import static org.finos.legend.sdlc.server.auth.LegendSDLCWebFilter.SESSION_ATTRIBUTE;
+
@Path("/auth")
public class GitLabAuthCheckResource extends BaseResource
{
-
private final HttpServletRequest httpRequest;
private final HttpServletResponse httpResponse;
private final GitLabAuthorizerManager authorizerManager;
private final GitLabAppInfo appInfo;
+ private final SessionProvider sessionProvider;
@Inject
- public GitLabAuthCheckResource(HttpServletRequest httpRequest, HttpServletResponse httpResponse, GitLabAuthorizerManager authorizerManager, GitLabAppInfo appInfo)
+ public GitLabAuthCheckResource(HttpServletRequest httpRequest,
+ HttpServletResponse httpResponse,
+ GitLabAuthorizerManager authorizerManager,
+ GitLabAppInfo appInfo,
+ SessionProvider sessionProvider)
{
super();
this.httpRequest = httpRequest;
this.httpResponse = httpResponse;
this.authorizerManager = authorizerManager;
this.appInfo = appInfo;
+ this.sessionProvider = sessionProvider;
}
@GET
@@ -57,7 +64,13 @@ public boolean isAuthorized()
{
return executeWithLogging("checking authorization", () ->
{
- Session session = SessionUtil.findSession(httpRequest);
+ Session session = SessionProvider.findSession(httpRequest);
+
+ if (session == null)
+ {
+ session = sessionProvider.getSessionFromSessionStore(httpRequest, httpResponse, appInfo);
+ httpRequest.setAttribute(SESSION_ATTRIBUTE, session);
+ }
if (session instanceof GitLabSession)
{
diff --git a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/guice/AbstractBaseModule.java b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/guice/AbstractBaseModule.java
index 569fafd1cc..bf5c338a56 100644
--- a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/guice/AbstractBaseModule.java
+++ b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/guice/AbstractBaseModule.java
@@ -17,6 +17,7 @@
import com.google.inject.Binder;
import com.google.inject.Provides;
import com.hubspot.dropwizard.guicier.DropwizardAwareModule;
+import org.eclipse.collections.api.factory.Maps;
import org.finos.legend.sdlc.server.BaseLegendSDLCServer;
import org.finos.legend.sdlc.server.BaseServer.ServerInfo;
import org.finos.legend.sdlc.server.config.LegendSDLCServerConfiguration;
@@ -224,6 +225,14 @@
import org.finos.legend.sdlc.server.resources.workflow.project.user.WorkspaceWorkflowsResource;
import org.finos.legend.sdlc.server.resources.workspace.project.user.WorkspacesResource;
import org.finos.legend.sdlc.server.tools.BackgroundTaskProcessor;
+import org.finos.legend.sdlc.server.tools.SessionProvider;
+import org.finos.legend.server.pac4j.LegendPac4jConfiguration;
+import org.finos.legend.server.pac4j.hazelcaststore.HazelcastSessionStore;
+import org.pac4j.core.context.J2EContext;
+import org.pac4j.core.context.session.J2ESessionStore;
+import org.pac4j.core.context.session.SessionStore;
+import org.pac4j.jax.rs.pac4j.JaxRsContext;
+import org.pac4j.jax.rs.servlet.pac4j.ServletSessionStore;
import java.util.Collections;
import java.util.List;
@@ -257,6 +266,7 @@ public void configure(Binder binder)
binder.bind(LegendSDLCServerFeaturesConfiguration.class).toProvider(this::getFeaturesConfiguration);
binder.bind(BackgroundTaskProcessor.class).toProvider(this.server::getBackgroundTaskProcessor);
binder.bind(ProjectStructurePlatformExtensions.class).toInstance(buildProjectStructurePlatformExtensions());
+ binder.bind(SessionProvider.class).toProvider(this::getSessionProvider);
bindResources(binder);
}
@@ -539,6 +549,25 @@ private AuthClientInjector resolveAuthClientInjector()
return builder -> builder;
}
+ private SessionProvider getSessionProvider()
+ {
+ LegendPac4jConfiguration config = getConfiguration().getPac4jConfiguration();
+ return new SessionProvider(getSessionStoreFromConfig(config));
+ }
+
+ private SessionStore getSessionStoreFromConfig(LegendPac4jConfiguration config)
+ {
+ if (config.getHazelcastSession() != null && config.getHazelcastSession().isEnabled())
+ {
+ return new HazelcastSessionStore(
+ config.getHazelcastSession().getConfigFilePath(),
+ Maps.immutable.with(
+ J2EContext.class, new J2ESessionStore(),
+ JaxRsContext.class, new ServletSessionStore()).castToMap());
+ }
+ return null;
+ }
+
@Provides
@Named("applicationName")
public String provideApplicationName(LegendSDLCServerConfiguration configuration)
diff --git a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/guice/UserContext.java b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/guice/UserContext.java
index c84d3b1fd2..2159c428f2 100644
--- a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/guice/UserContext.java
+++ b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/guice/UserContext.java
@@ -17,13 +17,12 @@
import com.google.inject.servlet.RequestScoped;
import org.finos.legend.sdlc.server.auth.Session;
import org.finos.legend.sdlc.server.error.LegendSDLCServerException;
-import org.finos.legend.sdlc.server.tools.SessionUtil;
+import org.finos.legend.sdlc.server.tools.SessionProvider;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
@RequestScoped
public class UserContext
{
@@ -37,7 +36,7 @@ public UserContext(HttpServletRequest httpRequest, HttpServletResponse httpRespo
{
this.httpRequest = httpRequest;
this.httpResponse = httpResponse;
- this.session = LegendSDLCServerException.validateNonNull(SessionUtil.findSession(httpRequest), "Invalid request");
+ this.session = LegendSDLCServerException.validateNonNull(SessionProvider.findSession(httpRequest), "Invalid request");
}
public String getCurrentUser()
diff --git a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/tools/SessionUtil.java b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/tools/SessionProvider.java
similarity index 65%
rename from legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/tools/SessionUtil.java
rename to legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/tools/SessionProvider.java
index a2c35c5622..08c64c1f3c 100644
--- a/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/tools/SessionUtil.java
+++ b/legend-sdlc-server/src/main/java/org/finos/legend/sdlc/server/tools/SessionProvider.java
@@ -16,18 +16,56 @@
import org.finos.legend.sdlc.server.auth.LegendSDLCWebFilter;
import org.finos.legend.sdlc.server.auth.Session;
+import org.finos.legend.sdlc.server.gitlab.GitLabAppInfo;
+import org.finos.legend.sdlc.server.gitlab.auth.GitLabSessionBuilder;
+import org.finos.legend.server.pac4j.gitlab.GitlabClient;
+import org.pac4j.core.context.J2EContext;
+import org.pac4j.core.context.Pac4jConstants;
+import org.pac4j.core.context.WebContext;
+import org.pac4j.core.context.session.SessionStore;
+import org.pac4j.core.profile.CommonProfile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import java.util.Map;
-public class SessionUtil
+public class SessionProvider
{
- private static final Logger LOGGER = LoggerFactory.getLogger(SessionUtil.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(SessionProvider.class);
+
+ private final SessionStore sessionStore;
+
+ public SessionProvider(SessionStore sessionStore)
+ {
+ this.sessionStore = sessionStore;
+ }
+
+ public Session getSessionFromSessionStore(HttpServletRequest httpRequest, HttpServletResponse httpResponse, GitLabAppInfo appInfo)
+ {
+ if (sessionStore != null)
+ {
+ WebContext context = new J2EContext(httpRequest, httpResponse);
+ Map profileMap =
+ (Map) sessionStore.get(context, Pac4jConstants.USER_PROFILES);
+
+ if (profileMap != null)
+ {
+ CommonProfile profile = profileMap.get(GitlabClient.GITLAB_CLIENT_NAME);
+ if (profile != null)
+ {
+ return GitLabSessionBuilder.newBuilder(appInfo).withProfile(profile).build();
+ }
+ }
+ }
+
+ return null;
+ }
public static Session findSession(ServletRequest request)
{
diff --git a/legend-sdlc-server/src/test/resources/config-sample.yaml b/legend-sdlc-server/src/test/resources/config-sample.yaml
index efd3b427b9..5f4dba93fc 100644
--- a/legend-sdlc-server/src/test/resources/config-sample.yaml
+++ b/legend-sdlc-server/src/test/resources/config-sample.yaml
@@ -59,6 +59,9 @@ pac4j:
secret: $APP_SECRET
discoveryUri: https://$GITLAB_HOST/.well-known/openid-configuration
scope: openid profile api
+# hazelcastSession:
+# enabled: true
+# configFilePath: legend-sdlc-server/src/test/resources/hazelcast.yaml
bypassPaths:
- /api/info
- /api/server/info
diff --git a/legend-sdlc-server/src/test/resources/hazelcast.yaml b/legend-sdlc-server/src/test/resources/hazelcast.yaml
new file mode 100644
index 0000000000..30a212dae1
--- /dev/null
+++ b/legend-sdlc-server/src/test/resources/hazelcast.yaml
@@ -0,0 +1,31 @@
+# Copyright 2023 Goldman Sachs
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+hazelcast:
+ cluster-name: legend-hazelcast-session-store-cluster
+ instance-name: legend-hazelcast-session-store
+ network:
+ port:
+ port: 5701
+ auto-increment: false
+ join:
+ multicast:
+ enabled: false
+ tcp-ip:
+ enabled: true
+ member-list:
+ - localhost
+ map:
+ session-store:
+ time-to-live-seconds: 7200
diff --git a/pom.xml b/pom.xml
index f2136170d7..3fd310be90 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,9 +70,9 @@
[11,12),[17,18)
- 4.24.0
+ 4.25.0
4.5.11
- 0.23.8
+ 0.24.0
1.15
@@ -1379,6 +1379,11 @@
pac4j-oidc
${pac4j.version}
+
+ org.pac4j.jax-rs
+ core
+ 3.0.0
+
org.slf4j