Skip to content

Commit

Permalink
JAspi for K9-tilbake
Browse files Browse the repository at this point in the history
  • Loading branch information
jolarsen committed Apr 14, 2024
1 parent 0a76844 commit 3f4754e
Show file tree
Hide file tree
Showing 25 changed files with 1,279 additions and 11 deletions.
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
<sonar.projectKey>navikt_fptilbake</sonar.projectKey>

<!-- Jakarta deps -->
<felles.version>7.1.2</felles.version>
<felles.version>7.1.3</felles.version>
<prosesstask.version>5.0.8</prosesstask.version>
<fpkontrakter.version>9.1.11</fpkontrakter.version>
<fpkontrakter.version>9.1.12</fpkontrakter.version>
<abakus-kontrakt.version>2.1.2</abakus-kontrakt.version>
<verapdf-validation-model.version>1.24.1</verapdf-validation-model.version>
<verapdf-validation-model.version>1.24.2</verapdf-validation-model.version>
<!-- Jakarta deps end -->

<fp-tidsserie.version>2.7.1</fp-tidsserie.version>
Expand Down Expand Up @@ -324,7 +324,7 @@
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>5.15.0</version>
<version>5.15.1</version>
</dependency>

<!-- 3dje parts biblioteker -->
Expand Down
11 changes: 10 additions & 1 deletion web/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<properties>
<!-- versjon brukes fra webapp-modulen under resources/web.swagger/index.html og må være samme som faktisk avhengighet som brukes -->
<swagger-ui.version>5.15.0</swagger-ui.version>
<swagger-ui.version>5.15.1</swagger-ui.version>
</properties>

<build>
Expand Down Expand Up @@ -240,6 +240,15 @@
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-cdi</artifactId>
</dependency>
<!-- k9tilbake -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-jaspi</artifactId>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import java.util.Set;
import java.util.stream.Collectors;

import no.nav.foreldrepenger.tilbakekreving.behandlingslager.fagsak.Fagsystem;
import no.nav.foreldrepenger.tilbakekreving.fagsystem.ApplicationName;

import org.glassfish.jersey.server.ServerProperties;

import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
Expand Down Expand Up @@ -105,8 +108,6 @@ public Set<Class<?>> getClasses() {
VergeRestTjeneste.class,
LosRestTjeneste.class,
FpOversiktRestTjeneste.class,
// autentisering
AuthenticationFilter.class,
// swagger
OpenApiResource.class,
// Applikasjonsoppsett
Expand All @@ -121,6 +122,11 @@ public Set<Class<?>> getClasses() {
if (ENV.isLocal()) {
classes.add(GrunnlagRestTestTjenesteLocalDev.class);
}
// Standard etter fork av fp-tilbake
if (Fagsystem.FPTILBAKE.equals(ApplicationName.hvilkenTilbake())) {
classes.add(AuthenticationFilter.class); // autentisering etter ny standard
}


return Collections.unmodifiableSet(classes);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,44 @@
import javax.naming.NamingException;
import javax.sql.DataSource;

import jakarta.security.auth.message.config.AuthConfigFactory;

import no.nav.foreldrepenger.tilbakekreving.web.server.jetty.sikkerhet.ContextPathHolder;

import no.nav.foreldrepenger.tilbakekreving.web.server.jetty.sikkerhet.jaspic.OidcAuthModule;

import org.eclipse.jetty.ee10.cdi.CdiDecoratingListener;
import org.eclipse.jetty.ee10.cdi.CdiServletContainerInitializer;
import org.eclipse.jetty.ee10.security.jaspi.DefaultAuthConfigFactory;
import org.eclipse.jetty.ee10.security.jaspi.JaspiAuthenticatorFactory;
import org.eclipse.jetty.ee10.security.jaspi.provider.JaspiAuthConfigProvider;
import org.eclipse.jetty.ee10.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
import org.eclipse.jetty.ee10.servlet.security.ConstraintMapping;
import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler;
import org.eclipse.jetty.ee10.webapp.WebAppContext;
import org.eclipse.jetty.plus.jndi.EnvEntry;
import org.eclipse.jetty.security.Constraint;
import org.eclipse.jetty.security.DefaultIdentityService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.jaas.JAASLoginService;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.FlywayException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.slf4j.bridge.SLF4JBridgeHandler;

import no.nav.foreldrepenger.konfig.Environment;
Expand Down Expand Up @@ -65,6 +82,9 @@ private static JettyServer jettyServer(String[] args) {
protected JettyServer(int serverPort) {
this.serverPort = serverPort;
ApplicationName.hvilkenTilbake(); // Sørger for at den initialiseres fra environment
if (Fagsystem.K9TILBAKE.equals(ApplicationName.hvilkenTilbake())) {
setContextAndCookiePath();
}
}

protected void bootStrap() throws Exception {
Expand All @@ -87,6 +107,15 @@ private void konfigurerSikkerhet() {
if (ENV.isLocal()) {
initTrustStore();
}
if (Fagsystem.K9TILBAKE.equals(ApplicationName.hvilkenTilbake())) {
var factory = new DefaultAuthConfigFactory();
factory.registerConfigProvider(new JaspiAuthConfigProvider(new OidcAuthModule()),
"HttpServlet",
"server " + CONTEXT_PATH,
"OIDC Authentication");

AuthConfigFactory.setFactory(factory);
}
}

private static void initTrustStore() {
Expand Down Expand Up @@ -128,7 +157,12 @@ private void migrerDatabaser(DataSource dataSource) {
private void start() throws Exception {
var server = new Server(getServerPort());
server.setConnectors(createConnectors(server).toArray(new Connector[]{}));
server.setHandler(createContext());
if (Fagsystem.K9TILBAKE.equals(ApplicationName.hvilkenTilbake())) {
var handlers = new Handler.Sequence(new ResetLogContextHandler(), createContext());
server.setHandler(handlers);
} else {
server.setHandler(createContext());
}
server.start();
server.join();
}
Expand All @@ -149,6 +183,39 @@ protected HttpConfiguration createHttpConfiguration() {
}

private static ContextHandler createContext() throws IOException {
if (Fagsystem.K9TILBAKE.equals(ApplicationName.hvilkenTilbake())) {
var ctx = new WebAppContext();
ctx.setParentLoaderPriority(true);
// må hoppe litt bukk for å hente web.xml fra classpath i stedet for fra filsystem.
String descriptor;
String baseResource;
try (var factory = ResourceFactory.closeable()) {
var resource = factory.newClassLoaderResource("/WEB-INF/web.xml", false);
descriptor = resource.getURI().toURL().toExternalForm();
baseResource = factory.newResource(".").getRealURI().toURL().toExternalForm();
}
ctx.setDescriptor(descriptor);

ctx.setContextPath(CONTEXT_PATH);

var appname = ApplicationName.hvilkenTilbake();
if (Fagsystem.K9TILBAKE.equals(appname)) {
ctx.setBaseResource(createResourceCollection(ctx));
} else {
ctx.setBaseResourceAsString(baseResource);
}
ctx.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
ctx.setAttribute(CONTAINER_JAR_PATTERN, String.format("%s%s", ENV.isLocal() ? JETTY_LOCAL_CLASSES : "", JETTY_SCAN_LOCATIONS));
// Enable Weld + CDI
ctx.setInitParameter(CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, CdiDecoratingListener.MODE);
ctx.addServletContainerInitializer(new CdiServletContainerInitializer());
ctx.addServletContainerInitializer(new org.jboss.weld.environment.servlet.EnhancedListener());

ctx.setSecurityHandler(createSecurityHandler());
ctx.setThrowUnavailableOnStartupException(true);

return ctx;
}
var ctx = new WebAppContext(CONTEXT_PATH, null, simpleConstraints(), null,
new ErrorPageErrorHandler(), ServletContextHandler.NO_SESSIONS);
ctx.setParentLoaderPriority(true);
Expand Down Expand Up @@ -234,4 +301,35 @@ public static String getCookiePath() {
default -> throw new IllegalArgumentException("Ikke-støttet applikasjonsnavn: " + appname);
};
}

/*
* K9-spesifikke ting som brukes ifm JASPI
*/
/**
* Legges først slik at alltid resetter context før prosesserer nye requests.
* Kjøres først så ikke risikerer andre har satt Request#setHandled(true).
*/
static final class ResetLogContextHandler extends Handler.Abstract {
@Override
public boolean handle(Request request, Response response, Callback callback) {
MDC.clear();
return false;
}
}

private static SecurityHandler createSecurityHandler() {
var securityHandler = new ConstraintSecurityHandler();
securityHandler.setAuthenticatorFactory(new JaspiAuthenticatorFactory());
var loginService = new JAASLoginService();
loginService.setName("jetty-login");
loginService.setLoginModuleName("jetty-login");
loginService.setIdentityService(new DefaultIdentityService());
securityHandler.setLoginService(loginService);
return securityHandler;
}

private void setContextAndCookiePath() {
ContextPathHolder.instance(CONTEXT_PATH, "/k9");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package no.nav.foreldrepenger.tilbakekreving.web.server.jetty.sikkerhet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Denne eksisterer nå kun pga exp/contract + fp/k9tilbake og cookiepath /k9
*/
public class ContextPathHolder {

private static final Logger LOG = LoggerFactory.getLogger(ContextPathHolder.class);

private static volatile ContextPathHolder instance; // NOSONAR
private final String cookiePath;
private final boolean harSattCookiePath;

private ContextPathHolder(String cookiePath) {
this.harSattCookiePath = cookiePath != null;
this.cookiePath = validerCookiePath(cookiePath);
}

public static ContextPathHolder instance() {
var inst = instance;
if (inst == null) {
inst = new ContextPathHolder(null);
instance = inst;
}
return inst;
}

@Deprecated // K9tilbake trenger denne
@SuppressWarnings("unused")
public static ContextPathHolder instance(@SuppressWarnings("unused") String contextPath, String cookiePath) {
var inst = instance;
if (inst == null) {
inst = new ContextPathHolder(cookiePath);
instance = inst;
}
return inst;
}

private String validerCookiePath(String cookiePath) {
if (cookiePath == null) {
return "/";
}
if (!cookiePath.startsWith("/")) {
LOG.warn("CookiePath ({}) er ugyldig som cookiePath, forkaster og bruker default ('/').", cookiePath);
return "/";
}
return cookiePath;
}

public String getCookiePath() {
return cookiePath;
}

public boolean harSattCookiePath() {
return harSattCookiePath;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Denne modulen dekker JASPI, JAAS og Tokenvalidering - LEGACY for bruk av K9-tilbake
-

Kode relatert til Context, OIDC-config og Tokenhenting/veksling ligger i felles-oidc

Sikkerhetskontekst skal hentes fra KontekstHolder, ikke via SubjectHandler

Kort om hovedkomponentene

OidcAuthModule
* Inngangsportalen og konfigureres programmatisk i applikasjonenes Jetty-oppsett
* validateRequest får inn alle requests og beskyttede ressurser håndteres av lokal oidcLogin
* Login lager en LoginContext og forsøker en login (validere token, sette context)
* Dersom unathorized: Hvis Bearer -> 401, ellers redirect til OpenAm-login
* Spesialhåndtering av interaktive requests auth-flow, cookies og refresh 2 minutt før tokenutløp
* Stateless connection - ingen session

LoginModule(s)
* Gjør tokenvalidering og fortsetter prosess basert på resultat
* Vil sørge for en kontekst bestående av Subject, Principal m/identType og token
* Får inn subject og callback i initialize()
* Vanlig OIDC-requests håndteres ved tokenvalidering og setter Authentication for request

OidcTokenValidator validerer tokens fra ulike issuers og henter jwks til keycache.
Er for tiden en blanding av jose4j og nimbusds (og litt no nav sikkerhet)

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package no.nav.foreldrepenger.tilbakekreving.web.server.jetty.sikkerhet.context;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import no.nav.vedtak.sikkerhet.kontekst.KontekstHolder;

public class ContextCleaner {

private static final Logger LOG = LoggerFactory.getLogger(ContextCleaner.class);

private ContextCleaner() {
}

public static void enusureCleanContext() {
try {
if (KontekstHolder.harKontekst()) {
LOG.trace("FPFELLES KONTEKST fjernet i ContextCleaner - burde vært fjernet før");
KontekstHolder.fjernKontekst();
}
} catch (Exception e) {
LOG.trace("FPFELLES ConClean: kunne ikke fjerne kontekst", e);
}
}
}

0 comments on commit 3f4754e

Please sign in to comment.