2121package eu .openanalytics .containerproxy ;
2222
2323import com .fasterxml .jackson .datatype .jsr353 .JSR353Module ;
24+ import eu .openanalytics .containerproxy .backend .ContainerBackendFactory ;
25+ import eu .openanalytics .containerproxy .backend .docker .DockerEngineBackend ;
26+ import eu .openanalytics .containerproxy .backend .docker .DockerSwarmBackend ;
27+ import eu .openanalytics .containerproxy .backend .kubernetes .KubernetesBackend ;
2428import eu .openanalytics .containerproxy .service .hearbeat .ActiveProxiesService ;
2529import eu .openanalytics .containerproxy .service .hearbeat .HeartbeatService ;
26- import eu .openanalytics .containerproxy .service .hearbeat .SessionReActivatorService ;
30+ import eu .openanalytics .containerproxy .service .hearbeat .IHeartbeatProcessor ;
31+ import eu .openanalytics .containerproxy .util .LoggingConfigurer ;
2732import eu .openanalytics .containerproxy .util .ProxyMappingManager ;
2833import io .undertow .Handlers ;
2934import io .undertow .server .handlers .SameSiteCookieHandler ;
3843import org .springframework .boot .actuate .health .HealthIndicator ;
3944import org .springframework .boot .actuate .redis .RedisHealthIndicator ;
4045import org .springframework .boot .autoconfigure .SpringBootApplication ;
46+ import org .springframework .boot .autoconfigure .condition .ConditionalOnMissingBean ;
4147import org .springframework .boot .autoconfigure .condition .ConditionalOnProperty ;
48+ import org .springframework .boot .autoconfigure .security .servlet .UserDetailsServiceAutoConfiguration ;
4249import org .springframework .boot .web .embedded .undertow .UndertowServletWebServerFactory ;
4350import org .springframework .boot .web .server .PortInUseException ;
4451import org .springframework .boot .web .servlet .FilterRegistrationBean ;
4754import org .springframework .core .env .Environment ;
4855import org .springframework .data .redis .connection .RedisConnectionFactory ;
4956import org .springframework .scheduling .annotation .EnableAsync ;
57+ import org .springframework .scheduling .annotation .EnableScheduling ;
5058import org .springframework .scheduling .concurrent .ThreadPoolTaskExecutor ;
5159import org .springframework .security .core .session .SessionRegistry ;
5260import org .springframework .security .web .session .HttpSessionEventPublisher ;
5361import org .springframework .session .FindByIndexNameSessionRepository ;
5462import org .springframework .session .Session ;
55- import org .springframework .session .web .http .DefaultCookieSerializer ;
5663import org .springframework .session .security .SpringSessionBackedSessionRegistry ;
64+ import org .springframework .session .web .http .DefaultCookieSerializer ;
5765import org .springframework .web .filter .FormContentFilter ;
5866
5967import javax .annotation .PostConstruct ;
6371import java .nio .file .Files ;
6472import java .nio .file .Paths ;
6573import java .security .Security ;
66- import java .util .Arrays ;
74+ import java .util .List ;
6775import java .util .Objects ;
6876import java .util .Properties ;
6977import java .util .concurrent .Executor ;
7078
79+ import static eu .openanalytics .containerproxy .api .ApiSecurityService .PROP_API_SECURITY_HIDE_SPEC_DETAILS ;
80+ import static eu .openanalytics .containerproxy .service .ProxyService .PROPERTY_STOP_PROXIES_ON_SHUTDOWN ;
81+
82+ @ EnableScheduling
7183@ EnableAsync
72- @ SpringBootApplication
84+ @ SpringBootApplication ( exclude = { UserDetailsServiceAutoConfiguration . class })
7385@ ComponentScan ("eu.openanalytics" )
7486public class ContainerProxyApplication {
7587 public static final String CONFIG_FILENAME = "application.yml" ;
@@ -94,10 +106,18 @@ public class ContainerProxyApplication {
94106 public static Boolean secureCookiesEnabled ;
95107 public static String sameSiteCookiePolicy ;
96108
97- public static void main ( String [] args ) {
109+ static {
98110 Security .addProvider (new BouncyCastleProvider ());
111+ ContainerBackendFactory .addBackend ("docker" , DockerEngineBackend .class );
112+ ContainerBackendFactory .addBackend ("docker-swarm" , DockerSwarmBackend .class );
113+ ContainerBackendFactory .addBackend ("kubernetes" , KubernetesBackend .class );
114+ }
115+
116+ public static void main (String [] args ) {
99117 SpringApplication app = new SpringApplication (ContainerProxyApplication .class );
100118
119+ app .addListeners (new LoggingConfigurer ());
120+
101121 boolean hasExternalConfig = Files .exists (Paths .get (CONFIG_FILENAME ));
102122 if (!hasExternalConfig ) app .setAdditionalProfiles (CONFIG_DEMO_PROFILE );
103123
@@ -131,6 +151,26 @@ public void init() {
131151 if (sameSiteCookiePolicy .equalsIgnoreCase ("none" ) && !secureCookiesEnabled ) {
132152 log .warn ("WARNING: Invalid configuration detected: same-site-cookie policy is set to None, but secure-cookies are not enabled. Secure cookies must be enabled when using None as same-site-cookie policy " );
133153 }
154+
155+
156+ if (environment .getProperty ("proxy.store-mode" , "" ).equalsIgnoreCase ("Redis" )) {
157+ if (!environment .getProperty ("spring.session.store-type" , "" ).equalsIgnoreCase ("redis" )) {
158+ // running in HA mode, but not using Redis sessions
159+ log .warn ("WARNING: Invalid configuration detected: store-mode is set to Redis (i.e. High-Availability mode), but you are not using Redis for user sessions!" );
160+ }
161+ if (environment .getProperty (PROPERTY_STOP_PROXIES_ON_SHUTDOWN , Boolean .class , true )) {
162+ // running in HA mode, but proxies are removed when shutting down
163+ log .warn ("WARNING: Invalid configuration detected: store-mode is set to Redis (i.e. High-Availability mode), but proxies are stopped at shutdown of server!" );
164+ }
165+ }
166+
167+ boolean hideSpecDetails = environment .getProperty (PROP_API_SECURITY_HIDE_SPEC_DETAILS , Boolean .class , true );
168+ if (!hideSpecDetails ) {
169+ log .warn ("WARNING: Insecure configuration detected: The API is configured to return the full spec of proxies, " +
170+ "this may contain sensitive values such as the container image, secret environment variables etc. " +
171+ "Remove the proxy.api-security.hide-spec-details property to enable API security." );
172+ }
173+
134174 }
135175
136176 @ Autowired (required = false )
@@ -213,7 +253,7 @@ public Health health() {
213253 @ Bean
214254 @ ConditionalOnProperty (name = "spring.session.store-type" , havingValue = "redis" )
215255 public <S extends Session > SessionRegistry sessionRegistry (FindByIndexNameSessionRepository <S > sessionRepository ) {
216- return new SpringSessionBackedSessionRegistry <S >(sessionRepository );
256+ return new SpringSessionBackedSessionRegistry <>(sessionRepository );
217257 }
218258
219259 @ Bean
@@ -231,8 +271,14 @@ public Executor taskExecutor() {
231271 }
232272
233273 @ Bean
234- public HeartbeatService heartbeatService (ActiveProxiesService activeProxiesService , SessionReActivatorService sessionReActivatorService ) {
235- return new HeartbeatService (Arrays .asList (activeProxiesService , sessionReActivatorService ));
274+ public HeartbeatService heartbeatService (List <IHeartbeatProcessor > heartbeatProcessors ) {
275+ return new HeartbeatService (heartbeatProcessors );
276+ }
277+
278+ @ Bean
279+ @ ConditionalOnMissingBean
280+ public ActiveProxiesService activeProxiesService () {
281+ return new ActiveProxiesService ();
236282 }
237283
238284 public static Properties getDefaultProperties () {
@@ -249,6 +295,7 @@ public static Properties getDefaultProperties() {
249295
250296 // disable logging of requests, since this reads part of the requests and therefore undertow is unable to correctly handle those requests
251297 properties .put ("logging.level.org.springframework.web.servlet.DispatcherServlet" , "INFO" );
298+ properties .put ("logging.level.io.fabric8.kubernetes.client.dsl.internal.VersionUsageUtils" , "ERROR" );
252299
253300 properties .put ("spring.application.name" , "ContainerProxy" );
254301
@@ -263,8 +310,9 @@ public static Properties getDefaultProperties() {
263310 properties .put ("management.server.port" , "9090" );
264311 // enable prometheus endpoint by default (but not the exporter)
265312 properties .put ("management.endpoint.prometheus.enabled" , "true" );
313+ properties .put ("management.endpoint.recyclable.enabled" , "true" );
266314 // include prometheus and health endpoint in exposure
267- properties .put ("management.endpoints.web.exposure.include" , "health,prometheus" );
315+ properties .put ("management.endpoints.web.exposure.include" , "health,prometheus,recyclable " );
268316
269317 // ====================
270318
@@ -284,6 +332,10 @@ public static Properties getDefaultProperties() {
284332
285333 properties .put ("spring.config.use-legacy-processing" , true );
286334
335+ // disable openapi docs and swagger ui
336+ properties .put ("springdoc.api-docs.enabled" , false );
337+ properties .put ("springdoc.swagger-ui.enabled" , false );
338+
287339 return properties ;
288340 }
289341
@@ -293,4 +345,4 @@ private static void setDefaultProperties(SpringApplication app) {
293345 System .setProperty ("jdk.serialSetFilterAfterRead" , "true" );
294346 }
295347
296- }
348+ }
0 commit comments