25
25
import stroom .config .app .AppConfig ;
26
26
import stroom .config .app .Config ;
27
27
import stroom .config .app .SecurityConfig ;
28
+ import stroom .config .app .SessionConfig ;
29
+ import stroom .config .app .SessionCookieConfig ;
28
30
import stroom .config .app .StroomYamlUtil ;
29
31
import stroom .config .global .impl .ConfigMapper ;
30
32
import stroom .dropwizard .common .AdminServlets ;
54
56
import stroom .util .logging .LambdaLoggerFactory ;
55
57
import stroom .util .logging .LogUtil ;
56
58
import stroom .util .shared .AbstractConfig ;
59
+ import stroom .util .shared .ModelStringUtil ;
57
60
import stroom .util .shared .ResourcePaths ;
61
+ import stroom .util .time .StroomDuration ;
58
62
import stroom .util .validation .ValidationModule ;
59
63
import stroom .util .yaml .YamlUtil ;
60
64
70
74
import jakarta .inject .Inject ;
71
75
import jakarta .servlet .DispatcherType ;
72
76
import jakarta .servlet .FilterRegistration ;
73
- import jakarta .servlet .SessionCookieConfig ;
74
77
import jakarta .validation .ValidatorFactory ;
75
78
import org .eclipse .jetty .server .session .SessionHandler ;
76
79
import org .eclipse .jetty .servlets .CrossOriginFilter ;
77
80
78
81
import java .io .IOException ;
79
82
import java .nio .file .Path ;
80
83
import java .nio .file .Paths ;
84
+ import java .time .Duration ;
81
85
import java .util .EnumSet ;
82
86
import java .util .Objects ;
83
87
@@ -220,15 +224,14 @@ public void run(final Config configuration, final Environment environment) {
220
224
// We want Stroom to use the root path so we need to move Dropwizard's path.
221
225
environment .jersey ().setUrlPattern (ResourcePaths .API_ROOT_PATH + "/*" );
222
226
223
- // Set up a session handler for Jetty
224
- configureSessionHandling (environment );
225
-
226
- // Ensure the session cookie that provides JSESSIONID is secure.
227
- // Need to get it from ConfigMapper not AppConfig as ConfigMapper is now the source of
228
- // truth for config.
227
+ // Need to get these config classed from ConfigMapper as the main appInjector is not created yet
228
+ // and configuration only holds the YAML view of the config, not the DB view.
229
229
final ConfigMapper configMapper = bootStrapInjector .getInstance (ConfigMapper .class );
230
- final stroom .config .app .SessionCookieConfig sessionCookieConfig = configMapper .getConfigObject (
231
- stroom .config .app .SessionCookieConfig .class );
230
+ final SessionCookieConfig sessionCookieConfig = configMapper .getConfigObject (SessionCookieConfig .class );
231
+ final SessionConfig sessionConfig = configMapper .getConfigObject (SessionConfig .class );
232
+
233
+ // Set up a session handler for Jetty
234
+ configureSessionHandling (environment , sessionConfig );
232
235
configureSessionCookie (environment , sessionCookieConfig );
233
236
234
237
// Configure Cross-Origin Resource Sharing.
@@ -273,11 +276,11 @@ public void run(final Config configuration, final Environment environment) {
273
276
274
277
private void showNodeInfo (final Config configuration ) {
275
278
LOGGER .info (""
276
- + "\n ********************************************************************************"
277
- + "\n Stroom home: " + homeDirProvider .get ().toAbsolutePath ().normalize ()
278
- + "\n Stroom temp: " + tempDirProvider .get ().toAbsolutePath ().normalize ()
279
- + "\n Node name: " + getNodeName (configuration .getYamlAppConfig ())
280
- + "\n ********************************************************************************" );
279
+ + "\n ********************************************************************************"
280
+ + "\n Stroom home: " + homeDirProvider .get ().toAbsolutePath ().normalize ()
281
+ + "\n Stroom temp: " + tempDirProvider .get ().toAbsolutePath ().normalize ()
282
+ + "\n Node name: " + getNodeName (configuration .getYamlAppConfig ())
283
+ + "\n ********************************************************************************" );
281
284
}
282
285
283
286
private void warnAboutDefaultOpenIdCreds (final Config configuration , final Injector injector ) {
@@ -299,17 +302,17 @@ private void warnAboutDefaultOpenIdCreds(final Config configuration, final Injec
299
302
.getFullPathStr (AbstractOpenIdConfig .PROP_NAME_IDP_TYPE );
300
303
301
304
LOGGER .warn ("\n " +
302
- "\n -----------------------------------------------------------------------------" +
303
- "\n " +
304
- "\n WARNING!" +
305
- "\n " +
306
- "\n Using default and publicly available Open ID authentication credentials. " +
307
- "\n This is insecure! These should only be used in test/demo environments. " +
308
- "\n Set " + propPath + " to INTERNAL_IDP/EXTERNAL_IDP for production environments." +
309
- "\n " +
310
- "\n " + defaultOpenIdCredentials .getApiKey () +
311
- "\n -----------------------------------------------------------------------------" +
312
- "\n " );
305
+ "\n -----------------------------------------------------------------------------" +
306
+ "\n " +
307
+ "\n WARNING!" +
308
+ "\n " +
309
+ "\n Using default and publicly available Open ID authentication credentials. " +
310
+ "\n This is insecure! These should only be used in test/demo environments. " +
311
+ "\n Set " + propPath + " to INTERNAL_IDP/EXTERNAL_IDP for production environments." +
312
+ "\n " +
313
+ "\n " + defaultOpenIdCredentials .getApiKey () +
314
+ "\n -----------------------------------------------------------------------------" +
315
+ "\n " );
313
316
}
314
317
}
315
318
@@ -344,35 +347,56 @@ private void validateAppConfig(final Config config, final Path configFile) {
344
347
345
348
if (result .hasErrors () && appConfig .isHaltBootOnConfigValidationFailure ()) {
346
349
LOGGER .error ("Application configuration is invalid. Stopping Stroom. To run Stroom with invalid " +
347
- "configuration, set {} to false, however this is not advised!" ,
350
+ "configuration, set {} to false, however this is not advised!" ,
348
351
appConfig .getFullPathStr (AppConfig .PROP_NAME_HALT_BOOT_ON_CONFIG_VALIDATION_FAILURE ));
349
352
System .exit (1 );
350
353
}
351
354
}
352
355
353
- private static void configureSessionHandling (final Environment environment ) {
354
- SessionHandler sessionHandler = new SessionHandler ();
356
+ private void configureSessionHandling (final Environment environment ,
357
+ final SessionConfig sessionConfig ) {
358
+
359
+ final SessionHandler sessionHandler = new SessionHandler ();
355
360
// We need to give our session cookie a name other than JSESSIONID, otherwise it might
356
361
// clash with other services running on the same domain.
357
362
sessionHandler .setSessionCookie (SESSION_COOKIE_NAME );
363
+ long maxInactiveIntervalSecs = NullSafe .getOrElse (
364
+ sessionConfig .getMaxInactiveInterval (),
365
+ StroomDuration ::getDuration ,
366
+ Duration ::toSeconds ,
367
+ -1L );
368
+ if (maxInactiveIntervalSecs > Integer .MAX_VALUE ) {
369
+ maxInactiveIntervalSecs = -1 ;
370
+ }
371
+ LOGGER .info ("Setting session maxInactiveInterval to {} secs ({})" ,
372
+ ModelStringUtil .formatCsv (maxInactiveIntervalSecs ),
373
+ (maxInactiveIntervalSecs > 0
374
+ ? Duration .ofSeconds (maxInactiveIntervalSecs ).toString ()
375
+ : String .valueOf (maxInactiveIntervalSecs )));
376
+
377
+ // If we don't let sessions expire then the Map of HttpSession in SessionListListener
378
+ // will grow and grow
379
+ sessionHandler .setMaxInactiveInterval ((int ) maxInactiveIntervalSecs );
380
+
358
381
environment .servlets ().setSessionHandler (sessionHandler );
359
382
environment .jersey ().register (SessionFactoryProvider .class );
360
383
}
361
384
362
- private static void configureSessionCookie (final Environment environment ,
363
- final stroom . config . app . SessionCookieConfig config ) {
385
+ private void configureSessionCookie (final Environment environment ,
386
+ final SessionCookieConfig sessionCookieConfig ) {
364
387
// Ensure the session cookie that provides JSESSIONID is secure.
365
- final SessionCookieConfig sessionCookieConfig = environment
388
+ final jakarta . servlet . SessionCookieConfig servletSessionCookieConfig = environment
366
389
.getApplicationContext ()
367
390
.getServletContext ()
368
391
.getSessionCookieConfig ();
369
- sessionCookieConfig .setSecure (config .isSecure ());
370
- sessionCookieConfig .setHttpOnly (config .isHttpOnly ());
392
+ servletSessionCookieConfig .setSecure (sessionCookieConfig .isSecure ());
393
+ servletSessionCookieConfig .setHttpOnly (sessionCookieConfig .isHttpOnly ());
371
394
// TODO : Add `SameSite=Strict` when supported by JEE
372
395
}
373
396
374
397
private static void configureCors (io .dropwizard .core .setup .Environment environment ) {
375
- FilterRegistration .Dynamic cors = environment .servlets ().addFilter ("CORS" , CrossOriginFilter .class );
398
+ final FilterRegistration .Dynamic cors = environment .servlets ()
399
+ .addFilter ("CORS" , CrossOriginFilter .class );
376
400
cors .addMappingForUrlPatterns (EnumSet .allOf (DispatcherType .class ), true , "/*" );
377
401
cors .setInitParameter (CrossOriginFilter .ALLOWED_METHODS_PARAM , "GET,PUT,POST,DELETE,OPTIONS,PATCH" );
378
402
cors .setInitParameter (CrossOriginFilter .ALLOWED_ORIGINS_PARAM , "*" );
0 commit comments