From b83945ad885dec8d108a61050ca20de298db93e0 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Thu, 4 Jul 2024 14:36:38 +0200 Subject: [PATCH 01/48] init gateway from internal archtype --- .gitignore | 34 +++ Dockerfile | 8 - pom.xml | 59 ++++ refarch-gateway/.gitignore | 32 ++ refarch-gateway/checkstyle.xml | 101 +++++++ refarch-gateway/pom.xml | 277 ++++++++++++++++++ refarch-gateway/runLocal.bat | 1 + refarch-gateway/runLocal.sh | 2 + refarch-gateway/runLocalNoSecurity.bat | 1 + refarch-gateway/runLocalNoSecurity.sh | 2 + .../java/@muenchen/ApiGatewayApplication.java | 41 +++ .../configuration/GuiConfiguration.java | 44 +++ .../NoSecurityConfiguration.java | 31 ++ .../configuration/SecurityConfiguration.java | 104 +++++++ .../configuration/VueCacheConfiguration.java | 34 +++ .../WebSessionConfiguration.java | 117 ++++++++ .../ParameterPollutionException.java | 27 ++ .../CsrfTokenAppendingHelperFilter.java | 37 +++ .../filter/DistributedTracingFilter.java | 59 ++++ .../GlobalAuthenticationErrorFilter.java | 93 ++++++ .../filter/GlobalBackend5xxTo400Mapper.java | 109 +++++++ ...GlobalRequestParameterPollutionFilter.java | 65 ++++ .../src/main/resources/application-dev.yml | 63 ++++ .../src/main/resources/application-kon.yml | 63 ++++ .../src/main/resources/application-local.yml | 58 ++++ .../resources/application-no-security.yml | 13 + .../src/main/resources/application-prod.yml | 63 ++++ .../src/main/resources/application-test.yml | 63 ++++ .../src/main/resources/application.yml | 58 ++++ refarch-gateway/src/main/resources/banner.txt | 17 ++ .../src/main/resources/logback-spring.xml | 124 ++++++++ .../test/java/@muenchen/TestConstants.java | 15 + .../controller/ActuatorInfoEndpointTest.java | 39 +++ .../CsrfTokenAppendingHelperFilterTest.java | 38 +++ .../GlobalAuthenticationErrorFilterTest.java | 67 +++++ .../GlobalBackend5xxTo400MapperTest.java | 94 ++++++ .../filter/GlobalBackendErrorFilterTest.java | 73 +++++ ...alRequestParameterPollutionFilterTest.java | 47 +++ .../@muenchen/route/BackendRouteTest.java | 76 +++++ 39 files changed, 2241 insertions(+), 8 deletions(-) create mode 100644 .gitignore delete mode 100644 Dockerfile create mode 100644 pom.xml create mode 100644 refarch-gateway/.gitignore create mode 100644 refarch-gateway/checkstyle.xml create mode 100644 refarch-gateway/pom.xml create mode 100644 refarch-gateway/runLocal.bat create mode 100644 refarch-gateway/runLocal.sh create mode 100644 refarch-gateway/runLocalNoSecurity.bat create mode 100644 refarch-gateway/runLocalNoSecurity.sh create mode 100644 refarch-gateway/src/main/java/@muenchen/ApiGatewayApplication.java create mode 100644 refarch-gateway/src/main/java/@muenchen/configuration/GuiConfiguration.java create mode 100644 refarch-gateway/src/main/java/@muenchen/configuration/NoSecurityConfiguration.java create mode 100644 refarch-gateway/src/main/java/@muenchen/configuration/SecurityConfiguration.java create mode 100644 refarch-gateway/src/main/java/@muenchen/configuration/VueCacheConfiguration.java create mode 100644 refarch-gateway/src/main/java/@muenchen/configuration/WebSessionConfiguration.java create mode 100644 refarch-gateway/src/main/java/@muenchen/exception/ParameterPollutionException.java create mode 100644 refarch-gateway/src/main/java/@muenchen/filter/CsrfTokenAppendingHelperFilter.java create mode 100644 refarch-gateway/src/main/java/@muenchen/filter/DistributedTracingFilter.java create mode 100644 refarch-gateway/src/main/java/@muenchen/filter/GlobalAuthenticationErrorFilter.java create mode 100644 refarch-gateway/src/main/java/@muenchen/filter/GlobalBackend5xxTo400Mapper.java create mode 100644 refarch-gateway/src/main/java/@muenchen/filter/GlobalRequestParameterPollutionFilter.java create mode 100644 refarch-gateway/src/main/resources/application-dev.yml create mode 100644 refarch-gateway/src/main/resources/application-kon.yml create mode 100644 refarch-gateway/src/main/resources/application-local.yml create mode 100644 refarch-gateway/src/main/resources/application-no-security.yml create mode 100644 refarch-gateway/src/main/resources/application-prod.yml create mode 100644 refarch-gateway/src/main/resources/application-test.yml create mode 100644 refarch-gateway/src/main/resources/application.yml create mode 100644 refarch-gateway/src/main/resources/banner.txt create mode 100644 refarch-gateway/src/main/resources/logback-spring.xml create mode 100644 refarch-gateway/src/test/java/@muenchen/TestConstants.java create mode 100644 refarch-gateway/src/test/java/@muenchen/controller/ActuatorInfoEndpointTest.java create mode 100644 refarch-gateway/src/test/java/@muenchen/filter/CsrfTokenAppendingHelperFilterTest.java create mode 100644 refarch-gateway/src/test/java/@muenchen/filter/GlobalAuthenticationErrorFilterTest.java create mode 100644 refarch-gateway/src/test/java/@muenchen/filter/GlobalBackend5xxTo400MapperTest.java create mode 100644 refarch-gateway/src/test/java/@muenchen/filter/GlobalBackendErrorFilterTest.java create mode 100644 refarch-gateway/src/test/java/@muenchen/filter/GlobalRequestParameterPollutionFilterTest.java create mode 100644 refarch-gateway/src/test/java/@muenchen/route/BackendRouteTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..49a46a55 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Covers Maven specific +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +!/.mvn/wrapper/maven-wrapper.jar + +# Covers Eclipse specific: +.settings/ +.classpath +.project + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +.idea +*.iml + +# Covers Netbeans: +**/nbproject/private/ +**/nbproject/Makefile-*.mk +**/nbproject/Package-*.bash +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +# Sonstiges +$(pwd) + diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index ae71e590..00000000 --- a/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -# Dockerfiles may only contain a FROM and the application data. -# For Java applications use /ubi9/openjdk-11-runtime or /ubi9/openjdk-17-runtime as Base Image, for documentation -# please see https://access.redhat.com/documentation/en-us/red_hat_jboss_middleware_for_openshift/3/html/red_hat_java_s2i_for_openshift/ -# All other variations must be approved by KM8 - -FROM registry.access.redhat.com/ubi9/openjdk-17-runtime:latest - -COPY target/*.jar /deployments/application.jar diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..c84c6d13 --- /dev/null +++ b/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + + + de.muenchen + muenchen-pom + 2.1.0 + + + + de.muenchen.oss + refarch + 0.0.1-SNAPSHOT + pom + refarch + + + refarch-gateway + + + + + 3.9.0.2155 + + + + https://github.com/it-at-m/refarch.git + scm:git:https://github.com/it-at-m/refarch.git + scm:git:https://github.com/it-at-m/refarch.git + + + + MIT + + + + + + + maven-scm-plugin + 1.10.0 + + RT-REL-${project.version} + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + ${sonar.scanner.version} + + + + + + diff --git a/refarch-gateway/.gitignore b/refarch-gateway/.gitignore new file mode 100644 index 00000000..b547ab07 --- /dev/null +++ b/refarch-gateway/.gitignore @@ -0,0 +1,32 @@ +# Covers Maven specific +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +!/.mvn/wrapper/maven-wrapper.jar + +# Covers Eclipse specific: +.settings/ +.classpath +.project + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +.idea +*.iml + +# Covers Netbeans: +**/nbproject/private/ +**/nbproject/Makefile-*.mk +**/nbproject/Package-*.bash +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + + diff --git a/refarch-gateway/checkstyle.xml b/refarch-gateway/checkstyle.xml new file mode 100644 index 00000000..37f7f0e7 --- /dev/null +++ b/refarch-gateway/checkstyle.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml new file mode 100644 index 00000000..523c198f --- /dev/null +++ b/refarch-gateway/pom.xml @@ -0,0 +1,277 @@ + + + 4.0.0 + + + + de.muenchen + muenchen-pom + 2.1.0 + + + + de.muenchen.oss.refarch.apigateway + gateway-apigateway + 0.0.1-SNAPSHOT + jar + gateway_apigateway + + + + UTF-8 + 17 + 17 + 17 + 3.0.7 + 2022.0.3 + 7.0.1 + + 4.2.8 + 3.12.0 + -Dorg.conscrypt.native.workdir=$(pwd) + 0.8.7 + + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring.cloud.version} + pom + import + + + + + + + + + + org.springframework.cloud + spring-cloud-starter + + + org.springframework.cloud + spring-cloud-starter-gateway + + + + + org.springframework.boot + spring-boot-starter-hateoas + + + + org.springframework.boot + spring-boot-starter-web + + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + org.springframework.boot + spring-boot-starter-oauth2-client + + + + + org.springframework.session + spring-session-hazelcast + + + com.hazelcast + hazelcast-all + ${hazelcast.version} + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + org.springframework.cloud + spring-cloud-starter-contract-stub-runner + test + + + + + org.projectlombok + lombok + provided + + + + + org.apache.commons + commons-lang3 + ${apache.commons.lang.version} + + + + + net.logstash.logback + logstash-logback-encoder + ${logstash.encoder.version} + + + io.micrometer + micrometer-tracing + + + io.micrometer + micrometer-tracing-bridge-brave + + + io.micrometer + micrometer-registry-prometheus + + + + + de.muenchen.oss.refarch.frontend + gateway-frontend + ${project.version} + runtime + + + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + ${jvm.options} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + + + com.diffplug.spotless + spotless-maven-plugin + 2.28.0 + + + de.muenchen.oss + itm-java-codeformat + 1.0.7 + + + + + + src/main/java/**/*.java + src/test/java/**/*.java + + + itm-java-codeformat/java_codestyle_formatter.xml + + + + + + + + + check + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.2.1 + + checkstyle.xml + + + + + check + + + + + + com.puppycrawl.tools + checkstyle + 9.3 + + + + + + + + diff --git a/refarch-gateway/runLocal.bat b/refarch-gateway/runLocal.bat new file mode 100644 index 00000000..39976102 --- /dev/null +++ b/refarch-gateway/runLocal.bat @@ -0,0 +1 @@ +mvn clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=local" diff --git a/refarch-gateway/runLocal.sh b/refarch-gateway/runLocal.sh new file mode 100644 index 00000000..4ecb1945 --- /dev/null +++ b/refarch-gateway/runLocal.sh @@ -0,0 +1,2 @@ +#!/bin/bash +mvn clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=local" diff --git a/refarch-gateway/runLocalNoSecurity.bat b/refarch-gateway/runLocalNoSecurity.bat new file mode 100644 index 00000000..e1571711 --- /dev/null +++ b/refarch-gateway/runLocalNoSecurity.bat @@ -0,0 +1 @@ +mvn clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=local,no-security" diff --git a/refarch-gateway/runLocalNoSecurity.sh b/refarch-gateway/runLocalNoSecurity.sh new file mode 100644 index 00000000..69535f25 --- /dev/null +++ b/refarch-gateway/runLocalNoSecurity.sh @@ -0,0 +1,2 @@ +#!/bin/bash +mvn clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=local,no-security" diff --git a/refarch-gateway/src/main/java/@muenchen/ApiGatewayApplication.java b/refarch-gateway/src/main/java/@muenchen/ApiGatewayApplication.java new file mode 100644 index 00000000..5ce401ef --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/ApiGatewayApplication.java @@ -0,0 +1,41 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * To do some base configuration for the non blocking client-server framework + * named Netty via properties use the properties listed in the link down below: + * + * @see https://projectreactor.io/docs/netty/release/api/constant-values.html + * + * As listed below, this above mentioned properties should be set before the application + * startup: + * + *
    + *
  • As command line argument: e.g. -Dreactor.netty.pool.maxConnections=1000. + *
  • As environmental property in Openshift: e.g. with key REACTOR_NETTY_POOL_MAXCONNECTIONS + * and value 1000. + *
  • As programatically set property before call {@link SpringApplication#run} in + * {@link ApiGatewayApplication#main}: e.g. + * System.setProperty("reactor.netty.pool.maxConnections", "1000");. + *
+ * + * To get more information about Spring Cloud Gateway visit the following link: + * + * @see https://cloud.spring.io/spring-cloud-gateway/reference/html/ + */ +@SpringBootApplication(scanBasePackages = { "@muenchen" }) +public class ApiGatewayApplication { + + public static void main(String[] args) { + SpringApplication.run(ApiGatewayApplication.class, args); + } + +} diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/GuiConfiguration.java b/refarch-gateway/src/main/java/@muenchen/configuration/GuiConfiguration.java new file mode 100644 index 00000000..948d9db0 --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/configuration/GuiConfiguration.java @@ -0,0 +1,44 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.configuration; + +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.ServerResponse; + +/** + * This class supplies the endpoint which provides the gui. + * + * The default path to the gui entry point is "classpath:/static/index.html". + */ +@Configuration +@Slf4j +public class GuiConfiguration { + + /** + * A router which returns the index.html as a resource. + * + * @param indexHtml The path to the index.html which serves as the starting point. + * @return the index.html as a resource. + */ + @Bean + public RouterFunction indexRouter( + @Value("classpath:/static/index.html") final Resource indexHtml) { + log.debug("Location gui entry point: {}", indexHtml); + return route(GET("/"), + request -> ok().contentType(MediaType.TEXT_HTML) + .bodyValue(indexHtml)); + } + +} diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/NoSecurityConfiguration.java b/refarch-gateway/src/main/java/@muenchen/configuration/NoSecurityConfiguration.java new file mode 100644 index 00000000..d820630f --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/configuration/NoSecurityConfiguration.java @@ -0,0 +1,31 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@Configuration +@Profile("no-security") +public class NoSecurityConfiguration { + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + // @formatter:off + return http + .authorizeExchange() + .anyExchange().permitAll() + .and() + .cors() + .and() + .csrf().disable() + .build(); + // @formatter:on + } + +} diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/SecurityConfiguration.java b/refarch-gateway/src/main/java/@muenchen/configuration/SecurityConfiguration.java new file mode 100644 index 00000000..b01af996 --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/configuration/SecurityConfiguration.java @@ -0,0 +1,104 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.configuration; + +import @muenchen.filter.CsrfTokenAppendingHelperFilter; +import java.net.URI; +import java.time.Duration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpMethod; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.server.SecurityWebFilterChain; +import org.springframework.security.web.server.WebFilterExchange; +import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler; +import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler; +import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler; +import org.springframework.security.web.server.csrf.CookieServerCsrfTokenRepository; +import org.springframework.security.web.server.csrf.ServerCsrfTokenRequestAttributeHandler; +import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers; +import reactor.core.publisher.Mono; + +@Configuration +@Profile("!no-security") +public class SecurityConfiguration { + + private static final String LOGOUT_URL = "/logout"; + + private static final String LOGOUT_SUCCESS_URL = "/loggedout.html"; + + /** + * Same lifetime as SSO Session (e.g. 10 hours). + */ + @Value("${spring.session.timeout:36000}") + private long springSessionTimeoutSeconds; + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + final CookieServerCsrfTokenRepository tokenRepository = CookieServerCsrfTokenRepository.withHttpOnlyFalse(); + // requestHandler needed for handling the raw CSRF tokens + final ServerCsrfTokenRequestAttributeHandler requestHandler = new ServerCsrfTokenRequestAttributeHandler(); + + // @formatter:off + http + .logout() + .logoutSuccessHandler(createLogoutSuccessHandler(LOGOUT_SUCCESS_URL)) + .logoutUrl(LOGOUT_URL) + .requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, LOGOUT_URL)) + .and() + .authorizeExchange() + // permitAll + .pathMatchers(HttpMethod.OPTIONS, "/api/**").permitAll() + .pathMatchers(LOGOUT_SUCCESS_URL).permitAll() + .pathMatchers("/api/*/info", + "/actuator/health", + "/actuator/info", + "/actuator/metrics").permitAll() + // only authenticated + .anyExchange().authenticated() + .and() + /* + * The necessary subscription for csrf token attachment to {@link ServerHttpResponse} + * is done in class {@link CsrfTokenAppendingHelperFilter}. + */ + .csrf((csrf) -> csrf + .csrfTokenRepository(tokenRepository) + .csrfTokenRequestHandler(requestHandler)) + .cors() + .and() + .oauth2Login() + /* + * Set security session timeout. + */ + .authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler() { + @Override + public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { + webFilterExchange.getExchange().getSession().subscribe( + webSession -> webSession.setMaxIdleTime(Duration.ofSeconds(springSessionTimeoutSeconds))); + return super.onAuthenticationSuccess(webFilterExchange, authentication); + } + }); + return http.build(); + // @formatter:on + } + + /** + * This method creates the {@link ServerLogoutSuccessHandler} for handling a successful logout. + * The usage is necessary in {@link SecurityWebFilterChain}. + * + * @param uri to forward after an successful logout. + * @return The handler for forwarding after an succesful logout. + */ + public static ServerLogoutSuccessHandler createLogoutSuccessHandler(final String uri) { + final RedirectServerLogoutSuccessHandler successHandler = new RedirectServerLogoutSuccessHandler(); + successHandler.setLogoutSuccessUrl(URI.create(uri)); + return successHandler; + } + +} diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/VueCacheConfiguration.java b/refarch-gateway/src/main/java/@muenchen/configuration/VueCacheConfiguration.java new file mode 100644 index 00000000..c1860be7 --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/configuration/VueCacheConfiguration.java @@ -0,0 +1,34 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.configuration; + +import java.time.Duration; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.CacheControl; +import org.springframework.web.reactive.config.ResourceHandlerRegistry; +import org.springframework.web.reactive.config.WebFluxConfigurer; + +/** + * VueCacheConfigurer setzt Cache Header für die von Vue gebauten Resourcen. Sie enthalten im Namen + * ein Hash, deswegen sollte das Caching hier keine Probleme machen. + */ +@Configuration +public class VueCacheConfiguration implements WebFluxConfigurer { + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/js/**") + .addResourceLocations("classpath:/static/js/") + .setCacheControl(CacheControl.maxAge(Duration.ofDays(30))); + registry.addResourceHandler("/css/**") + .addResourceLocations("classpath:/static/css/") + .setCacheControl(CacheControl.maxAge(Duration.ofDays(30))); + registry.addResourceHandler("/fonts/**") + .addResourceLocations("classpath:/static/fonts/") + .setCacheControl(CacheControl.maxAge(Duration.ofDays(30))); + registry.addResourceHandler("/img/**") + .addResourceLocations("classpath:/static/img/") + .setCacheControl(CacheControl.maxAge(Duration.ofDays(30))); + } +} diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/WebSessionConfiguration.java b/refarch-gateway/src/main/java/@muenchen/configuration/WebSessionConfiguration.java new file mode 100644 index 00000000..db97f6ad --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/configuration/WebSessionConfiguration.java @@ -0,0 +1,117 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.configuration; + +import com.hazelcast.config.Config; +import com.hazelcast.config.EvictionPolicy; +import com.hazelcast.config.MapConfig; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.map.IMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; +import org.springframework.security.oauth2.client.web.server.WebSessionServerOAuth2AuthorizedClientRepository; +import org.springframework.session.MapSession; +import org.springframework.session.ReactiveMapSessionRepository; +import org.springframework.session.ReactiveSessionRepository; +import org.springframework.session.Session; +import org.springframework.session.config.annotation.web.server.EnableSpringWebSession; +import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository; + +/** + * This class configures Hazelcast as the ReactiveSessionRepository. + * + */ +@Configuration +@EnableSpringWebSession +public class WebSessionConfiguration { + + @Value("${hazelcast.instance:hazl_instance}") + public String hazelcastInstanceName; + + @Value("${hazelcast.group-name:session_replication_group}") + public String groupConfigName; + + @Value("${app.spring-session-hazelcast.namespace:my_namespace}") + public String openshiftNamespace; + + @Value("${hazelcast.openshift-service-name:apigateway}") + public String openshiftServiceName; + + @Bean + public ServerOAuth2AuthorizedClientRepository authorizedClientRepository() { + return new WebSessionServerOAuth2AuthorizedClientRepository(); + } + + @Bean + public ReactiveSessionRepository reactiveSessionRepository(@Qualifier("hazelcastInstance") @Autowired HazelcastInstance hazelcastInstance) { + final IMap map = hazelcastInstance.getMap(HazelcastIndexedSessionRepository.DEFAULT_SESSION_MAP_NAME); + return new ReactiveMapSessionRepository(map); + } + + @Bean + @Profile({ "local", "test" }) + public Config localConfig(@Value( + "${spring.session.timeout}" + ) int timeout) { + final var hazelcastConfig = new Config(); + hazelcastConfig.setInstanceName(hazelcastInstanceName); + hazelcastConfig.setClusterName(groupConfigName); + + addSessionTimeoutToHazelcastConfig(hazelcastConfig, timeout); + + final var networkConfig = hazelcastConfig.getNetworkConfig(); + + final var joinConfig = networkConfig.getJoin(); + joinConfig.getMulticastConfig().setEnabled(false); + joinConfig.getTcpIpConfig() + .setEnabled(true) + .addMember("127.0.0.1"); + + return hazelcastConfig; + } + + @Bean + @Profile({ "dev", "kon", "prod" }) + public Config config(@Value("${spring.session.timeout}") int timeout) { + final var hazelcastConfig = new Config(); + hazelcastConfig.setInstanceName(hazelcastInstanceName); + hazelcastConfig.setClusterName(groupConfigName); + + addSessionTimeoutToHazelcastConfig(hazelcastConfig, timeout); + + hazelcastConfig.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); + hazelcastConfig.getNetworkConfig().getJoin().getKubernetesConfig().setEnabled(true) + // explicitely configure namespace because default env lookup is not alway correct + .setProperty("namespace", openshiftNamespace) + //If we dont set a specific name, it would call -all- services within a namespace + .setProperty("service-name", openshiftServiceName); + + return hazelcastConfig; + } + + /** + * Adds the session timeout in seconds to the hazelcast configuration. + * + * Since we are creating the map it's important to evict sessions + * by setting a reasonable value for time to live. + * + * @param hazelcastConfig to add the timeout. + * @param sessionTimeout for security session. + */ + private void addSessionTimeoutToHazelcastConfig(final Config hazelcastConfig, final int sessionTimeout) { + final var sessionConfig = new MapConfig(); + sessionConfig.setName(HazelcastIndexedSessionRepository.DEFAULT_SESSION_MAP_NAME); + sessionConfig.setTimeToLiveSeconds(sessionTimeout); + sessionConfig.getEvictionConfig().setEvictionPolicy(EvictionPolicy.LRU); + + hazelcastConfig.addMapConfig(sessionConfig); + } + +} diff --git a/refarch-gateway/src/main/java/@muenchen/exception/ParameterPollutionException.java b/refarch-gateway/src/main/java/@muenchen/exception/ParameterPollutionException.java new file mode 100644 index 00000000..1b0c2950 --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/exception/ParameterPollutionException.java @@ -0,0 +1,27 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.exception; + +import @muenchen.filter.GlobalRequestParameterPollutionFilter; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +/** + * Used in {@link GlobalRequestParameterPollutionFilter} to signal a possible parameter pollution + * attack. + */ +@ResponseStatus( + code = HttpStatus.BAD_REQUEST, + reason = "parameter pollution" +) +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ParameterPollutionException extends RuntimeException { + // default Ctor +} diff --git a/refarch-gateway/src/main/java/@muenchen/filter/CsrfTokenAppendingHelperFilter.java b/refarch-gateway/src/main/java/@muenchen/filter/CsrfTokenAppendingHelperFilter.java new file mode 100644 index 00000000..39eeb86d --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/filter/CsrfTokenAppendingHelperFilter.java @@ -0,0 +1,37 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import @muenchen.configuration.SecurityConfiguration; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.security.web.server.csrf.CookieServerCsrfTokenRepository; +import org.springframework.security.web.server.csrf.CsrfToken; +import org.springframework.security.web.server.csrf.CsrfWebFilter; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +/** + * This class subscribes the {@link ServerWebExchange} for csrf token attachment + * within the classes {@link CookieServerCsrfTokenRepository} and {@link CsrfWebFilter}. + * The csrf configuration done only in {@link SecurityConfiguration#springSecurityFilterChain} is + * not sufficient for csrf token attachment to a {@link ServerHttpResponse}. + */ +@Component +@Slf4j +public class CsrfTokenAppendingHelperFilter implements WebFilter { + + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + log.debug("Trigger to append CSRF token to response"); + Mono csrfToken = exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty()); + return csrfToken.doOnSuccess(token -> { + // do nothing -> CSRF-Token is added as cookie in class CookieServerCsrfTokenRepository#saveToken + }).then(chain.filter(exchange)); + } + +} diff --git a/refarch-gateway/src/main/java/@muenchen/filter/DistributedTracingFilter.java b/refarch-gateway/src/main/java/@muenchen/filter/DistributedTracingFilter.java new file mode 100644 index 00000000..01414afc --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/filter/DistributedTracingFilter.java @@ -0,0 +1,59 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import io.micrometer.tracing.Tracer; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +/** + * This class adds the sleuth headers "X-B3-SpanId" and "X-B3-TraceId" + * to each route response. + */ +@Component +@Slf4j +public class DistributedTracingFilter implements WebFilter { + + public static final String TRACE_ID = "TraceId"; + public static final String SPAN_ID = "SpanId"; + + @Autowired + private Tracer tracer; + + /** + * This method adds the zipkin headers "X-B3-SpanId" and "X-B3-TraceId" + * to each response in {@link ServerWebExchange}. + * + * @param serverWebExchange the current server exchange without zipkin headers + * @param webFilterChain provides a way to delegate to the next filter + * @return {@code Mono} to indicate when request processing for adding zipkin headers is + * complete + */ + @Override + public Mono filter(ServerWebExchange serverWebExchange, + WebFilterChain webFilterChain) { + ServerHttpResponse response = serverWebExchange.getResponse(); + response.beforeCommit(() -> { + var span = tracer.currentSpan(); + if (span != null) { + HttpHeaders headers = response.getHeaders(); + headers.add(TRACE_ID, span.context().traceId()); + headers.add(SPAN_ID, span.context().spanId()); + } else { + log.debug("Traceinformation missing - Skip Trace Header insertion"); + } + return Mono.empty(); + }); + return webFilterChain.filter(serverWebExchange); + } + +} diff --git a/refarch-gateway/src/main/java/@muenchen/filter/GlobalAuthenticationErrorFilter.java b/refarch-gateway/src/main/java/@muenchen/filter/GlobalAuthenticationErrorFilter.java new file mode 100644 index 00000000..7eedd862 --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/filter/GlobalAuthenticationErrorFilter.java @@ -0,0 +1,93 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import com.hazelcast.org.apache.commons.codec.binary.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; +import org.reactivestreams.Publisher; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.http.server.reactive.ServerHttpResponseDecorator; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * This {@link GlobalFilter} replaces the body by a generic authentication error body, + * when a server responses with a {@link HttpStatus#UNAUTHORIZED}. + *

+ * The header {@link HttpHeaders#WWW_AUTHENTICATE} containing the access token is removed + * by the property 'RemoveResponseHeader' in the corresponding route within 'application.yml'. + */ +@Component +@Slf4j +public class GlobalAuthenticationErrorFilter implements GlobalFilter, Ordered { + + private static final String GENERIC_AUTHENTICATION_ERROR = "{ \"status\":401, \"error\":\"Authentication Error\" }"; + + public static final int ORDER_GLOBAL_FILTER = -3; + + @Override + public int getOrder() { + return ORDER_GLOBAL_FILTER; + } + + @Override + public Mono filter(final ServerWebExchange exchange, final GatewayFilterChain chain) { + log.debug("Check for authentication errors"); + final HttpStatus httpStatus = HttpStatus.UNAUTHORIZED; + final String newResponseBody = GENERIC_AUTHENTICATION_ERROR; + final String EMPTY_JSON_OBJECT = "{}"; + + final ServerHttpResponse response = exchange.getResponse(); + + final ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) { + + /** + * This overridden method adds the response body given in the parameter of + * the surrounding method when the http status given in the parameter of + * the surrounding method is met otherwise the already appended body will be used. + * + * @param body The body received by the upstream response. + * @return Either the body received by the upstream response or + * the body given by the parameter. + */ + @Override + public Mono writeWith(Publisher body) { + final HttpStatusCode responseHttpStatus = getDelegate().getStatusCode(); + if (body instanceof Flux && responseHttpStatus.equals(httpStatus)) { + final DataBufferFactory dataBufferFactory = response.bufferFactory(); + final DataBuffer newDataBuffer = dataBufferFactory.wrap( + StringUtils.getBytesUtf8(ObjectUtils.defaultIfNull(newResponseBody, EMPTY_JSON_OBJECT))); + + log.debug("Response from upstream {} get new response body: {}", httpStatus, newResponseBody); + getDelegate().getHeaders().setContentLength(newDataBuffer.readableByteCount()); + getDelegate().getHeaders().setContentType(MediaType.APPLICATION_JSON); + Flux flux = (Flux) body; + + return super.writeWith(flux.buffer().map( + // replace old body represented by dataBuffer by the new one + dataBuffer -> newDataBuffer)); + } + return super.writeWith(body); + } + + }; + + final ServerWebExchange swe = exchange.mutate().response(decoratedResponse).build(); + return chain.filter(swe); + }; + +} diff --git a/refarch-gateway/src/main/java/@muenchen/filter/GlobalBackend5xxTo400Mapper.java b/refarch-gateway/src/main/java/@muenchen/filter/GlobalBackend5xxTo400Mapper.java new file mode 100644 index 00000000..bd6c3ada --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/filter/GlobalBackend5xxTo400Mapper.java @@ -0,0 +1,109 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import com.hazelcast.org.apache.commons.codec.binary.StringUtils; +import java.nio.charset.StandardCharsets; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; +import org.reactivestreams.Publisher; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.core.io.buffer.DefaultDataBuffer; +import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.http.server.reactive.ServerHttpResponseDecorator; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * This {@link GlobalFilter} replaces the body by a generic error body, when a server responses + * with a {@link HttpStatus#INTERNAL_SERVER_ERROR}. + */ +@Component +@Slf4j +public class GlobalBackend5xxTo400Mapper implements GlobalFilter, Ordered { + + public static final int ORDER_GLOBAL_FILTER = -3; + + /** + * Variable entscheidet, ob alle 5xx Fehler auf 400 gemappt werden sollen. + **/ + @Value("${config.map5xxto400: true}") + private boolean MAP_5xx_TO_400; + + static final String GENERIC_ERROR_400 = "{ \"status\":400, \"error\":\"Bad Request\" }"; + static final String GENERIC_ERROR_500 = "{ \"status\":500, \"error\":\"Internal Server Error\" }"; + + @Override + public int getOrder() { + return ORDER_GLOBAL_FILTER; + } + + @Override + public Mono filter(final ServerWebExchange exchange, final GatewayFilterChain chain) { + final String EMPTY_JSON_OBJECT = "{}"; + final ServerHttpResponse response = exchange.getResponse(); + final ServerHttpRequest request = exchange.getRequest(); + final DataBufferFactory dataBufferFactory = response.bufferFactory(); + + final ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) { + + @Override + public Mono writeWith(Publisher body) { + final HttpStatusCode responseHttpStatus = getDelegate().getStatusCode(); + + final Flux flux = (Flux) body; + + if (body instanceof Flux && responseHttpStatus.is5xxServerError()) { + + return super.writeWith(flux.buffer().map( + // replace old body represented by dataBuffer by the new one + + dataBuffer -> { + // Log-Ausgabe + DefaultDataBuffer joinedBuffers = new DefaultDataBufferFactory().join(dataBuffer); + byte[] content = new byte[joinedBuffers.readableByteCount()]; + joinedBuffers.read(content); + String responseBody = new String(content, StandardCharsets.UTF_8); + log.error("Error: 5xx vom Backend: requestId: {}, method: {}, url: {}, \nresponse body :{}, statusCode: {}", request.getId(), + request.getMethod(), request.getURI(), responseBody, responseHttpStatus); + + // Response manipulieren + final DataBuffer newDataBuffer; + if (MAP_5xx_TO_400) { + getDelegate().setStatusCode(HttpStatus.BAD_REQUEST); + newDataBuffer = dataBufferFactory.wrap( + StringUtils.getBytesUtf8(ObjectUtils.defaultIfNull(GENERIC_ERROR_400, EMPTY_JSON_OBJECT))); + } else { + getDelegate().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + newDataBuffer = dataBufferFactory.wrap( + StringUtils.getBytesUtf8(ObjectUtils.defaultIfNull(GENERIC_ERROR_500, EMPTY_JSON_OBJECT))); + } + + getDelegate().getHeaders().setContentLength(newDataBuffer.readableByteCount()); + getDelegate().getHeaders().setContentType(MediaType.APPLICATION_JSON); + + return newDataBuffer; + })); + } + return super.writeWith(body); + } + }; + + // replace response with decorator + return chain.filter(exchange.mutate().response(decoratedResponse).build()); + } +} diff --git a/refarch-gateway/src/main/java/@muenchen/filter/GlobalRequestParameterPollutionFilter.java b/refarch-gateway/src/main/java/@muenchen/filter/GlobalRequestParameterPollutionFilter.java new file mode 100644 index 00000000..f1a0eb0f --- /dev/null +++ b/refarch-gateway/src/main/java/@muenchen/filter/GlobalRequestParameterPollutionFilter.java @@ -0,0 +1,65 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import @muenchen.exception.ParameterPollutionException; +import java.util.List; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + * This {@link GlobalFilter} is used to detect and to fend off a parameter pollution attack. + * + * Within a {@link HttpRequest} each request parameter should only exist once. + * This check is necessary to avoid e.g. SQL injection split over multiple request parameters with + * the same name. + */ +@Component +@Slf4j +public class GlobalRequestParameterPollutionFilter implements GlobalFilter, Ordered { + + public static final int ORDER_GLOBAL_FILTER = -3; + + @Override + public int getOrder() { + return ORDER_GLOBAL_FILTER; + } + + /** + * See {@link GlobalFilter#filter(ServerWebExchange, GatewayFilterChain)} + * + * @throws ParameterPollutionException is throw when a request parameter exists multiple times. + * The exception represents a http response with status {@link HttpStatus#BAD_REQUEST}. + */ + @Override + public Mono filter(final ServerWebExchange exchange, final GatewayFilterChain chain) throws ParameterPollutionException { + log.debug("Check for parameter pollution attack."); + ServerHttpRequest request = exchange.getRequest(); + if (!CollectionUtils.isEmpty(request.getQueryParams())) { + MultiValueMap parameterMap = request.getQueryParams(); + for (Map.Entry> entry : parameterMap.entrySet()) { + String key = entry.getKey(); + List value = entry.getValue(); + if (!CollectionUtils.isEmpty(value) && value.size() > 1) { + log.warn("Possible parameter pollution attack detected: Parameter \"{}\" detected more than once in the request!", key); + throw new ParameterPollutionException(); + } + } + } + return chain.filter(exchange); + } + +} diff --git a/refarch-gateway/src/main/resources/application-dev.yml b/refarch-gateway/src/main/resources/application-dev.yml new file mode 100644 index 00000000..4d8c52d1 --- /dev/null +++ b/refarch-gateway/src/main/resources/application-dev.yml @@ -0,0 +1,63 @@ +app: + backend-service: + frontend-service: + +spring: + + # Define the keycloak development realm here + realm: + + # spring cloud gateway config + cloud: + gateway: + actuator: + verbose: + enabled: false + globalcors: + corsConfigurations: + # The cors configuration to allow frontend developers cross origin request via this api gateway + '[/**]': + allowedOrigins: + - "http://localhost:8081" + - "http://127.0.0.1:8081" + allowedMethods: "*" + allowedHeaders: "*" + allowCredentials: true + maxAge: 3600 + routes: + - id: sso + uri: https://ssodev.muenchen.de/ + predicates: + - Path=/api/sso/userinfo + filters: + - RewritePath=/api/sso/userinfo, /auth/realms/${spring.realm}/protocol/openid-connect/userinfo + - id: backend + uri: http://${app.backend-service}:8080/ + predicates: + - Path=/api/refarch-gateway-backend-service/** + filters: + - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} + - RemoveResponseHeader=WWW-Authenticate + default-filters: + - RemoveResponseHeader=Expires + - RemoveRequestHeader=cookie + - RemoveRequestHeader=x-xsrf-token + - TokenRelay= + + # security config + security: + oauth2: + client: + provider: + keycloak: + issuer-uri: https://ssodev.muenchen.de/auth/realms/${spring.realm} + registration: + keycloak: + client-id: refarch-gateway + client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 + + mvc: + log-request-details: on + +hazelcast: + openshift-service-name: ${app.frontend-service} diff --git a/refarch-gateway/src/main/resources/application-kon.yml b/refarch-gateway/src/main/resources/application-kon.yml new file mode 100644 index 00000000..68ee0e05 --- /dev/null +++ b/refarch-gateway/src/main/resources/application-kon.yml @@ -0,0 +1,63 @@ +app: + backend-service: + frontend-service: + +spring: + + # Define the keycloak consolidation realm here; default is "intrap" + realm: intrap + + # spring cloud gateway config + cloud: + gateway: + actuator: + verbose: + enabled: false + globalcors: + corsConfigurations: + # The cors configuration to allow frontend developers cross origin request via this api gateway + '[/**]': + allowedOrigins: + - "http://localhost:8081" + - "http://127.0.0.1:8081" + allowedMethods: "*" + allowedHeaders: "*" + allowCredentials: true + maxAge: 3600 + routes: + - id: sso + uri: https://ssotest.muenchen.de/ + predicates: + - Path=/api/sso/userinfo + filters: + - RewritePath=/api/sso/userinfo, /auth/realms/${spring.realm}/protocol/openid-connect/userinfo + - id: backend + uri: http://${app.backend-service}:8080/ + predicates: + - Path=/api/refarch-gateway-backend-service/** + filters: + - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} + - RemoveResponseHeader=WWW-Authenticate + default-filters: + - RemoveResponseHeader=Expires + - RemoveRequestHeader=cookie + - RemoveRequestHeader=x-xsrf-token + - TokenRelay= + + # security config + security: + oauth2: + client: + provider: + keycloak: + issuer-uri: https://ssotest.muenchen.de/auth/realms/${spring.realm} + registration: + keycloak: + client-id: refarch-gateway + client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 + + mvc: + log-request-details: on + +hazelcast: + openshift-service-name: ${app.frontend-service} diff --git a/refarch-gateway/src/main/resources/application-local.yml b/refarch-gateway/src/main/resources/application-local.yml new file mode 100644 index 00000000..bc050507 --- /dev/null +++ b/refarch-gateway/src/main/resources/application-local.yml @@ -0,0 +1,58 @@ +server: + port: 8082 +spring: + + # Define the local keycloak realm here + realm: + + # spring cloud gateway config + cloud: + gateway: + actuator: + verbose: + enabled: false + globalcors: + corsConfigurations: + # The cors configuration to allow frontend developers cross origin request via this api gateway + '[/**]': + allowedOrigins: + - "http://localhost:8081" + - "http://127.0.0.1:8081" + allowedMethods: "*" + allowedHeaders: "*" + allowCredentials: true + maxAge: 3600 + routes: + - id: sso + uri: https://ssodev.muenchen.de/ + predicates: + - Path=/api/sso/userinfo + filters: + - RewritePath=/api/sso/userinfo, /auth/realms/${spring.realm}/protocol/openid-connect/userinfo + - id: backend + uri: http://localhost:39146/ + predicates: + - Path=/api/refarch-gateway-backend-service/** + filters: + - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} + - RemoveResponseHeader=WWW-Authenticate + default-filters: + - RemoveResponseHeader=Expires + - RemoveRequestHeader=cookie + - RemoveRequestHeader=x-xsrf-token + - TokenRelay= + + # security config + security: + oauth2: + client: + provider: + keycloak: + issuer-uri: https://ssodev.muenchen.de/auth/realms/${spring.realm} + registration: + keycloak: + client-id: refarch-gateway + client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 + + mvc: + log-request-details: on diff --git a/refarch-gateway/src/main/resources/application-no-security.yml b/refarch-gateway/src/main/resources/application-no-security.yml new file mode 100644 index 00000000..62e30811 --- /dev/null +++ b/refarch-gateway/src/main/resources/application-no-security.yml @@ -0,0 +1,13 @@ +spring: + autoconfigure: + exclude: + - org.springframework.cloud.security.oauth2.gateway.TokenRelayAutoConfiguration + - org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration + cloud: + gateway: + # The whole list need to be overridden to remove CustomTokenRelayGatewayFilter + default-filters: + - RemoveResponseHeader=Expires + - RemoveRequestHeader=cookie + - RemoveRequestHeader=x-xsrf-token + diff --git a/refarch-gateway/src/main/resources/application-prod.yml b/refarch-gateway/src/main/resources/application-prod.yml new file mode 100644 index 00000000..d33dc8ef --- /dev/null +++ b/refarch-gateway/src/main/resources/application-prod.yml @@ -0,0 +1,63 @@ +app: + backend-service: + frontend-service: + +spring: + + # Define the keycloak productive realm here + realm: muenchen.de + + # spring cloud gateway config + cloud: + gateway: + actuator: + verbose: + enabled: false + globalcors: + corsConfigurations: + # The cors configuration to allow frontend developers cross origin request via this api gateway + '[/**]': + allowedOrigins: + - "http://localhost:8081" + - "http://127.0.0.1:8081" + allowedMethods: "*" + allowedHeaders: "*" + allowCredentials: true + maxAge: 3600 + routes: + - id: sso + uri: https://sso.muenchen.de/ + predicates: + - Path=/api/sso/userinfo + filters: + - RewritePath=/api/sso/userinfo, /auth/realms/${spring.realm}/protocol/openid-connect/userinfo + - id: backend + uri: http://${app.backend-service}:8080/ + predicates: + - Path=/api/refarch-gateway-backend-service/** + filters: + - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} + - RemoveResponseHeader=WWW-Authenticate + default-filters: + - RemoveResponseHeader=Expires + - RemoveRequestHeader=cookie + - RemoveRequestHeader=x-xsrf-token + - TokenRelay= + + # security config + security: + oauth2: + client: + provider: + keycloak: + issuer-uri: https://sso.muenchen.de/auth/realms/${spring.realm} + registration: + keycloak: + client-id: refarch-gateway + client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 + + mvc: + log-request-details: false + +hazelcast: + openshift-service-name: ${app.frontend-service} diff --git a/refarch-gateway/src/main/resources/application-test.yml b/refarch-gateway/src/main/resources/application-test.yml new file mode 100644 index 00000000..ca9f8e30 --- /dev/null +++ b/refarch-gateway/src/main/resources/application-test.yml @@ -0,0 +1,63 @@ +wiremock: + server: + port: 0 + https-port: -1 + +spring: + + # muenchen.de realm is used by default so that the SpringContext can be initalized upon running the tests. Change to your own dev realm if available + realm: muenchen.de + + # spring cloud gateway config + cloud: + gateway: + actuator: + verbose: + enabled: false + globalcors: + corsConfigurations: + # The cors configuration to allow frontend developers cross origin request via this api gateway + '[/**]': + allowedOrigins: + - "http://localhost:8081" + - "http://127.0.0.1:8081" + allowedMethods: "*" + allowedHeaders: "*" + allowCredentials: true + maxAge: 3600 + routes: + - id: sso + uri: https://ssotest.muenchen.de/ + predicates: + - Path=/api/sso/userinfo + filters: + - RewritePath=/api/sso/userinfo, /auth/realms/${spring.realm}/protocol/openid-connect/userinfo + - id: backend + uri: http://localhost:${wiremock.server.port}/ + predicates: + - Path=/api/refarch-gateway-backend-service/** + filters: + - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} + - RemoveResponseHeader=WWW-Authenticate + default-filters: + - RemoveResponseHeader=Expires + - RemoveRequestHeader=cookie + - RemoveRequestHeader=x-xsrf-token + - TokenRelay= + + # security config + security: + oauth2: + client: + provider: + keycloak: + issuer-uri: https://sso.muenchen.de/auth/realms/${spring.realm} + registration: + keycloak: + client-id: refarch-gateway + client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 + + mvc: + log-request-details: on + +info.appswitcher.url: https://test-url-appswitcher.muenchen.de diff --git a/refarch-gateway/src/main/resources/application.yml b/refarch-gateway/src/main/resources/application.yml new file mode 100644 index 00000000..eb46b92f --- /dev/null +++ b/refarch-gateway/src/main/resources/application.yml @@ -0,0 +1,58 @@ +spring: + application.name: @project.artifactId@ + banner.location: banner.txt + main: + web-application-type: reactive + jackson: + serialization: + indent-output: on + session: + timeout: 36000 # in seconds; Goal: same lifetime as SSO Session (e.g. 10 hours) + zipkin: + enabled: false + sleuth: + reactor: + instrumentation-type: decorate_on_each # https://github.com/spring-cloud/spring-cloud-gateway/pull/2106 + +server: + port: 8080 + error: + include-exception: false + include-stacktrace: never + include-message: always + whitelabel: + enabled: false + +management: + endpoints: + enabled-by-default: false + web: + cors: + allowedOrigins: + - "http://localhost:8081" + - "http://127.0.0.1:8081" + allowedMethods: "*" + allowedHeaders: "*" + allowCredentials: on + maxAge: 3600 + exposure: + include: health, info, prometheus + path-mapping: + prometheus: metrics + endpoint: + health: + enabled: on + probes: + enabled: true + info: + enabled: on + prometheus: + enabled: on + info: + env: + enabled: true +info.application.name: ${spring.application.name} +info.application.version: @project.version@ +info.appswitcher.url: https://appswitcher.muenchen.de + +config.map5xxto400: false diff --git a/refarch-gateway/src/main/resources/banner.txt b/refarch-gateway/src/main/resources/banner.txt new file mode 100644 index 00000000..ab68c31a --- /dev/null +++ b/refarch-gateway/src/main/resources/banner.txt @@ -0,0 +1,17 @@ +--------------------------------------------------------------------------------------------------------------------------------------------------- + ____ _ _ _ _ + | _ \ | | | | /\ | | | | + | |_) | __ _ _ __ _ __ __ _ | | __ _ _ __| | __ _ ______ / \ _ __ ___ | |__ ___ | |_ _ _ _ __ ___ + | _ < / _` | | '__| | '__| / _` | | |/ / | | | | / _` | / _` | |______| / /\ \ | '__| / __| | '_ \ / _ \ | __| | | | | | '_ \ / _ \ + | |_) | | (_| | | | | | | (_| | | < | |_| | | (_| | | (_| | / ____ \ | | | (__ | | | | | __/ | |_ | |_| | | |_) | | __/ + |____/ \__,_| |_| |_| \__,_| |_|\_\ \__,_| \__,_| \__,_| /_/ \_\ |_| \___| |_| |_| \___| \__| \__, | | .__/ \___| + __/ | | | + |___/ |_| by CCSE + + Du benutzt den RefArch-Archetype und willst it@M helfen, ihn weiter zu verbessern? + + Gib uns dein Feedback und Verbesserungsvorschläge unter https://git.muenchen.de/ccse/refarch-archetype/refarch-overview/-/issues/new?issuable_template=Feedback + + Application Name : ${spring.application.name} + Spring Boot Version : ${spring-boot.formatted-version} +--------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/refarch-gateway/src/main/resources/logback-spring.xml b/refarch-gateway/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..43d6be87 --- /dev/null +++ b/refarch-gateway/src/main/resources/logback-spring.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + %date{yyyy.MM.dd HH:mm:ss.SSS} | ${springAppName} | TraceId: %X{traceId:-} | SpanId: %X{spanId:-}] | %level | [%thread] | %logger{0} | [%file : %line] - %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + "timestamp" : "%date{yyyy-MM-dd'T'HH:mm:ss.SSS}", + "appName" : "${springAppName}", + "TraceId" : "%mdc{traceId}", + "SpanId" : "%mdc{spanId}", + "thread" : "%thread", + "level" : "%level", + "logger": "%logger", + "location" : { + "fileName" : "%file", + "line" : "%line" + }, + "message": "%message" + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/refarch-gateway/src/test/java/@muenchen/TestConstants.java b/refarch-gateway/src/test/java/@muenchen/TestConstants.java new file mode 100644 index 00000000..e178c371 --- /dev/null +++ b/refarch-gateway/src/test/java/@muenchen/TestConstants.java @@ -0,0 +1,15 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class TestConstants { + + public static final String SPRING_TEST_PROFILE = "test"; + +} diff --git a/refarch-gateway/src/test/java/@muenchen/controller/ActuatorInfoEndpointTest.java b/refarch-gateway/src/test/java/@muenchen/controller/ActuatorInfoEndpointTest.java new file mode 100644 index 00000000..d00e0401 --- /dev/null +++ b/refarch-gateway/src/test/java/@muenchen/controller/ActuatorInfoEndpointTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.controller; + +import @muenchen.ApiGatewayApplication; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static @muenchen.TestConstants.SPRING_TEST_PROFILE; + +@ExtendWith(SpringExtension.class) +@SpringBootTest( + classes = { ApiGatewayApplication.class }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT +) +@ActiveProfiles(SPRING_TEST_PROFILE) +public class ActuatorInfoEndpointTest { + + @Autowired + private WebTestClient webTestClient; + + @Test + public void actuatorInfoProvidesAppswitcherUrl() { + //@formatter:off + webTestClient.get().uri("/actuator/info").exchange() + .expectStatus().isOk() + .expectBody() + .jsonPath("$.appswitcher.url").isEqualTo("https://test-url-appswitcher.muenchen.de"); + //@formatter:on + } + +} diff --git a/refarch-gateway/src/test/java/@muenchen/filter/CsrfTokenAppendingHelperFilterTest.java b/refarch-gateway/src/test/java/@muenchen/filter/CsrfTokenAppendingHelperFilterTest.java new file mode 100644 index 00000000..59533b6d --- /dev/null +++ b/refarch-gateway/src/test/java/@muenchen/filter/CsrfTokenAppendingHelperFilterTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import @muenchen.ApiGatewayApplication; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static @muenchen.TestConstants.SPRING_TEST_PROFILE; + +@ExtendWith(SpringExtension.class) +@SpringBootTest( + classes = { ApiGatewayApplication.class }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT +) +@ActiveProfiles(SPRING_TEST_PROFILE) +class CsrfTokenAppendingHelperFilterTest { + + @Autowired + private WebTestClient webTestClient; + + @Test + @WithMockUser + void csrfCookieAppendition() { + webTestClient.get().uri("/").exchange() + .expectHeader() + .valueMatches("set-cookie", "XSRF-TOKEN=[a-f\\d]{8}(-[a-f\\d]{4}){3}-[a-f\\d]{12}?;\\sPath=/"); + } + +} diff --git a/refarch-gateway/src/test/java/@muenchen/filter/GlobalAuthenticationErrorFilterTest.java b/refarch-gateway/src/test/java/@muenchen/filter/GlobalAuthenticationErrorFilterTest.java new file mode 100644 index 00000000..fe01ba34 --- /dev/null +++ b/refarch-gateway/src/test/java/@muenchen/filter/GlobalAuthenticationErrorFilterTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import @muenchen.ApiGatewayApplication; +import com.github.tomakehurst.wiremock.http.HttpHeader; +import com.github.tomakehurst.wiremock.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +import org.springframework.http.HttpStatus; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; + +@ExtendWith(SpringExtension.class) +@SpringBootTest( + classes = { ApiGatewayApplication.class }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT +) +@ActiveProfiles(SPRING_TEST_PROFILE) +@AutoConfigureWireMock +class GlobalAuthenticationErrorFilterTest { + + @Autowired + private WebTestClient webTestClient; + + @BeforeEach + void setup() { + stubFor(get(urlEqualTo("/remote")) + .willReturn(aResponse() + .withStatus(HttpStatus.UNAUTHORIZED.value()) + .withHeaders(new HttpHeaders( + new HttpHeader("Content-Type", "application/json"), + new HttpHeader("WWW-Authenticate", "Bearer realm=\"Access to the staging site\", charset=\"UTF-8\""), + new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) + .withBody("{ \"testkey\" : \"testvalue\" }"))); + } + + @Test + @WithMockUser + void backendAuthenticationError() { + //@formatter:off + webTestClient.get().uri("/api/refarch-gateway-backend-service/remote").exchange() + .expectStatus().isEqualTo(HttpStatus.UNAUTHORIZED) + .expectHeader().valueMatches("Content-Type", "application/json") + .expectHeader().doesNotExist("WWW-Authenticate") + .expectHeader().valueMatches("Expires", "0") + .expectBody() + .jsonPath("$.status").isEqualTo("401") + .jsonPath("$.error").isEqualTo("Authentication Error"); + //@formatter:on + } + +} diff --git a/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackend5xxTo400MapperTest.java b/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackend5xxTo400MapperTest.java new file mode 100644 index 00000000..16ce5949 --- /dev/null +++ b/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackend5xxTo400MapperTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import @muenchen.ApiGatewayApplication; +import com.github.tomakehurst.wiremock.http.HttpHeader; +import com.github.tomakehurst.wiremock.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +import org.springframework.http.HttpStatus; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; + +@ExtendWith(SpringExtension.class) +@SpringBootTest( + classes = { ApiGatewayApplication.class }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT +) +@ActiveProfiles(SPRING_TEST_PROFILE) +@AutoConfigureWireMock +@TestPropertySource( + properties = { + "config.map5xxto400:true", + } +) +public class GlobalBackend5xxTo400MapperTest { + + @Autowired + private WebTestClient webTestClient; + + @Test + @WithMockUser + public void backendError500() { + + stubFor(get(urlEqualTo("/remote")) + .willReturn(aResponse() + .withStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()) + .withHeaders(new HttpHeaders( + new HttpHeader("Content-Type", "application/json"), + new HttpHeader("WWW-Authenticate", "Bearer realm=\"Access to the staging site\", charset=\"UTF-8\""), + new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) + .withBody("{ \"testkey\" : \"testvalue\" }"))); + + //@formatter:off + webTestClient.get().uri("/api/refarch-gateway-backend-service/remote").exchange() + .expectStatus().isEqualTo(HttpStatus.BAD_REQUEST) + .expectHeader().valueMatches("Content-Type", "application/json") + .expectHeader().doesNotExist("WWW-Authenticate") + .expectHeader().valueMatches("Expires", "0") + .expectBody() + .jsonPath("$.status").isEqualTo("400") + .jsonPath("$.error").isEqualTo("Bad Request"); + //@formatter:on + } + + @Test + @WithMockUser + public void backendError200() { + + stubFor(get(urlEqualTo("/remote")) + .willReturn(aResponse() + .withStatus(HttpStatus.OK.value()) + .withHeaders(new HttpHeaders( + new HttpHeader("Content-Type", "application/json"), + new HttpHeader("WWW-Authenticate", "Bearer realm=\"Access to the staging site\", charset=\"UTF-8\""), + new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) + .withBody("{ \"testkey\" : \"testvalue\" }"))); + + //@formatter:off + webTestClient.get().uri("/api/refarch-gateway-backend-service/remote").exchange() + .expectStatus().isEqualTo(HttpStatus.OK) + .expectHeader().valueMatches("Content-Type", "application/json") + .expectHeader().doesNotExist("WWW-Authenticate") + .expectHeader().valueMatches("Expires", "0") + .expectBody() + .jsonPath("$.testkey").isEqualTo("testvalue"); + //@formatter:on + } +} diff --git a/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackendErrorFilterTest.java b/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackendErrorFilterTest.java new file mode 100644 index 00000000..f047eb50 --- /dev/null +++ b/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackendErrorFilterTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import @muenchen.ApiGatewayApplication; +import com.github.tomakehurst.wiremock.http.HttpHeader; +import com.github.tomakehurst.wiremock.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +import org.springframework.http.HttpStatus; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; + +@ExtendWith(SpringExtension.class) +@SpringBootTest( + classes = { ApiGatewayApplication.class }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT +) +@ActiveProfiles(SPRING_TEST_PROFILE) +@AutoConfigureWireMock +@TestPropertySource( + properties = { + "config.map5xxto400:false", + } +) +class GlobalBackendErrorFilterTest { + + @Autowired + private WebTestClient webTestClient; + + @BeforeEach + void setup() { + stubFor(get(urlEqualTo("/remote")) + .willReturn(aResponse() + .withStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()) + .withHeaders(new HttpHeaders( + new HttpHeader("Content-Type", "application/json"), + new HttpHeader("WWW-Authenticate", "Bearer realm=\"Access to the staging site\", charset=\"UTF-8\""), + new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) + .withBody("{ \"testkey\" : \"testvalue\" }"))); + } + + @Test + @WithMockUser + void backendError() { + //@formatter:off + webTestClient.get().uri("/api/refarch-gateway-backend-service/remote").exchange() + .expectStatus().isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR) + .expectHeader().valueMatches("Content-Type", "application/json") + .expectHeader().doesNotExist("WWW-Authenticate") + .expectHeader().valueMatches("Expires", "0") + .expectBody() + .jsonPath("$.status").isEqualTo("500") + .jsonPath("$.error").isEqualTo("Internal Server Error"); + //@formatter:on + } + +} diff --git a/refarch-gateway/src/test/java/@muenchen/filter/GlobalRequestParameterPollutionFilterTest.java b/refarch-gateway/src/test/java/@muenchen/filter/GlobalRequestParameterPollutionFilterTest.java new file mode 100644 index 00000000..dda2b9f1 --- /dev/null +++ b/refarch-gateway/src/test/java/@muenchen/filter/GlobalRequestParameterPollutionFilterTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.filter; + +import @muenchen.ApiGatewayApplication; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.nio.charset.StandardCharsets; + +@ExtendWith(SpringExtension.class) +@SpringBootTest( + classes = { ApiGatewayApplication.class }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT +) +@ActiveProfiles(SPRING_TEST_PROFILE) +class GlobalRequestParameterPollutionFilterTest { + + @Autowired + private WebTestClient webTestClient; + + @Test + @WithMockUser + void parameterPollutionAttack() { + final StringBuilder jsonResponseBody = new StringBuilder(); + String url = "/api/refarch-gateway-backend-service/testendpoint?parameter1=testdata_1¶meter2=testdata¶meter1=testdata_2"; + webTestClient.get().uri(url).exchange() + .expectStatus() + .isEqualTo(HttpStatus.BAD_REQUEST) + .expectBody() + .consumeWith(responseBody -> jsonResponseBody.append(new String(responseBody.getResponseBody(), StandardCharsets.UTF_8))); + assertTrue(jsonResponseBody.toString().contains("\"message\" : \"parameter pollution\"")); + } + +} diff --git a/refarch-gateway/src/test/java/@muenchen/route/BackendRouteTest.java b/refarch-gateway/src/test/java/@muenchen/route/BackendRouteTest.java new file mode 100644 index 00000000..6cebacea --- /dev/null +++ b/refarch-gateway/src/test/java/@muenchen/route/BackendRouteTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik + * der Landeshauptstadt München, 2024 + */ +package @muenchen.route; + +import com.github.tomakehurst.wiremock.http.HttpHeader; +import com.github.tomakehurst.wiremock.http.HttpHeaders; +import com.github.tomakehurst.wiremock.matching.EqualToPattern; +import @muenchen.ApiGatewayApplication; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +import org.springframework.http.HttpStatus; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; + +@ExtendWith(SpringExtension.class) +@SpringBootTest( + classes = { ApiGatewayApplication.class }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT +) +@ActiveProfiles(SPRING_TEST_PROFILE) +@AutoConfigureWireMock +class BackendRouteTest { + + @Autowired + private WebTestClient webTestClient; + + @BeforeEach + void setup() { + stubFor(get(urlEqualTo("/remote/endpoint")) + .willReturn(aResponse() + .withStatus(HttpStatus.OK.value()) + .withHeaders(new HttpHeaders( + new HttpHeader("Content-Type", "application/json"), + new HttpHeader("WWW-Authenticate", "Bearer realm=\"Access to the staging site\", charset=\"UTF-8\""), // removed by route filter + new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT") // removed by route filter + )) + .withBody("{ \"testkey\" : \"testvalue\" }"))); + } + + @Test + @WithMockUser + void backendRouteResponse() { + webTestClient.get().uri("/api/refarch-gateway-backend-service/remote/endpoint") + .header("Cookie", "SESSION=5cfb01a3-b691-4ca9-8735-a05690e6c2ec; XSRF-TOKEN=4d82f9f1-41f6-4a09-994a-df99d30d1be9") // removed by default-filter + .header("X-XSRF-TOKEN", "5cfb01a3-b691-4ca9-8735-a05690e6c2ec") // angular specific -> removed by default-filter + .header("Content-Type", "application/hal+json") + .exchange() + .expectStatus().isEqualTo(HttpStatus.OK) + .expectHeader().valueMatches("Content-Type", "application/json") + .expectHeader().doesNotExist("WWW-Authenticate") + .expectHeader().valueMatches("Expires", "0") + .expectBody().jsonPath("$.testkey").isEqualTo("testvalue"); + + verify(getRequestedFor(urlEqualTo("/remote/endpoint")) + .withoutHeader("Cookie") + .withoutHeader("X-SRF-TOKEN") + .withHeader("Content-Type", new EqualToPattern("application/hal+json"))); + } + +} From 22e71618b3a87ee0d41a8000615c36bd54987768 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Thu, 4 Jul 2024 15:12:01 +0200 Subject: [PATCH 02/48] gateway fix package --- .../ApiGatewayApplication.java | 4 ++-- .../configuration/GuiConfiguration.java | 2 +- .../configuration/NoSecurityConfiguration.java | 2 +- .../configuration/SecurityConfiguration.java | 4 ++-- .../configuration/VueCacheConfiguration.java | 2 +- .../configuration/WebSessionConfiguration.java | 2 +- .../exception/ParameterPollutionException.java | 4 ++-- .../filter/CsrfTokenAppendingHelperFilter.java | 4 ++-- .../filter/DistributedTracingFilter.java | 2 +- .../filter/GlobalAuthenticationErrorFilter.java | 2 +- .../filter/GlobalBackend5xxTo400Mapper.java | 2 +- .../filter/GlobalRequestParameterPollutionFilter.java | 4 ++-- refarch-gateway/src/main/resources/logback-spring.xml | 4 ++-- .../TestConstants.java | 2 +- .../controller/ActuatorInfoEndpointTest.java | 6 +++--- .../filter/CsrfTokenAppendingHelperFilterTest.java | 6 +++--- .../filter/GlobalAuthenticationErrorFilterTest.java | 6 +++--- .../filter/GlobalBackend5xxTo400MapperTest.java | 6 +++--- .../filter/GlobalBackendErrorFilterTest.java | 6 +++--- .../filter/GlobalRequestParameterPollutionFilterTest.java | 6 +++--- .../route/BackendRouteTest.java | 6 +++--- 21 files changed, 41 insertions(+), 41 deletions(-) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/ApiGatewayApplication.java (92%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/configuration/GuiConfiguration.java (96%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/configuration/NoSecurityConfiguration.java (94%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/configuration/SecurityConfiguration.java (97%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/configuration/VueCacheConfiguration.java (96%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/configuration/WebSessionConfiguration.java (98%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/exception/ParameterPollutionException.java (84%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/CsrfTokenAppendingHelperFilter.java (92%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/DistributedTracingFilter.java (97%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/GlobalAuthenticationErrorFilter.java (98%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/GlobalBackend5xxTo400Mapper.java (99%) rename refarch-gateway/src/main/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/GlobalRequestParameterPollutionFilter.java (95%) rename refarch-gateway/src/test/java/{@muenchen => de.muenchen.oss.refarch.gateway}/TestConstants.java (89%) rename refarch-gateway/src/test/java/{@muenchen => de.muenchen.oss.refarch.gateway}/controller/ActuatorInfoEndpointTest.java (86%) rename refarch-gateway/src/test/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/CsrfTokenAppendingHelperFilterTest.java (86%) rename refarch-gateway/src/test/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/GlobalAuthenticationErrorFilterTest.java (93%) rename refarch-gateway/src/test/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/GlobalBackend5xxTo400MapperTest.java (95%) rename refarch-gateway/src/test/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/GlobalBackendErrorFilterTest.java (93%) rename refarch-gateway/src/test/java/{@muenchen => de.muenchen.oss.refarch.gateway}/filter/GlobalRequestParameterPollutionFilterTest.java (90%) rename refarch-gateway/src/test/java/{@muenchen => de.muenchen.oss.refarch.gateway}/route/BackendRouteTest.java (94%) diff --git a/refarch-gateway/src/main/java/@muenchen/ApiGatewayApplication.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java similarity index 92% rename from refarch-gateway/src/main/java/@muenchen/ApiGatewayApplication.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java index 5ce401ef..cdee8b90 100644 --- a/refarch-gateway/src/main/java/@muenchen/ApiGatewayApplication.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java @@ -2,7 +2,7 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen; +package de.muenchen.oss.refarch.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -31,7 +31,7 @@ * @see https://cloud.spring.io/spring-cloud-gateway/reference/html/ */ -@SpringBootApplication(scanBasePackages = { "@muenchen" }) +@SpringBootApplication(scanBasePackages = { "de.muenchen.oss.refarch.gateway" }) public class ApiGatewayApplication { public static void main(String[] args) { diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/GuiConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java similarity index 96% rename from refarch-gateway/src/main/java/@muenchen/configuration/GuiConfiguration.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java index 948d9db0..64d18ed1 100644 --- a/refarch-gateway/src/main/java/@muenchen/configuration/GuiConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java @@ -2,7 +2,7 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.configuration; +package de.muenchen.oss.refarch.gateway.configuration; import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RouterFunctions.route; diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/NoSecurityConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java similarity index 94% rename from refarch-gateway/src/main/java/@muenchen/configuration/NoSecurityConfiguration.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java index d820630f..c7797f26 100644 --- a/refarch-gateway/src/main/java/@muenchen/configuration/NoSecurityConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java @@ -2,7 +2,7 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.configuration; +package de.muenchen.oss.refarch.gateway.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/SecurityConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java similarity index 97% rename from refarch-gateway/src/main/java/@muenchen/configuration/SecurityConfiguration.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java index b01af996..f92089c4 100644 --- a/refarch-gateway/src/main/java/@muenchen/configuration/SecurityConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.configuration; +package de.muenchen.oss.refarch.gateway.configuration; -import @muenchen.filter.CsrfTokenAppendingHelperFilter; +import de.muenchen.oss.refarch.gateway.filter.CsrfTokenAppendingHelperFilter; import java.net.URI; import java.time.Duration; import org.springframework.beans.factory.annotation.Value; diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/VueCacheConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java similarity index 96% rename from refarch-gateway/src/main/java/@muenchen/configuration/VueCacheConfiguration.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java index c1860be7..369de70e 100644 --- a/refarch-gateway/src/main/java/@muenchen/configuration/VueCacheConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java @@ -2,7 +2,7 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.configuration; +package de.muenchen.oss.refarch.gateway.configuration; import java.time.Duration; import org.springframework.context.annotation.Configuration; diff --git a/refarch-gateway/src/main/java/@muenchen/configuration/WebSessionConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java similarity index 98% rename from refarch-gateway/src/main/java/@muenchen/configuration/WebSessionConfiguration.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java index db97f6ad..76e0cc57 100644 --- a/refarch-gateway/src/main/java/@muenchen/configuration/WebSessionConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java @@ -2,7 +2,7 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.configuration; +package de.muenchen.oss.refarch.gateway.configuration; import com.hazelcast.config.Config; import com.hazelcast.config.EvictionPolicy; diff --git a/refarch-gateway/src/main/java/@muenchen/exception/ParameterPollutionException.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/exception/ParameterPollutionException.java similarity index 84% rename from refarch-gateway/src/main/java/@muenchen/exception/ParameterPollutionException.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/exception/ParameterPollutionException.java index 1b0c2950..f93ef68c 100644 --- a/refarch-gateway/src/main/java/@muenchen/exception/ParameterPollutionException.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/exception/ParameterPollutionException.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.exception; +package de.muenchen.oss.refarch.gateway.exception; -import @muenchen.filter.GlobalRequestParameterPollutionFilter; +import de.muenchen.oss.refarch.gateway.filter.GlobalRequestParameterPollutionFilter; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; diff --git a/refarch-gateway/src/main/java/@muenchen/filter/CsrfTokenAppendingHelperFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java similarity index 92% rename from refarch-gateway/src/main/java/@muenchen/filter/CsrfTokenAppendingHelperFilter.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java index 39eeb86d..8c5751f3 100644 --- a/refarch-gateway/src/main/java/@muenchen/filter/CsrfTokenAppendingHelperFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; -import @muenchen.configuration.SecurityConfiguration; +import de.muenchen.oss.refarch.gateway.configuration.SecurityConfiguration; import lombok.extern.slf4j.Slf4j; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.security.web.server.csrf.CookieServerCsrfTokenRepository; diff --git a/refarch-gateway/src/main/java/@muenchen/filter/DistributedTracingFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java similarity index 97% rename from refarch-gateway/src/main/java/@muenchen/filter/DistributedTracingFilter.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java index 01414afc..047e3ad0 100644 --- a/refarch-gateway/src/main/java/@muenchen/filter/DistributedTracingFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java @@ -2,7 +2,7 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; import io.micrometer.tracing.Tracer; import lombok.extern.slf4j.Slf4j; diff --git a/refarch-gateway/src/main/java/@muenchen/filter/GlobalAuthenticationErrorFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java similarity index 98% rename from refarch-gateway/src/main/java/@muenchen/filter/GlobalAuthenticationErrorFilter.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java index 7eedd862..a3d1fdb8 100644 --- a/refarch-gateway/src/main/java/@muenchen/filter/GlobalAuthenticationErrorFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java @@ -2,7 +2,7 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; import com.hazelcast.org.apache.commons.codec.binary.StringUtils; import lombok.extern.slf4j.Slf4j; diff --git a/refarch-gateway/src/main/java/@muenchen/filter/GlobalBackend5xxTo400Mapper.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java similarity index 99% rename from refarch-gateway/src/main/java/@muenchen/filter/GlobalBackend5xxTo400Mapper.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java index bd6c3ada..cf87c9a8 100644 --- a/refarch-gateway/src/main/java/@muenchen/filter/GlobalBackend5xxTo400Mapper.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java @@ -2,7 +2,7 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; import com.hazelcast.org.apache.commons.codec.binary.StringUtils; import java.nio.charset.StandardCharsets; diff --git a/refarch-gateway/src/main/java/@muenchen/filter/GlobalRequestParameterPollutionFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java similarity index 95% rename from refarch-gateway/src/main/java/@muenchen/filter/GlobalRequestParameterPollutionFilter.java rename to refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java index f1a0eb0f..5078a9de 100644 --- a/refarch-gateway/src/main/java/@muenchen/filter/GlobalRequestParameterPollutionFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; -import @muenchen.exception.ParameterPollutionException; +import de.muenchen.oss.refarch.gateway.exception.ParameterPollutionException; import java.util.List; import java.util.Map; import lombok.extern.slf4j.Slf4j; diff --git a/refarch-gateway/src/main/resources/logback-spring.xml b/refarch-gateway/src/main/resources/logback-spring.xml index 43d6be87..1494ddd2 100644 --- a/refarch-gateway/src/main/resources/logback-spring.xml +++ b/refarch-gateway/src/main/resources/logback-spring.xml @@ -20,7 +20,7 @@ - @@ -89,7 +89,7 @@ - diff --git a/refarch-gateway/src/test/java/@muenchen/TestConstants.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/TestConstants.java similarity index 89% rename from refarch-gateway/src/test/java/@muenchen/TestConstants.java rename to refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/TestConstants.java index e178c371..7e0bb707 100644 --- a/refarch-gateway/src/test/java/@muenchen/TestConstants.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/TestConstants.java @@ -2,7 +2,7 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen; +package de.muenchen.oss.refarch.gateway; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/refarch-gateway/src/test/java/@muenchen/controller/ActuatorInfoEndpointTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java similarity index 86% rename from refarch-gateway/src/test/java/@muenchen/controller/ActuatorInfoEndpointTest.java rename to refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java index d00e0401..2285b831 100644 --- a/refarch-gateway/src/test/java/@muenchen/controller/ActuatorInfoEndpointTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.controller; +package de.muenchen.oss.refarch.gateway.controller; -import @muenchen.ApiGatewayApplication; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -13,7 +13,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; @ExtendWith(SpringExtension.class) @SpringBootTest( diff --git a/refarch-gateway/src/test/java/@muenchen/filter/CsrfTokenAppendingHelperFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java similarity index 86% rename from refarch-gateway/src/test/java/@muenchen/filter/CsrfTokenAppendingHelperFilterTest.java rename to refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java index 59533b6d..0582ac7b 100644 --- a/refarch-gateway/src/test/java/@muenchen/filter/CsrfTokenAppendingHelperFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; -import @muenchen.ApiGatewayApplication; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -14,7 +14,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; @ExtendWith(SpringExtension.class) @SpringBootTest( diff --git a/refarch-gateway/src/test/java/@muenchen/filter/GlobalAuthenticationErrorFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java similarity index 93% rename from refarch-gateway/src/test/java/@muenchen/filter/GlobalAuthenticationErrorFilterTest.java rename to refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java index fe01ba34..4dcfb22e 100644 --- a/refarch-gateway/src/test/java/@muenchen/filter/GlobalAuthenticationErrorFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; -import @muenchen.ApiGatewayApplication; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; import org.junit.jupiter.api.BeforeEach; @@ -19,7 +19,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; diff --git a/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackend5xxTo400MapperTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java similarity index 95% rename from refarch-gateway/src/test/java/@muenchen/filter/GlobalBackend5xxTo400MapperTest.java rename to refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java index 16ce5949..c19a6efd 100644 --- a/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackend5xxTo400MapperTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; -import @muenchen.ApiGatewayApplication; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; import org.junit.jupiter.api.BeforeEach; @@ -20,7 +20,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; diff --git a/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackendErrorFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java similarity index 93% rename from refarch-gateway/src/test/java/@muenchen/filter/GlobalBackendErrorFilterTest.java rename to refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java index f047eb50..cdc1e54a 100644 --- a/refarch-gateway/src/test/java/@muenchen/filter/GlobalBackendErrorFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; -import @muenchen.ApiGatewayApplication; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; import org.junit.jupiter.api.BeforeEach; @@ -20,7 +20,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; diff --git a/refarch-gateway/src/test/java/@muenchen/filter/GlobalRequestParameterPollutionFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java similarity index 90% rename from refarch-gateway/src/test/java/@muenchen/filter/GlobalRequestParameterPollutionFilterTest.java rename to refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java index dda2b9f1..e164e456 100644 --- a/refarch-gateway/src/test/java/@muenchen/filter/GlobalRequestParameterPollutionFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java @@ -2,9 +2,9 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.filter; +package de.muenchen.oss.refarch.gateway.filter; -import @muenchen.ApiGatewayApplication; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -15,7 +15,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.charset.StandardCharsets; diff --git a/refarch-gateway/src/test/java/@muenchen/route/BackendRouteTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java similarity index 94% rename from refarch-gateway/src/test/java/@muenchen/route/BackendRouteTest.java rename to refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java index 6cebacea..af653eb9 100644 --- a/refarch-gateway/src/test/java/@muenchen/route/BackendRouteTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java @@ -2,12 +2,12 @@ * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik * der Landeshauptstadt München, 2024 */ -package @muenchen.route; +package de.muenchen.oss.refarch.gateway.route; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; import com.github.tomakehurst.wiremock.matching.EqualToPattern; -import @muenchen.ApiGatewayApplication; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,7 +20,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static @muenchen.TestConstants.SPRING_TEST_PROFILE; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; From d11cabc790811e2859bb33629da7875cdb1bb33f Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Thu, 4 Jul 2024 15:12:26 +0200 Subject: [PATCH 03/48] mv build config to root --- pom.xml | 154 ++++++++++++++++++++++++++++++------ refarch-gateway/pom.xml | 168 ++-------------------------------------- 2 files changed, 139 insertions(+), 183 deletions(-) diff --git a/pom.xml b/pom.xml index c84c6d13..fa3e20a2 100644 --- a/pom.xml +++ b/pom.xml @@ -4,29 +4,28 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - - de.muenchen - muenchen-pom - 2.1.0 - - - de.muenchen.oss refarch - 0.0.1-SNAPSHOT + 1.0.0-SNAPSHOT pom refarch + + UTF-8 + 17 + 17 + 17 + -Dorg.conscrypt.native.workdir=$(pwd) + 0.8.7 + + 3.0.7 + 2022.0.3 + + refarch-gateway - - - 3.9.0.2155 - - https://github.com/it-at-m/refarch.git scm:git:https://github.com/it-at-m/refarch.git @@ -38,22 +37,131 @@ + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring.cloud.version} + pom + import + + + + + + + src/main/resources + true + + - maven-scm-plugin - 1.10.0 + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 - RT-REL-${project.version} + ${jvm.options} - org.sonarsource.scanner.maven - sonar-maven-plugin - ${sonar.scanner.version} - + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + + + com.diffplug.spotless + spotless-maven-plugin + 2.28.0 + + + de.muenchen.oss + itm-java-codeformat + 1.0.7 + + + + + + src/main/java/**/*.java + src/test/java/**/*.java + + + itm-java-codeformat/java_codestyle_formatter.xml + + + + + + + + + check + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.2.1 + + checkstyle.xml + + + + + check + + + + + + com.puppycrawl.tools + checkstyle + 9.3 + + + - - diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index 523c198f..17bf908f 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -6,59 +6,26 @@ - de.muenchen - muenchen-pom - 2.1.0 + de.muenchen.oss + refarch + ../pom.xml + 1.0.0-SNAPSHOT - de.muenchen.oss.refarch.apigateway - gateway-apigateway - 0.0.1-SNAPSHOT + de.muenchen.oss.refarch + refarch-gateway + 1.0.0-SNAPSHOT jar - gateway_apigateway - + refarch-gateway - UTF-8 - 17 - 17 - 17 - 3.0.7 - 2022.0.3 7.0.1 - 4.2.8 3.12.0 - -Dorg.conscrypt.native.workdir=$(pwd) - 0.8.7 - - - - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring.cloud.version} - pom - import - - - - - - org.springframework.cloud @@ -154,124 +121,5 @@ io.micrometer micrometer-registry-prometheus - - - - de.muenchen.oss.refarch.frontend - gateway-frontend - ${project.version} - runtime - - - - - - - - src/main/resources - true - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - - ${jvm.options} - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - - repackage - - - - - - org.jacoco - jacoco-maven-plugin - ${jacoco.version} - - - - prepare-agent - - - - report - prepare-package - - report - - - - - - - - com.diffplug.spotless - spotless-maven-plugin - 2.28.0 - - - de.muenchen.oss - itm-java-codeformat - 1.0.7 - - - - - - src/main/java/**/*.java - src/test/java/**/*.java - - - itm-java-codeformat/java_codestyle_formatter.xml - - - - - - - - - check - - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.2.1 - - checkstyle.xml - - - - - check - - - - - - com.puppycrawl.tools - checkstyle - 9.3 - - - - - - - From d4e2a69aad719e29702bf205709045c9506021a7 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Thu, 4 Jul 2024 15:30:12 +0200 Subject: [PATCH 04/48] cp build from digiwf --- pom.xml | 399 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 307 insertions(+), 92 deletions(-) diff --git a/pom.xml b/pom.xml index fa3e20a2..c7002463 100644 --- a/pom.xml +++ b/pom.xml @@ -15,8 +15,10 @@ 17 17 17 - -Dorg.conscrypt.native.workdir=$(pwd) - 0.8.7 + + 1.18.34 + 0.2.0 + 1.5.5.Final 3.0.7 2022.0.3 @@ -59,109 +61,322 @@ - - - src/main/resources - true - - + + + + org.apache.maven.plugins + maven-clean-plugin + 3.4.0 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + true + ${java.version} + ${java.version} + true + + + org.projectlombok + lombok + + ${lombok.version} + + + org.projectlombok + lombok-mapstruct-binding + ${lombok.mapstruct.binding.version} + + + org.mapstruct + mapstruct-processor + ${org.mapstruct.version} + + + + + -Amapstruct.defaultComponentModel=spring + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + UTF-8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.2 + + + org.apache.maven.plugins + maven-install-plugin + 3.1.2 + + + org.apache.maven.plugins + maven-release-plugin + 3.1.0 + + false + false + release + deploy + @{project.version} + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.3.0 + + random + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.3.0 + + + run-itests + integration-test + + integration-test + verify + + + + + ${project.build.outputDirectory} + @{argLine} -Xms256m -Xmx2048m -Dfile.encoding=${project.build.sourceEncoding} + + + + org.jacoco + jacoco-maven-plugin + 0.8.12 + + + prepare-agent + + prepare-agent + + + + report + test + + report + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.5.0 + + + enforce-maven + + enforce + + + + + ${java.version} + + + 3.9.0 + + + + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.5.0 + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + org.openapitools + openapi-generator-maven-plugin + 7.7.0 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.7.0 + + + org.apache.maven.plugins + maven-gpg-plugin + 3.2.4 + + + org.codehaus.mojo + versions-maven-plugin + 2.17.0 + + + org.apache.maven.plugins + maven-source-plugin + 3.3.1 + + + de.juplo + hibernate-maven-plugin + 2.1.1 + + + org.apache.cxf + cxf-codegen-plugin + 4.0.4 + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + com.github.eirslett + frontend-maven-plugin + 1.15.0 + + + org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - - ${jvm.options} - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - - repackage - - - + maven-enforcer-plugin org.jacoco jacoco-maven-plugin - ${jacoco.version} - - - - prepare-agent - - - - report - prepare-package - - report - - - - - - com.diffplug.spotless - spotless-maven-plugin - 2.28.0 - - - de.muenchen.oss - itm-java-codeformat - 1.0.7 - - - - - - src/main/java/**/*.java - src/test/java/**/*.java - - - itm-java-codeformat/java_codestyle_formatter.xml - - - - - - - - - check - - - + org.apache.maven.plugins + maven-release-plugin - org.apache.maven.plugins - maven-checkstyle-plugin - 3.2.1 - - checkstyle.xml - - - - - check - - - - - - com.puppycrawl.tools - checkstyle - 9.3 - - + maven-failsafe-plugin + + + + + release + + + + + org.sonatype.central + central-publishing-maven-plugin + true + + true + true + ${project.groupId}:${project.version} + + + refarch-gateway + + + + + + + org.codehaus.mojo + versions-maven-plugin + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar-no-fork + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + none + + **/*.java + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + --pinentry-mode + loopback + + + + + + + + + From 9986be5d01c48a441d66a02629104d126eb2692e Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Thu, 4 Jul 2024 15:30:26 +0200 Subject: [PATCH 05/48] gateway fix maven filters in config --- refarch-gateway/src/main/resources/application.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/refarch-gateway/src/main/resources/application.yml b/refarch-gateway/src/main/resources/application.yml index eb46b92f..dd92460b 100644 --- a/refarch-gateway/src/main/resources/application.yml +++ b/refarch-gateway/src/main/resources/application.yml @@ -1,5 +1,5 @@ spring: - application.name: @project.artifactId@ + application.name: '@project.artifactId@' banner.location: banner.txt main: web-application-type: reactive @@ -51,8 +51,10 @@ management: info: env: enabled: true -info.application.name: ${spring.application.name} -info.application.version: @project.version@ -info.appswitcher.url: https://appswitcher.muenchen.de +info: + application: + name: ${spring.application.name} + version: '@project.version@' + appswitcher.url: https://appswitcher.muenchen.de config.map5xxto400: false From 583819c9e70f44b966ce3930bda760f981aeb109 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 07:19:18 +0200 Subject: [PATCH 06/48] gateway upgrade hazlecast --- refarch-gateway/pom.xml | 4 ++-- .../filter/GlobalAuthenticationErrorFilter.java | 2 +- .../filter/GlobalBackend5xxTo400Mapper.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index 17bf908f..028a4fda 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -21,7 +21,7 @@ 7.0.1 - 4.2.8 + 5.4.0 3.12.0 @@ -68,7 +68,7 @@ com.hazelcast - hazelcast-all + hazelcast-spring ${hazelcast.version} diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java index a3d1fdb8..dbe9be72 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java @@ -4,7 +4,7 @@ */ package de.muenchen.oss.refarch.gateway.filter; -import com.hazelcast.org.apache.commons.codec.binary.StringUtils; +import org.apache.commons.codec.binary.StringUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.reactivestreams.Publisher; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java index cf87c9a8..fa8cf6c4 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java @@ -4,9 +4,9 @@ */ package de.muenchen.oss.refarch.gateway.filter; -import com.hazelcast.org.apache.commons.codec.binary.StringUtils; import java.nio.charset.StandardCharsets; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.StringUtils; import org.apache.commons.lang3.ObjectUtils; import org.reactivestreams.Publisher; import org.springframework.beans.factory.annotation.Value; From bfca877910f6d3c27fcbc286bd0ae587430d2b00 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 07:19:38 +0200 Subject: [PATCH 07/48] gateway upgrade hazlecast --- refarch-gateway/pom.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index 028a4fda..ddd8d482 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -23,6 +23,7 @@ 7.0.1 5.4.0 3.12.0 + 1.17.0 @@ -71,6 +72,11 @@ hazelcast-spring ${hazelcast.version} + + commons-codec + commons-codec + ${apache.commons.codec.version} + @@ -103,7 +109,7 @@ ${apache.commons.lang.version} - + net.logstash.logback logstash-logback-encoder From 528cbcd6102d3da0b9e84e7641dff79215628c49 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 07:21:02 +0200 Subject: [PATCH 08/48] upgrade dependencies --- pom.xml | 20 +++++++++++++++++--- refarch-gateway/pom.xml | 7 ------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index c7002463..fc8eea33 100644 --- a/pom.xml +++ b/pom.xml @@ -20,8 +20,8 @@ 0.2.0 1.5.5.Final - 3.0.7 - 2022.0.3 + 3.2.4 + 2023.0.1 @@ -39,6 +39,20 @@ + + + org.mapstruct + mapstruct + ${org.mapstruct.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + @@ -217,7 +231,7 @@ org.springframework.boot spring-boot-maven-plugin - ${spring-boot.version} + ${spring.boot.version} diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index ddd8d482..7b685b89 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -95,13 +95,6 @@ test - - - org.projectlombok - lombok - provided - - org.apache.commons From 6191a48fffedca8390c0199b125d9d436383721a Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 07:51:18 +0200 Subject: [PATCH 09/48] gateway reformat tests --- .../controller/ActuatorInfoEndpointTest.java | 6 ++--- .../CsrfTokenAppendingHelperFilterTest.java | 2 +- .../GlobalAuthenticationErrorFilterTest.java | 18 ++++++-------- .../GlobalBackend5xxTo400MapperTest.java | 24 +++++++------------ .../filter/GlobalBackendErrorFilterTest.java | 18 ++++++-------- ...alRequestParameterPollutionFilterTest.java | 6 ++--- .../route/BackendRouteTest.java | 9 ++----- .../resources/application-test.yml | 6 ++--- 8 files changed, 33 insertions(+), 56 deletions(-) rename refarch-gateway/src/{main => test}/resources/application-test.yml (92%) diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java index 2285b831..b1d9227f 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java @@ -17,7 +17,7 @@ @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = { ApiGatewayApplication.class }, + classes = {ApiGatewayApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) @@ -28,12 +28,10 @@ public class ActuatorInfoEndpointTest { @Test public void actuatorInfoProvidesAppswitcherUrl() { - //@formatter:off webTestClient.get().uri("/actuator/info").exchange() .expectStatus().isOk() .expectBody() - .jsonPath("$.appswitcher.url").isEqualTo("https://test-url-appswitcher.muenchen.de"); - //@formatter:on + .jsonPath("$.appswitcher.url").isEqualTo("https://test-url-appswitcher.muenchen.de"); } } diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java index 0582ac7b..7d0ba1a4 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java @@ -18,7 +18,7 @@ @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = { ApiGatewayApplication.class }, + classes = {ApiGatewayApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java index 4dcfb22e..b818b8e1 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java @@ -4,9 +4,9 @@ */ package de.muenchen.oss.refarch.gateway.filter; -import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -19,15 +19,12 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; +import static com.github.tomakehurst.wiremock.client.WireMock.*; import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = { ApiGatewayApplication.class }, + classes = {ApiGatewayApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) @@ -45,23 +42,22 @@ void setup() { .withHeaders(new HttpHeaders( new HttpHeader("Content-Type", "application/json"), new HttpHeader("WWW-Authenticate", "Bearer realm=\"Access to the staging site\", charset=\"UTF-8\""), - new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) + new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT") + )) .withBody("{ \"testkey\" : \"testvalue\" }"))); } @Test @WithMockUser void backendAuthenticationError() { - //@formatter:off webTestClient.get().uri("/api/refarch-gateway-backend-service/remote").exchange() .expectStatus().isEqualTo(HttpStatus.UNAUTHORIZED) .expectHeader().valueMatches("Content-Type", "application/json") .expectHeader().doesNotExist("WWW-Authenticate") .expectHeader().valueMatches("Expires", "0") .expectBody() - .jsonPath("$.status").isEqualTo("401") - .jsonPath("$.error").isEqualTo("Authentication Error"); - //@formatter:on + .jsonPath("$.status").isEqualTo("401") + .jsonPath("$.error").isEqualTo("Authentication Error"); } } diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java index c19a6efd..22b31e4f 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java @@ -4,10 +4,9 @@ */ package de.muenchen.oss.refarch.gateway.filter; -import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; -import org.junit.jupiter.api.BeforeEach; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -20,26 +19,22 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; +import static com.github.tomakehurst.wiremock.client.WireMock.*; import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = { ApiGatewayApplication.class }, + classes = {ApiGatewayApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) @AutoConfigureWireMock @TestPropertySource( properties = { - "config.map5xxto400:true", + "config.map5xxto400=true", } ) public class GlobalBackend5xxTo400MapperTest { - @Autowired private WebTestClient webTestClient; @@ -56,16 +51,14 @@ public void backendError500() { new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) .withBody("{ \"testkey\" : \"testvalue\" }"))); - //@formatter:off webTestClient.get().uri("/api/refarch-gateway-backend-service/remote").exchange() .expectStatus().isEqualTo(HttpStatus.BAD_REQUEST) .expectHeader().valueMatches("Content-Type", "application/json") .expectHeader().doesNotExist("WWW-Authenticate") .expectHeader().valueMatches("Expires", "0") .expectBody() - .jsonPath("$.status").isEqualTo("400") - .jsonPath("$.error").isEqualTo("Bad Request"); - //@formatter:on + .jsonPath("$.status").isEqualTo("400") + .jsonPath("$.error").isEqualTo("Bad Request"); } @Test @@ -81,14 +74,13 @@ public void backendError200() { new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) .withBody("{ \"testkey\" : \"testvalue\" }"))); - //@formatter:off webTestClient.get().uri("/api/refarch-gateway-backend-service/remote").exchange() .expectStatus().isEqualTo(HttpStatus.OK) .expectHeader().valueMatches("Content-Type", "application/json") .expectHeader().doesNotExist("WWW-Authenticate") .expectHeader().valueMatches("Expires", "0") .expectBody() - .jsonPath("$.testkey").isEqualTo("testvalue"); - //@formatter:on + .jsonPath("$.testkey").isEqualTo("testvalue"); } + } diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java index cdc1e54a..c353bec4 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java @@ -4,9 +4,9 @@ */ package de.muenchen.oss.refarch.gateway.filter; -import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; +import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,15 +20,12 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; +import static com.github.tomakehurst.wiremock.client.WireMock.*; import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = { ApiGatewayApplication.class }, + classes = {ApiGatewayApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) @@ -51,23 +48,22 @@ void setup() { .withHeaders(new HttpHeaders( new HttpHeader("Content-Type", "application/json"), new HttpHeader("WWW-Authenticate", "Bearer realm=\"Access to the staging site\", charset=\"UTF-8\""), - new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) + new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT") + )) .withBody("{ \"testkey\" : \"testvalue\" }"))); } @Test @WithMockUser void backendError() { - //@formatter:off webTestClient.get().uri("/api/refarch-gateway-backend-service/remote").exchange() .expectStatus().isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR) .expectHeader().valueMatches("Content-Type", "application/json") .expectHeader().doesNotExist("WWW-Authenticate") .expectHeader().valueMatches("Expires", "0") .expectBody() - .jsonPath("$.status").isEqualTo("500") - .jsonPath("$.error").isEqualTo("Internal Server Error"); - //@formatter:on + .jsonPath("$.status").isEqualTo("500") + .jsonPath("$.error").isEqualTo("Internal Server Error"); } } diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java index e164e456..0dce9167 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java @@ -15,14 +15,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; +import java.nio.charset.StandardCharsets; + import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.nio.charset.StandardCharsets; - @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = { ApiGatewayApplication.class }, + classes = {ApiGatewayApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java index af653eb9..ad7dfc9e 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java @@ -20,17 +20,12 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; +import static com.github.tomakehurst.wiremock.client.WireMock.*; import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.client.WireMock.verify; @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = { ApiGatewayApplication.class }, + classes = {ApiGatewayApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) diff --git a/refarch-gateway/src/main/resources/application-test.yml b/refarch-gateway/src/test/resources/application-test.yml similarity index 92% rename from refarch-gateway/src/main/resources/application-test.yml rename to refarch-gateway/src/test/resources/application-test.yml index ca9f8e30..21e66438 100644 --- a/refarch-gateway/src/main/resources/application-test.yml +++ b/refarch-gateway/src/test/resources/application-test.yml @@ -4,8 +4,8 @@ wiremock: https-port: -1 spring: - - # muenchen.de realm is used by default so that the SpringContext can be initalized upon running the tests. Change to your own dev realm if available + + # muenchen.de realm is used by default so that the SpringContext can be initialized upon running the tests. Change to your own dev realm if available realm: muenchen.de # spring cloud gateway config @@ -55,7 +55,7 @@ spring: registration: keycloak: client-id: refarch-gateway - client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 + client-secret: mvc: log-request-details: on From b599f93ceab00d363f5773375202ffbdaaf85690 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 08:00:53 +0200 Subject: [PATCH 10/48] gateway update config --- .../src/main/resources/application.yml | 48 ++++++++++++++----- refarch-gateway/src/main/resources/banner.txt | 20 +++----- .../src/test/resources/application-test.yml | 26 ++-------- 3 files changed, 46 insertions(+), 48 deletions(-) diff --git a/refarch-gateway/src/main/resources/application.yml b/refarch-gateway/src/main/resources/application.yml index dd92460b..90f98c0c 100644 --- a/refarch-gateway/src/main/resources/application.yml +++ b/refarch-gateway/src/main/resources/application.yml @@ -7,12 +7,42 @@ spring: serialization: indent-output: on session: - timeout: 36000 # in seconds; Goal: same lifetime as SSO Session (e.g. 10 hours) + timeout: 1800 # in seconds; Goal: same lifetime as SSO Session, actual: 30 minutes zipkin: enabled: false sleuth: reactor: instrumentation-type: decorate_on_each # https://github.com/spring-cloud/spring-cloud-gateway/pull/2106 + security: + oauth2: + resourceserver: + jwt: + issuer-uri: ${SSO_ISSUER_URL} + client: + provider: + keycloak: + issuer-uri: ${SSO_ISSUER_URL} + registration: + keycloak: + client-id: ${SSO_CLIENT_ID} + client-secret: ${SSO_CLIENT_SECRET} + scope: email, profile, openid # needed for userInfo endpoint + provider: keycloak + cloud: + gateway: + globalcors: + cors-configurations: + '[/public/**]': + allowedOriginPatterns: ${ALLOWED_ORIGINS_PUBLIC} + '[/clients/**]': + allowedOriginPatterns: ${ALLOWED_ORIGINS_CLIENTS} + allowedHeaders: "*" + allowCredentials: true + default-filters: + - RemoveResponseHeader=Expires + - RemoveRequestHeader=cookie + - RemoveRequestHeader=x-xsrf-token + - TokenRelay= server: port: 8080 @@ -22,21 +52,14 @@ server: include-message: always whitelabel: enabled: false + shutdown: graceful management: endpoints: enabled-by-default: false web: - cors: - allowedOrigins: - - "http://localhost:8081" - - "http://127.0.0.1:8081" - allowedMethods: "*" - allowedHeaders: "*" - allowCredentials: on - maxAge: 3600 exposure: - include: health, info, prometheus + include: health, info, prometheus, livenessstate, readinessstate path-mapping: prometheus: metrics endpoint: @@ -51,10 +74,11 @@ management: info: env: enabled: true + info: application: name: ${spring.application.name} version: '@project.version@' - appswitcher.url: https://appswitcher.muenchen.de -config.map5xxto400: false +config: + map5xxto400: true diff --git a/refarch-gateway/src/main/resources/banner.txt b/refarch-gateway/src/main/resources/banner.txt index ab68c31a..d9c17921 100644 --- a/refarch-gateway/src/main/resources/banner.txt +++ b/refarch-gateway/src/main/resources/banner.txt @@ -1,17 +1,11 @@ --------------------------------------------------------------------------------------------------------------------------------------------------- - ____ _ _ _ _ - | _ \ | | | | /\ | | | | - | |_) | __ _ _ __ _ __ __ _ | | __ _ _ __| | __ _ ______ / \ _ __ ___ | |__ ___ | |_ _ _ _ __ ___ - | _ < / _` | | '__| | '__| / _` | | |/ / | | | | / _` | / _` | |______| / /\ \ | '__| / __| | '_ \ / _ \ | __| | | | | | '_ \ / _ \ - | |_) | | (_| | | | | | | (_| | | < | |_| | | (_| | | (_| | / ____ \ | | | (__ | | | | | __/ | |_ | |_| | | |_) | | __/ - |____/ \__,_| |_| |_| \__,_| |_|\_\ \__,_| \__,_| \__,_| /_/ \_\ |_| \___| |_| |_| \___| \__| \__, | | .__/ \___| - __/ | | | - |___/ |_| by CCSE - - Du benutzt den RefArch-Archetype und willst it@M helfen, ihn weiter zu verbessern? + ____ __ _ ____ _ + | _ \ ___ / _| __ _ _ __ ___| |__ / ___| __ _| |_ _____ ____ _ _ _ + | |_) / _ \ |_ / _` | '__/ __| '_ \| | _ / _` | __/ _ \ \ /\ / / _` | | | | + | _ < __/ _| (_| | | | (__| | | | |_| | (_| | || __/\ V V / (_| | |_| | + |_| \_\___|_| \__,_|_| \___|_| |_|\____|\__,_|\__\___| \_/\_/ \__,_|\__, | + |___/ - Gib uns dein Feedback und Verbesserungsvorschläge unter https://git.muenchen.de/ccse/refarch-archetype/refarch-overview/-/issues/new?issuable_template=Feedback - - Application Name : ${spring.application.name} + Application Name : ${spring.application.name} (v${info.application.version}) Spring Boot Version : ${spring-boot.formatted-version} --------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/refarch-gateway/src/test/resources/application-test.yml b/refarch-gateway/src/test/resources/application-test.yml index 21e66438..dae01432 100644 --- a/refarch-gateway/src/test/resources/application-test.yml +++ b/refarch-gateway/src/test/resources/application-test.yml @@ -4,27 +4,12 @@ wiremock: https-port: -1 spring: - # muenchen.de realm is used by default so that the SpringContext can be initialized upon running the tests. Change to your own dev realm if available realm: muenchen.de # spring cloud gateway config cloud: gateway: - actuator: - verbose: - enabled: false - globalcors: - corsConfigurations: - # The cors configuration to allow frontend developers cross origin request via this api gateway - '[/**]': - allowedOrigins: - - "http://localhost:8081" - - "http://127.0.0.1:8081" - allowedMethods: "*" - allowedHeaders: "*" - allowCredentials: true - maxAge: 3600 routes: - id: sso uri: https://ssotest.muenchen.de/ @@ -39,15 +24,13 @@ spring: filters: - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} - RemoveResponseHeader=WWW-Authenticate - default-filters: - - RemoveResponseHeader=Expires - - RemoveRequestHeader=cookie - - RemoveRequestHeader=x-xsrf-token - - TokenRelay= # security config security: oauth2: + resourceserver: + jwt: + issuer-uri: https://sso.muenchen.de/auth/realms/${spring.realm} client: provider: keycloak: @@ -57,7 +40,4 @@ spring: client-id: refarch-gateway client-secret: - mvc: - log-request-details: on - info.appswitcher.url: https://test-url-appswitcher.muenchen.de From 5b7b879d721ed57969af5796757b572219a3b109 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 09:34:56 +0200 Subject: [PATCH 11/48] gateway add csrf whitelist --- .../configuration/CsrfProtectionMatcher.java | 51 +++++++++++++++++++ .../configuration/SecurityProperties.java | 17 +++++++ 2 files changed, 68 insertions(+) create mode 100644 refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/CsrfProtectionMatcher.java create mode 100644 refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityProperties.java diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/CsrfProtectionMatcher.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/CsrfProtectionMatcher.java new file mode 100644 index 00000000..2f970e48 --- /dev/null +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/CsrfProtectionMatcher.java @@ -0,0 +1,51 @@ +package de.muenchen.oss.refarch.gateway.configuration; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpMethod; +import org.springframework.security.web.server.csrf.CsrfWebFilter; +import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher; +import org.springframework.util.AntPathMatcher; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +@Configuration +@Profile("!no-security") +@RequiredArgsConstructor +public class CsrfProtectionMatcher implements ServerWebExchangeMatcher { + + /** + * Copied from {@link CsrfWebFilter}.DefaultRequireCsrfProtectionMatcher + */ + private static final Set ALLOWED_METHODS = new HashSet<>( + Arrays.asList(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.TRACE, HttpMethod.OPTIONS)); + + private final SecurityProperties securityProperties; + + @Override + public Mono matches(ServerWebExchange exchange) { + return Mono.just(exchange.getRequest()) + .flatMap((r) -> Mono.justOrEmpty(new MethodAndPath(r.getMethod(), r.getPath().toString()))) + .filter((mp) -> ALLOWED_METHODS.contains(mp.method) || isWhitelisted(mp.path)) + .flatMap((m) -> MatchResult.notMatch()) + .switchIfEmpty(MatchResult.match()); + } + + private boolean isWhitelisted(String path) { + for (String whitelisted : securityProperties.getCsrfWhitelisted()) { + if (new AntPathMatcher().match(whitelisted, path)) { + return true; + } + } + return false; + } + + + private record MethodAndPath(HttpMethod method, String path) { + } +} \ No newline at end of file diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityProperties.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityProperties.java new file mode 100644 index 00000000..afb6e2a7 --- /dev/null +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityProperties.java @@ -0,0 +1,17 @@ +package de.muenchen.oss.refarch.gateway.configuration; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +@Getter +@Setter +@ConfigurationProperties("refarch.security") +public class SecurityProperties { + /** + * List of url patterns excluded from csrf protection. + */ + private List csrfWhitelisted = List.of(); +} From 5e9f1dd8137d0a35da855650de6ead01b2eaff69 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 09:35:42 +0200 Subject: [PATCH 12/48] gateway update dependency, cleanup config and add Dockerfile --- refarch-gateway/Dockerfile | 3 + refarch-gateway/pom.xml | 4 ++ .../src/main/resources/application-dev.yml | 63 ------------------- .../src/main/resources/application-kon.yml | 63 ------------------- .../src/main/resources/application-local.yml | 58 ----------------- .../src/main/resources/application-prod.yml | 63 ------------------- 6 files changed, 7 insertions(+), 247 deletions(-) create mode 100644 refarch-gateway/Dockerfile delete mode 100644 refarch-gateway/src/main/resources/application-dev.yml delete mode 100644 refarch-gateway/src/main/resources/application-kon.yml delete mode 100644 refarch-gateway/src/main/resources/application-local.yml delete mode 100644 refarch-gateway/src/main/resources/application-prod.yml diff --git a/refarch-gateway/Dockerfile b/refarch-gateway/Dockerfile new file mode 100644 index 00000000..f8e83f3a --- /dev/null +++ b/refarch-gateway/Dockerfile @@ -0,0 +1,3 @@ +FROM registry.access.redhat.com/ubi9/openjdk-17:latest + +COPY target/*.jar /deployments/spring-boot-application.jar diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index 7b685b89..3e2ce08f 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -61,6 +61,10 @@ org.springframework.boot spring-boot-starter-oauth2-client + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + diff --git a/refarch-gateway/src/main/resources/application-dev.yml b/refarch-gateway/src/main/resources/application-dev.yml deleted file mode 100644 index 4d8c52d1..00000000 --- a/refarch-gateway/src/main/resources/application-dev.yml +++ /dev/null @@ -1,63 +0,0 @@ -app: - backend-service: - frontend-service: - -spring: - - # Define the keycloak development realm here - realm: - - # spring cloud gateway config - cloud: - gateway: - actuator: - verbose: - enabled: false - globalcors: - corsConfigurations: - # The cors configuration to allow frontend developers cross origin request via this api gateway - '[/**]': - allowedOrigins: - - "http://localhost:8081" - - "http://127.0.0.1:8081" - allowedMethods: "*" - allowedHeaders: "*" - allowCredentials: true - maxAge: 3600 - routes: - - id: sso - uri: https://ssodev.muenchen.de/ - predicates: - - Path=/api/sso/userinfo - filters: - - RewritePath=/api/sso/userinfo, /auth/realms/${spring.realm}/protocol/openid-connect/userinfo - - id: backend - uri: http://${app.backend-service}:8080/ - predicates: - - Path=/api/refarch-gateway-backend-service/** - filters: - - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} - - RemoveResponseHeader=WWW-Authenticate - default-filters: - - RemoveResponseHeader=Expires - - RemoveRequestHeader=cookie - - RemoveRequestHeader=x-xsrf-token - - TokenRelay= - - # security config - security: - oauth2: - client: - provider: - keycloak: - issuer-uri: https://ssodev.muenchen.de/auth/realms/${spring.realm} - registration: - keycloak: - client-id: refarch-gateway - client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 - - mvc: - log-request-details: on - -hazelcast: - openshift-service-name: ${app.frontend-service} diff --git a/refarch-gateway/src/main/resources/application-kon.yml b/refarch-gateway/src/main/resources/application-kon.yml deleted file mode 100644 index 68ee0e05..00000000 --- a/refarch-gateway/src/main/resources/application-kon.yml +++ /dev/null @@ -1,63 +0,0 @@ -app: - backend-service: - frontend-service: - -spring: - - # Define the keycloak consolidation realm here; default is "intrap" - realm: intrap - - # spring cloud gateway config - cloud: - gateway: - actuator: - verbose: - enabled: false - globalcors: - corsConfigurations: - # The cors configuration to allow frontend developers cross origin request via this api gateway - '[/**]': - allowedOrigins: - - "http://localhost:8081" - - "http://127.0.0.1:8081" - allowedMethods: "*" - allowedHeaders: "*" - allowCredentials: true - maxAge: 3600 - routes: - - id: sso - uri: https://ssotest.muenchen.de/ - predicates: - - Path=/api/sso/userinfo - filters: - - RewritePath=/api/sso/userinfo, /auth/realms/${spring.realm}/protocol/openid-connect/userinfo - - id: backend - uri: http://${app.backend-service}:8080/ - predicates: - - Path=/api/refarch-gateway-backend-service/** - filters: - - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} - - RemoveResponseHeader=WWW-Authenticate - default-filters: - - RemoveResponseHeader=Expires - - RemoveRequestHeader=cookie - - RemoveRequestHeader=x-xsrf-token - - TokenRelay= - - # security config - security: - oauth2: - client: - provider: - keycloak: - issuer-uri: https://ssotest.muenchen.de/auth/realms/${spring.realm} - registration: - keycloak: - client-id: refarch-gateway - client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 - - mvc: - log-request-details: on - -hazelcast: - openshift-service-name: ${app.frontend-service} diff --git a/refarch-gateway/src/main/resources/application-local.yml b/refarch-gateway/src/main/resources/application-local.yml deleted file mode 100644 index bc050507..00000000 --- a/refarch-gateway/src/main/resources/application-local.yml +++ /dev/null @@ -1,58 +0,0 @@ -server: - port: 8082 -spring: - - # Define the local keycloak realm here - realm: - - # spring cloud gateway config - cloud: - gateway: - actuator: - verbose: - enabled: false - globalcors: - corsConfigurations: - # The cors configuration to allow frontend developers cross origin request via this api gateway - '[/**]': - allowedOrigins: - - "http://localhost:8081" - - "http://127.0.0.1:8081" - allowedMethods: "*" - allowedHeaders: "*" - allowCredentials: true - maxAge: 3600 - routes: - - id: sso - uri: https://ssodev.muenchen.de/ - predicates: - - Path=/api/sso/userinfo - filters: - - RewritePath=/api/sso/userinfo, /auth/realms/${spring.realm}/protocol/openid-connect/userinfo - - id: backend - uri: http://localhost:39146/ - predicates: - - Path=/api/refarch-gateway-backend-service/** - filters: - - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} - - RemoveResponseHeader=WWW-Authenticate - default-filters: - - RemoveResponseHeader=Expires - - RemoveRequestHeader=cookie - - RemoveRequestHeader=x-xsrf-token - - TokenRelay= - - # security config - security: - oauth2: - client: - provider: - keycloak: - issuer-uri: https://ssodev.muenchen.de/auth/realms/${spring.realm} - registration: - keycloak: - client-id: refarch-gateway - client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 - - mvc: - log-request-details: on diff --git a/refarch-gateway/src/main/resources/application-prod.yml b/refarch-gateway/src/main/resources/application-prod.yml deleted file mode 100644 index d33dc8ef..00000000 --- a/refarch-gateway/src/main/resources/application-prod.yml +++ /dev/null @@ -1,63 +0,0 @@ -app: - backend-service: - frontend-service: - -spring: - - # Define the keycloak productive realm here - realm: muenchen.de - - # spring cloud gateway config - cloud: - gateway: - actuator: - verbose: - enabled: false - globalcors: - corsConfigurations: - # The cors configuration to allow frontend developers cross origin request via this api gateway - '[/**]': - allowedOrigins: - - "http://localhost:8081" - - "http://127.0.0.1:8081" - allowedMethods: "*" - allowedHeaders: "*" - allowCredentials: true - maxAge: 3600 - routes: - - id: sso - uri: https://sso.muenchen.de/ - predicates: - - Path=/api/sso/userinfo - filters: - - RewritePath=/api/sso/userinfo, /auth/realms/${spring.realm}/protocol/openid-connect/userinfo - - id: backend - uri: http://${app.backend-service}:8080/ - predicates: - - Path=/api/refarch-gateway-backend-service/** - filters: - - RewritePath=/api/refarch-gateway-backend-service/(?.*), /$\{urlsegments} - - RemoveResponseHeader=WWW-Authenticate - default-filters: - - RemoveResponseHeader=Expires - - RemoveRequestHeader=cookie - - RemoveRequestHeader=x-xsrf-token - - TokenRelay= - - # security config - security: - oauth2: - client: - provider: - keycloak: - issuer-uri: https://sso.muenchen.de/auth/realms/${spring.realm} - registration: - keycloak: - client-id: refarch-gateway - client-secret: 0b67133e-f4e0-42f6-b05f-7b51175969e8 - - mvc: - log-request-details: false - -hazelcast: - openshift-service-name: ${app.frontend-service} From 4bd092872ab88e15e81b3963657799ac32c13d23 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 09:36:14 +0200 Subject: [PATCH 13/48] gateway update no-security syntax --- .../configuration/NoSecurityConfiguration.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java index c7797f26..81525251 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java @@ -16,16 +16,11 @@ public class NoSecurityConfiguration { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - // @formatter:off return http - .authorizeExchange() - .anyExchange().permitAll() - .and() - .cors() - .and() - .csrf().disable() + .authorizeExchange(authorizeExchangeSpec -> authorizeExchangeSpec.anyExchange().permitAll()) + .cors(corsSpec -> {}) + .csrf(ServerHttpSecurity.CsrfSpec::disable) .build(); - // @formatter:on } } From 3be35392c50e3d0ceab24e6f3eed49e4e0810305 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 09:38:45 +0200 Subject: [PATCH 14/48] gateway update security config --- .../configuration/SecurityConfiguration.java | 107 +++++++++++------- .../SpaServerCsrfTokenRequestHandler.java | 41 +++++++ 2 files changed, 108 insertions(+), 40 deletions(-) create mode 100644 refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SpaServerCsrfTokenRequestHandler.java diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java index f92089c4..28a93245 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java @@ -4,35 +4,41 @@ */ package de.muenchen.oss.refarch.gateway.configuration; -import de.muenchen.oss.refarch.gateway.filter.CsrfTokenAppendingHelperFilter; -import java.net.URI; -import java.time.Duration; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; +import org.springframework.core.annotation.Order; import org.springframework.http.HttpMethod; -import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.security.config.Customizer; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.core.Authentication; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.WebFilterExchange; import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler; +import org.springframework.security.web.server.authentication.logout.HttpStatusReturningServerLogoutSuccessHandler; import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler; import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler; import org.springframework.security.web.server.csrf.CookieServerCsrfTokenRepository; -import org.springframework.security.web.server.csrf.ServerCsrfTokenRequestAttributeHandler; import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers; import reactor.core.publisher.Mono; +import java.net.URI; +import java.time.Duration; + + @Configuration @Profile("!no-security") +@RequiredArgsConstructor public class SecurityConfiguration { private static final String LOGOUT_URL = "/logout"; private static final String LOGOUT_SUCCESS_URL = "/loggedout.html"; + private final CsrfProtectionMatcher csrfProtectionMatcher; + /** * Same lifetime as SSO Session (e.g. 10 hours). */ @@ -40,52 +46,73 @@ public class SecurityConfiguration { private long springSessionTimeoutSeconds; @Bean - public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - final CookieServerCsrfTokenRepository tokenRepository = CookieServerCsrfTokenRepository.withHttpOnlyFalse(); - // requestHandler needed for handling the raw CSRF tokens - final ServerCsrfTokenRequestAttributeHandler requestHandler = new ServerCsrfTokenRequestAttributeHandler(); + @Order(0) + public SecurityWebFilterChain clientAccessFilterChain(ServerHttpSecurity http) { + http + .securityMatcher(ServerWebExchangeMatchers.pathMatchers("/clients/**")) + .authorizeExchange(authorizeExchangeSpec -> { + authorizeExchangeSpec.pathMatchers(HttpMethod.OPTIONS, "/clients/**").permitAll() + .anyExchange().authenticated(); + }) + .cors(corsSpec -> { + }) + .oauth2ResourceServer(oauth2 -> + oauth2.jwt(Customizer.withDefaults()) + ); + return http.build(); + } - // @formatter:off + @Bean + @Order(1) + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http - .logout() - .logoutSuccessHandler(createLogoutSuccessHandler(LOGOUT_SUCCESS_URL)) - .logoutUrl(LOGOUT_URL) - .requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, LOGOUT_URL)) - .and() - .authorizeExchange() - // permitAll - .pathMatchers(HttpMethod.OPTIONS, "/api/**").permitAll() - .pathMatchers(LOGOUT_SUCCESS_URL).permitAll() - .pathMatchers("/api/*/info", - "/actuator/health", - "/actuator/info", - "/actuator/metrics").permitAll() - // only authenticated - .anyExchange().authenticated() - .and() + .logout(logoutSpec -> { + logoutSpec.logoutSuccessHandler(createLogoutSuccessHandler(LOGOUT_SUCCESS_URL)) + .logoutUrl(LOGOUT_URL) + .requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, LOGOUT_URL)); + }) + + .authorizeExchange(authorizeExchangeSpec -> { + // permitAll + authorizeExchangeSpec.pathMatchers(HttpMethod.OPTIONS, "/api/**").permitAll() + .pathMatchers(LOGOUT_SUCCESS_URL).permitAll() + .pathMatchers("/api/*/info", + "/actuator/health", + "/actuator/info", + "/actuator/metrics").permitAll() + .pathMatchers(HttpMethod.OPTIONS, "/public/**").permitAll() + .pathMatchers(HttpMethod.GET, "/public/**").permitAll() + // only authenticated + .anyExchange().authenticated(); + }) + .cors(corsSpec -> { + }) + .csrf(csrfSpec -> { /* - * The necessary subscription for csrf token attachment to {@link ServerHttpResponse} - * is done in class {@link CsrfTokenAppendingHelperFilter}. - */ - .csrf((csrf) -> csrf - .csrfTokenRepository(tokenRepository) - .csrfTokenRequestHandler(requestHandler)) - .cors() - .and() - .oauth2Login() + * Custom csrf request handler for spa and BREACH attack protection. + * https://docs.spring.io/spring-security/reference/6.1-SNAPSHOT/servlet/exploits/csrf.html#csrf-integration-javascript-spa + */ + csrfSpec.csrfTokenRequestHandler(new SpaServerCsrfTokenRequestHandler()); /* - * Set security session timeout. - */ - .authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler() { + * The necessary subscription for csrf token attachment to {@link ServerHttpResponse} + * is done in class {@link CsrfTokenAppendingHelperFilter}. + */ + csrfSpec.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse()); + csrfSpec.requireCsrfProtectionMatcher(csrfProtectionMatcher); + }) + .oauth2Login(oAuth2LoginSpec -> { + oAuth2LoginSpec.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler() { @Override public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { webFilterExchange.getExchange().getSession().subscribe( - webSession -> webSession.setMaxIdleTime(Duration.ofSeconds(springSessionTimeoutSeconds))); + webSession -> webSession.setMaxIdleTime(Duration.ofSeconds(springSessionTimeoutSeconds)) + ); return super.onAuthenticationSuccess(webFilterExchange, authentication); } }); + }); + return http.build(); - // @formatter:on } /** diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SpaServerCsrfTokenRequestHandler.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SpaServerCsrfTokenRequestHandler.java new file mode 100644 index 00000000..bc63af00 --- /dev/null +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SpaServerCsrfTokenRequestHandler.java @@ -0,0 +1,41 @@ +package de.muenchen.oss.refarch.gateway.configuration; + +import org.springframework.security.web.server.csrf.CsrfToken; +import org.springframework.security.web.server.csrf.ServerCsrfTokenRequestAttributeHandler; +import org.springframework.security.web.server.csrf.ServerCsrfTokenRequestHandler; +import org.springframework.security.web.server.csrf.XorServerCsrfTokenRequestAttributeHandler; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +public class SpaServerCsrfTokenRequestHandler extends ServerCsrfTokenRequestAttributeHandler { + private final ServerCsrfTokenRequestHandler delegate = new XorServerCsrfTokenRequestAttributeHandler(); + + @Override + public void handle(ServerWebExchange exchange, Mono csrfToken) { + /* + * Always use XorCsrfTokenRequestAttributeHandler to provide BREACH protection of + * the CsrfToken when it is rendered in the response body. + */ + this.delegate.handle(exchange, csrfToken); + } + + @Override + public Mono resolveCsrfTokenValue(ServerWebExchange exchange, CsrfToken csrfToken) { + /* + * If the request contains a request header, use CsrfTokenRequestAttributeHandler + * to resolve the CsrfToken. This applies when a single-page application includes + * the header value automatically, which was obtained via a cookie containing the + * raw CsrfToken. + */ + if (exchange.getRequest().getHeaders().containsKey(csrfToken.getHeaderName())) { + return super.resolveCsrfTokenValue(exchange, csrfToken); + } + /* + * In all other cases (e.g. if the request contains a request parameter), use + * XorCsrfTokenRequestAttributeHandler to resolve the CsrfToken. This applies + * when a server-side rendered form includes the _csrf request parameter as a + * hidden input. + */ + return this.delegate.resolveCsrfTokenValue(exchange, csrfToken); + } +} From eb7c9d9a9e1a523c0e7ccdcdecf21d682440f82b Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 09:38:58 +0200 Subject: [PATCH 15/48] gateway add csrf whitelist --- .../ApiGatewayApplication.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java index cdee8b90..ad0ab25b 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java @@ -4,8 +4,11 @@ */ package de.muenchen.oss.refarch.gateway; +import de.muenchen.oss.refarch.gateway.configuration.SecurityProperties; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + /** * To do some base configuration for the non blocking client-server framework @@ -31,7 +34,8 @@ * @see https://cloud.spring.io/spring-cloud-gateway/reference/html/ */ -@SpringBootApplication(scanBasePackages = { "de.muenchen.oss.refarch.gateway" }) +@SpringBootApplication +@EnableConfigurationProperties(SecurityProperties.class) public class ApiGatewayApplication { public static void main(String[] args) { From a2837567250ced67758f0663a9be126e450490de Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 10:04:31 +0200 Subject: [PATCH 16/48] gateway fiy warnings and format files --- refarch-gateway/pom.xml | 15 ++++ .../ApiGatewayApplication.java | 31 ++++----- .../configuration/GuiConfiguration.java | 10 +-- .../NoSecurityConfiguration.java | 3 +- .../configuration/SecurityConfiguration.java | 68 +++++++++---------- .../configuration/VueCacheConfiguration.java | 3 +- .../WebSessionConfiguration.java | 11 ++- .../filter/DistributedTracingFilter.java | 6 +- .../GlobalAuthenticationErrorFilter.java | 14 ++-- .../filter/GlobalBackend5xxTo400Mapper.java | 13 ++-- ...GlobalRequestParameterPollutionFilter.java | 9 +-- .../src/main/resources/application.yml | 5 -- ...alRequestParameterPollutionFilterTest.java | 5 +- 13 files changed, 103 insertions(+), 90 deletions(-) diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index 3e2ce08f..b808dede 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -125,4 +125,19 @@ micrometer-registry-prometheus + + + + + src/main/resources + true + + + + + org.springframework.boot + spring-boot-maven-plugin + + + diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java index ad0ab25b..8761d099 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java @@ -15,24 +15,23 @@ * named Netty via properties use the properties listed in the link down below: * * @see https://projectreactor.io/docs/netty/release/api/constant-values.html - * - * As listed below, this above mentioned properties should be set before the application - * startup: - * - *

    - *
  • As command line argument: e.g. -Dreactor.netty.pool.maxConnections=1000. - *
  • As environmental property in Openshift: e.g. with key REACTOR_NETTY_POOL_MAXCONNECTIONS - * and value 1000. - *
  • As programatically set property before call {@link SpringApplication#run} in - * {@link ApiGatewayApplication#main}: e.g. - * System.setProperty("reactor.netty.pool.maxConnections", "1000");. - *
- * - * To get more information about Spring Cloud Gateway visit the following link: + * "https://projectreactor.io/docs/netty/release/api/constant-values.html">https://projectreactor.io/docs/netty/release/api/constant-values.html + *

+ * As listed below, this above mentioned properties should be set before the application + * startup: * + *

    + *
  • As command line argument: e.g. -Dreactor.netty.pool.maxConnections=1000. + *
  • As environmental property in Openshift: e.g. with key REACTOR_NETTY_POOL_MAXCONNECTIONS + * and value 1000. + *
  • As programatically set property before call {@link SpringApplication#run} in + * {@link ApiGatewayApplication#main}: e.g. + * System.setProperty("reactor.netty.pool.maxConnections", "1000");. + *
+ *

+ * To get more information about Spring Cloud Gateway visit the following link: * @see https://cloud.spring.io/spring-cloud-gateway/reference/html/ + * "https://cloud.spring.io/spring-cloud-gateway/reference/html/">https://cloud.spring.io/spring-cloud-gateway/reference/html/ */ @SpringBootApplication @EnableConfigurationProperties(SecurityProperties.class) diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java index 64d18ed1..6068a561 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java @@ -4,10 +4,6 @@ */ package de.muenchen.oss.refarch.gateway.configuration; -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RouterFunctions.route; -import static org.springframework.web.reactive.function.server.ServerResponse.ok; - import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -17,9 +13,13 @@ import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.ServerResponse; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + /** * This class supplies the endpoint which provides the gui. - * + *

* The default path to the gui entry point is "classpath:/static/index.html". */ @Configuration diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java index 81525251..93ff102e 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java @@ -18,7 +18,8 @@ public class NoSecurityConfiguration { public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { return http .authorizeExchange(authorizeExchangeSpec -> authorizeExchangeSpec.anyExchange().permitAll()) - .cors(corsSpec -> {}) + .cors(corsSpec -> { + }) .csrf(ServerHttpSecurity.CsrfSpec::disable) .build(); } diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java index 28a93245..e1a1e3eb 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java @@ -17,7 +17,6 @@ import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.WebFilterExchange; import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler; -import org.springframework.security.web.server.authentication.logout.HttpStatusReturningServerLogoutSuccessHandler; import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler; import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler; import org.springframework.security.web.server.csrf.CookieServerCsrfTokenRepository; @@ -45,15 +44,28 @@ public class SecurityConfiguration { @Value("${spring.session.timeout:36000}") private long springSessionTimeoutSeconds; + /** + * This method creates the {@link ServerLogoutSuccessHandler} for handling a successful logout. + * The usage is necessary in {@link SecurityWebFilterChain}. + * + * @param uri to forward after an successful logout. + * @return The handler for forwarding after an succesful logout. + */ + public static ServerLogoutSuccessHandler createLogoutSuccessHandler(final String uri) { + final RedirectServerLogoutSuccessHandler successHandler = new RedirectServerLogoutSuccessHandler(); + successHandler.setLogoutSuccessUrl(URI.create(uri)); + return successHandler; + } + @Bean @Order(0) public SecurityWebFilterChain clientAccessFilterChain(ServerHttpSecurity http) { http .securityMatcher(ServerWebExchangeMatchers.pathMatchers("/clients/**")) - .authorizeExchange(authorizeExchangeSpec -> { - authorizeExchangeSpec.pathMatchers(HttpMethod.OPTIONS, "/clients/**").permitAll() - .anyExchange().authenticated(); - }) + .authorizeExchange(authorizeExchangeSpec -> + authorizeExchangeSpec + .pathMatchers(HttpMethod.OPTIONS, "/clients/**").permitAll() + .anyExchange().authenticated()) .cors(corsSpec -> { }) .oauth2ResourceServer(oauth2 -> @@ -66,12 +78,11 @@ public SecurityWebFilterChain clientAccessFilterChain(ServerHttpSecurity http) { @Order(1) public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http - .logout(logoutSpec -> { - logoutSpec.logoutSuccessHandler(createLogoutSuccessHandler(LOGOUT_SUCCESS_URL)) - .logoutUrl(LOGOUT_URL) - .requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, LOGOUT_URL)); - }) - + .logout(logoutSpec -> + logoutSpec.logoutSuccessHandler(createLogoutSuccessHandler(LOGOUT_SUCCESS_URL)) + .logoutUrl(LOGOUT_URL) + .requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, LOGOUT_URL)) + ) .authorizeExchange(authorizeExchangeSpec -> { // permitAll authorizeExchangeSpec.pathMatchers(HttpMethod.OPTIONS, "/api/**").permitAll() @@ -100,32 +111,19 @@ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) csrfSpec.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse()); csrfSpec.requireCsrfProtectionMatcher(csrfProtectionMatcher); }) - .oauth2Login(oAuth2LoginSpec -> { - oAuth2LoginSpec.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler() { - @Override - public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { - webFilterExchange.getExchange().getSession().subscribe( - webSession -> webSession.setMaxIdleTime(Duration.ofSeconds(springSessionTimeoutSeconds)) - ); - return super.onAuthenticationSuccess(webFilterExchange, authentication); - } - }); - }); + .oauth2Login(oAuth2LoginSpec -> + oAuth2LoginSpec.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler() { + @Override + public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { + webFilterExchange.getExchange().getSession().subscribe( + webSession -> webSession.setMaxIdleTime(Duration.ofSeconds(springSessionTimeoutSeconds)) + ); + return super.onAuthenticationSuccess(webFilterExchange, authentication); + } + }) + ); return http.build(); } - /** - * This method creates the {@link ServerLogoutSuccessHandler} for handling a successful logout. - * The usage is necessary in {@link SecurityWebFilterChain}. - * - * @param uri to forward after an successful logout. - * @return The handler for forwarding after an succesful logout. - */ - public static ServerLogoutSuccessHandler createLogoutSuccessHandler(final String uri) { - final RedirectServerLogoutSuccessHandler successHandler = new RedirectServerLogoutSuccessHandler(); - successHandler.setLogoutSuccessUrl(URI.create(uri)); - return successHandler; - } - } diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java index 369de70e..d08eb7a2 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java @@ -4,12 +4,13 @@ */ package de.muenchen.oss.refarch.gateway.configuration; -import java.time.Duration; import org.springframework.context.annotation.Configuration; import org.springframework.http.CacheControl; import org.springframework.web.reactive.config.ResourceHandlerRegistry; import org.springframework.web.reactive.config.WebFluxConfigurer; +import java.time.Duration; + /** * VueCacheConfigurer setzt Cache Header für die von Vue gebauten Resourcen. Sie enthalten im Namen * ein Hash, deswegen sollte das Caching hier keine Probleme machen. diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java index 76e0cc57..8155bdc5 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java @@ -26,7 +26,6 @@ /** * This class configures Hazelcast as the ReactiveSessionRepository. - * */ @Configuration @EnableSpringWebSession @@ -56,9 +55,9 @@ public ReactiveSessionRepository reactiveSessionRepository(@Qualifie } @Bean - @Profile({ "local", "test" }) + @Profile({"local", "test"}) public Config localConfig(@Value( - "${spring.session.timeout}" + "${spring.session.timeout}" ) int timeout) { final var hazelcastConfig = new Config(); hazelcastConfig.setInstanceName(hazelcastInstanceName); @@ -78,7 +77,7 @@ public Config localConfig(@Value( } @Bean - @Profile({ "dev", "kon", "prod" }) + @Profile({"dev", "kon", "prod"}) public Config config(@Value("${spring.session.timeout}") int timeout) { final var hazelcastConfig = new Config(); hazelcastConfig.setInstanceName(hazelcastInstanceName); @@ -98,12 +97,12 @@ public Config config(@Value("${spring.session.timeout}") int timeout) { /** * Adds the session timeout in seconds to the hazelcast configuration. - * + *

* Since we are creating the map it's important to evict sessions * by setting a reasonable value for time to live. * * @param hazelcastConfig to add the timeout. - * @param sessionTimeout for security session. + * @param sessionTimeout for security session. */ private void addSessionTimeoutToHazelcastConfig(final Config hazelcastConfig, final int sessionTimeout) { final var sessionConfig = new MapConfig(); diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java index 047e3ad0..39292216 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java @@ -34,13 +34,13 @@ public class DistributedTracingFilter implements WebFilter { * to each response in {@link ServerWebExchange}. * * @param serverWebExchange the current server exchange without zipkin headers - * @param webFilterChain provides a way to delegate to the next filter + * @param webFilterChain provides a way to delegate to the next filter * @return {@code Mono} to indicate when request processing for adding zipkin headers is - * complete + * complete */ @Override public Mono filter(ServerWebExchange serverWebExchange, - WebFilterChain webFilterChain) { + WebFilterChain webFilterChain) { ServerHttpResponse response = serverWebExchange.getResponse(); response.beforeCommit(() -> { var span = tracer.currentSpan(); diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java index dbe9be72..c576bf60 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java @@ -4,8 +4,9 @@ */ package de.muenchen.oss.refarch.gateway.filter; -import org.apache.commons.codec.binary.StringUtils; +import lombok.NonNull; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.StringUtils; import org.apache.commons.lang3.ObjectUtils; import org.reactivestreams.Publisher; import org.springframework.cloud.gateway.filter.GatewayFilterChain; @@ -35,9 +36,8 @@ @Slf4j public class GlobalAuthenticationErrorFilter implements GlobalFilter, Ordered { - private static final String GENERIC_AUTHENTICATION_ERROR = "{ \"status\":401, \"error\":\"Authentication Error\" }"; - public static final int ORDER_GLOBAL_FILTER = -3; + private static final String GENERIC_AUTHENTICATION_ERROR = "{ \"status\":401, \"error\":\"Authentication Error\" }"; @Override public int getOrder() { @@ -65,9 +65,10 @@ public Mono filter(final ServerWebExchange exchange, final GatewayFilterCh * the body given by the parameter. */ @Override - public Mono writeWith(Publisher body) { + @NonNull + public Mono writeWith(@NonNull Publisher body) { final HttpStatusCode responseHttpStatus = getDelegate().getStatusCode(); - if (body instanceof Flux && responseHttpStatus.equals(httpStatus)) { + if (body instanceof Flux flux && responseHttpStatus.equals(httpStatus)) { final DataBufferFactory dataBufferFactory = response.bufferFactory(); final DataBuffer newDataBuffer = dataBufferFactory.wrap( StringUtils.getBytesUtf8(ObjectUtils.defaultIfNull(newResponseBody, EMPTY_JSON_OBJECT))); @@ -75,7 +76,6 @@ public Mono writeWith(Publisher body) { log.debug("Response from upstream {} get new response body: {}", httpStatus, newResponseBody); getDelegate().getHeaders().setContentLength(newDataBuffer.readableByteCount()); getDelegate().getHeaders().setContentType(MediaType.APPLICATION_JSON); - Flux flux = (Flux) body; return super.writeWith(flux.buffer().map( // replace old body represented by dataBuffer by the new one @@ -88,6 +88,6 @@ public Mono writeWith(Publisher body) { final ServerWebExchange swe = exchange.mutate().response(decoratedResponse).build(); return chain.filter(swe); - }; + } } diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java index fa8cf6c4..13e443d1 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java @@ -4,7 +4,7 @@ */ package de.muenchen.oss.refarch.gateway.filter; -import java.nio.charset.StandardCharsets; +import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.StringUtils; import org.apache.commons.lang3.ObjectUtils; @@ -28,6 +28,8 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.nio.charset.StandardCharsets; + /** * This {@link GlobalFilter} replaces the body by a generic error body, when a server responses * with a {@link HttpStatus#INTERNAL_SERVER_ERROR}. @@ -37,16 +39,14 @@ public class GlobalBackend5xxTo400Mapper implements GlobalFilter, Ordered { public static final int ORDER_GLOBAL_FILTER = -3; - + static final String GENERIC_ERROR_400 = "{ \"status\":400, \"error\":\"Bad Request\" }"; + static final String GENERIC_ERROR_500 = "{ \"status\":500, \"error\":\"Internal Server Error\" }"; /** * Variable entscheidet, ob alle 5xx Fehler auf 400 gemappt werden sollen. **/ @Value("${config.map5xxto400: true}") private boolean MAP_5xx_TO_400; - static final String GENERIC_ERROR_400 = "{ \"status\":400, \"error\":\"Bad Request\" }"; - static final String GENERIC_ERROR_500 = "{ \"status\":500, \"error\":\"Internal Server Error\" }"; - @Override public int getOrder() { return ORDER_GLOBAL_FILTER; @@ -62,7 +62,8 @@ public Mono filter(final ServerWebExchange exchange, final GatewayFilterCh final ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) { @Override - public Mono writeWith(Publisher body) { + @NonNull + public Mono writeWith(@NonNull Publisher body) { final HttpStatusCode responseHttpStatus = getDelegate().getStatusCode(); final Flux flux = (Flux) body; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java index 5078a9de..41e06cb4 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java @@ -5,8 +5,6 @@ package de.muenchen.oss.refarch.gateway.filter; import de.muenchen.oss.refarch.gateway.exception.ParameterPollutionException; -import java.util.List; -import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; @@ -20,9 +18,12 @@ import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import java.util.List; +import java.util.Map; + /** * This {@link GlobalFilter} is used to detect and to fend off a parameter pollution attack. - * + *

* Within a {@link HttpRequest} each request parameter should only exist once. * This check is necessary to avoid e.g. SQL injection split over multiple request parameters with * the same name. @@ -42,7 +43,7 @@ public int getOrder() { * See {@link GlobalFilter#filter(ServerWebExchange, GatewayFilterChain)} * * @throws ParameterPollutionException is throw when a request parameter exists multiple times. - * The exception represents a http response with status {@link HttpStatus#BAD_REQUEST}. + * The exception represents a http response with status {@link HttpStatus#BAD_REQUEST}. */ @Override public Mono filter(final ServerWebExchange exchange, final GatewayFilterChain chain) throws ParameterPollutionException { diff --git a/refarch-gateway/src/main/resources/application.yml b/refarch-gateway/src/main/resources/application.yml index 90f98c0c..bbfc3f0d 100644 --- a/refarch-gateway/src/main/resources/application.yml +++ b/refarch-gateway/src/main/resources/application.yml @@ -8,11 +8,6 @@ spring: indent-output: on session: timeout: 1800 # in seconds; Goal: same lifetime as SSO Session, actual: 30 minutes - zipkin: - enabled: false - sleuth: - reactor: - instrumentation-type: decorate_on_each # https://github.com/spring-cloud/spring-cloud-gateway/pull/2106 security: oauth2: resourceserver: diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java index 0dce9167..60ac71e8 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java @@ -16,6 +16,7 @@ import org.springframework.test.web.reactive.server.WebTestClient; import java.nio.charset.StandardCharsets; +import java.util.Objects; import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -40,7 +41,9 @@ void parameterPollutionAttack() { .expectStatus() .isEqualTo(HttpStatus.BAD_REQUEST) .expectBody() - .consumeWith(responseBody -> jsonResponseBody.append(new String(responseBody.getResponseBody(), StandardCharsets.UTF_8))); + .consumeWith(responseBody -> jsonResponseBody.append( + new String(Objects.requireNonNull(responseBody.getResponseBody()), StandardCharsets.UTF_8) + )); assertTrue(jsonResponseBody.toString().contains("\"message\" : \"parameter pollution\"")); } From 96563f194464d6eb77c587f2a07954fd6831db74 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 10:21:29 +0200 Subject: [PATCH 17/48] update ci --- .github/workflows/{build.yaml => dependency_compliance.yaml} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename .github/workflows/{build.yaml => dependency_compliance.yaml} (91%) diff --git a/.github/workflows/build.yaml b/.github/workflows/dependency_compliance.yaml similarity index 91% rename from .github/workflows/build.yaml rename to .github/workflows/dependency_compliance.yaml index 53f0e5b2..3b59a046 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/dependency_compliance.yaml @@ -1,6 +1,6 @@ -name: build and test +name: dependency-compliance -on: [push] +on: [ push ] jobs: compliance: From 75bbdb2be9e1ec54e9fc3a85fe0bda6525431d81 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 10:24:42 +0200 Subject: [PATCH 18/48] gateway init README.md --- refarch-gateway/README.md | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 refarch-gateway/README.md diff --git a/refarch-gateway/README.md b/refarch-gateway/README.md new file mode 100644 index 00000000..10680e7d --- /dev/null +++ b/refarch-gateway/README.md @@ -0,0 +1,41 @@ +# Refarch Gateway + +## Usage + +- Image: TODO +- Helm-Chart: TODO + +### Routing + +Routes are configured via environment variables as listed under [Configuration](#configuration). + +By default, routes require authentication through oAuth2 and manage the session between the client and gateway using +cookies. +The gateway then maps the session cookie to a JWT before routing it. + +Beside the default behaviour there are some special route prefixes which are handled different: + +- `/public/**`: All `OPTIONS` and `GET` requests are routed without security. +- `/clients/**`: Uses JWT for authenticating incoming requests instead of session cookies. + +## Profiles + +| Profile | Description | +|---------------|---------------------------------------------------------------------------------------------------| +| `no-security` | Disables complete security like authentication, authorization, csrf etc. Routing works as normal. | + +## Configuration + +| Var | Description | Example | +|----------------------------------------------------------|----------------------------------------------------|-------------------------------------------------------------------------| +| `SSO_ISSUER_URL` | Url of the oAuth2 server used for authentication. | `https://sso.muenchen.de/auth/realms/muenchen.de` | +| `SSO_CLIENT_ID` | OAuth2 client id used for authentication. | | +| `SSO_CLIENT_SECRET` | OAuth2 client secret used for authentication. | | +| `SPRING_CLOUD_GATEWAY_ROUTES__ID` | Id of a route definition. | `backend` | +| `SPRING_CLOUD_GATEWAY_ROUTES__URI` | The uri to route to if this route matches. | `http://backend-service:8080/` | +| `SPRING_CLOUD_GATEWAY_ROUTES__PREDICATES_` | Route predicates i.e. matcher. | `Path=/api/backend-service/**` | +| `SPRING_CLOUD_GATEWAY_ROUTES__FILTERS_` | List of filters applied to the route. | `RewritePath=/api/backend-service/(?.*), /$\{urlsegments}` | +| `ALLOWED_ORIGINS_PUBLIC` (optional) | List of urls allowed as origin for public routes. | `https://*.muenchen.de,http://localhost:*` | +| `ALLOWED_ORIGINS_CLIENTS` (optional) | List of urls allowed as origin for clients routes. | `https://*.muenchen.de,http://localhost:*` | +| `REFARCH_SECURITY_CSRFWHITELISTED_` (optional) | List of routes to disable csrf protection for. | `/example/**` | +| `INFO_APPSWITCHER_URL` (optional) | App switcher url for usage in refarch frontend. | `https://appswitcher.muenchen.de` | From 397bc9361f85cc4bce9f1751962d830e2088d991 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 12:23:56 +0200 Subject: [PATCH 19/48] init ci --- .github/workflows/build.yaml | 13 ++++++ .github/workflows/maven.yaml | 79 ++++++++++++++++++++++++++++++++++ .github/workflows/release.yaml | 24 +++++++++++ 3 files changed, 116 insertions(+) create mode 100644 .github/workflows/build.yaml create mode 100644 .github/workflows/maven.yaml create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 00000000..89dfb126 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,13 @@ +on: + pull_request: + push: + branches: + - main + +jobs: + build: + uses: ./.github/workflows/maven.yaml + with: + build-images: ${{ github.ref_name == 'main' }} + release-version: dev + secrets: inherit diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml new file mode 100644 index 00000000..100c9591 --- /dev/null +++ b/.github/workflows/maven.yaml @@ -0,0 +1,79 @@ +env: + JAVA_VERSION: 17 + REGISTRY: ghcr.io + TZ: Europe/Berlin + +on: + workflow_call: + inputs: + snapshot-release: + description: 'Snapshot release?' + type: boolean + default: true + build-images: + description: 'Build and push images?' + type: boolean + default: false + release-version: + description: 'Release version' + type: string + required: false + +jobs: + release: + runs-on: ubuntu-latest + steps: + # Checkout source code, set up Java, etc. Then... + - name: Checkout code + uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: "temurin" + cache: "maven" + - name: Maven build + run: mvn --batch-mode clean install + - name: "Upload Artifact" + uses: actions/upload-artifact@v4 + with: + name: target + path: "**/target" + retention-days: 5 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build-image: + if: inputs.build-images == true + needs: release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Download a single artifact + uses: actions/download-artifact@v4 + with: + name: target + - name: Login to Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # refarch-gateway + - name: Extract metadata (tags, labels) for gateway image + id: gateway_meta + uses: docker/metadata-action@v5 + with: + images: "${{ env.REGISTRY }}/${{ github.repository }}/refarch-gateway" + tags: | + type=raw,value=${{ inputs.release-version }} + type=raw,value=latest,enable=${{ inputs.snapshot-release == false }} + - name: Build and push gateway image + uses: docker/build-push-action@v4 + with: + context: ./refarch-gateway + push: true + tags: ${{ steps.gateway_meta.outputs.tags }} + labels: ${{ steps.gateway_meta.outputs.labels }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..5615e269 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,24 @@ +on: + workflow_dispatch: + inputs: + snapshot-release: + description: 'Snapshot release?' + type: boolean + default: true + build-images: + description: 'Build and push images?' + type: boolean + default: false + release-version: + description: 'Release version' + type: string + required: false + +jobs: + build: + uses: ./.github/workflows/maven.yaml + with: + snapshot-release: ${{ inputs.snapshot-release != false }} + build-images: true + release-version: ${{ inputs.release-version }} + secrets: inherit From fcc4abace0469e3cc3595e1468b0b03bdf5be838 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 12:25:31 +0200 Subject: [PATCH 20/48] init ci --- .github/workflows/build.yaml | 4 +++- .github/workflows/maven.yaml | 2 +- .github/workflows/release.yaml | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 89dfb126..7bc4e489 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,3 +1,5 @@ +name: build + on: pull_request: push: @@ -5,7 +7,7 @@ on: - main jobs: - build: + maven: uses: ./.github/workflows/maven.yaml with: build-images: ${{ github.ref_name == 'main' }} diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index 100c9591..f1bf4060 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -20,7 +20,7 @@ on: required: false jobs: - release: + build-maven: runs-on: ubuntu-latest steps: # Checkout source code, set up Java, etc. Then... diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5615e269..c2c2e3bc 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,3 +1,5 @@ +name: release + on: workflow_dispatch: inputs: From e471c62d93d988df43959a7e4f49c110e69b75cb Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 12:27:55 +0200 Subject: [PATCH 21/48] init ci --- .github/workflows/build.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7bc4e489..d752ac77 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -3,8 +3,6 @@ name: build on: pull_request: push: - branches: - - main jobs: maven: From 8ab10545d26be3e74f9fe271ee0fdc8db80a7094 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 12:39:45 +0200 Subject: [PATCH 22/48] Revert "init ci" This reverts commit e471c62d93d988df43959a7e4f49c110e69b75cb. --- .github/workflows/build.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d752ac77..7bc4e489 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -3,6 +3,8 @@ name: build on: pull_request: push: + branches: + - main jobs: maven: From e35e2dc0749c18b7c5431c0b51cb6ff33f6f6183 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 13:15:07 +0200 Subject: [PATCH 23/48] updaten maven version enforce --- .github/workflows/maven.yaml | 1 - pom.xml | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index f1bf4060..e8d040e8 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -23,7 +23,6 @@ jobs: build-maven: runs-on: ubuntu-latest steps: - # Checkout source code, set up Java, etc. Then... - name: Checkout code uses: actions/checkout@v4 - name: Set up JDK diff --git a/pom.xml b/pom.xml index fc8eea33..23ff09fd 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 @@ -216,7 +216,7 @@ ${java.version} - 3.9.0 + [3.8,) From c486b782f4ca1e82bfc6e33695e5f789e72e8154 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 13:58:09 +0200 Subject: [PATCH 24/48] ci use github dependency review --- .github/workflows/dependency_compliance.yaml | 19 ------------------- .github/workflows/dependency_review.yaml | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 19 deletions(-) delete mode 100644 .github/workflows/dependency_compliance.yaml create mode 100644 .github/workflows/dependency_review.yaml diff --git a/.github/workflows/dependency_compliance.yaml b/.github/workflows/dependency_compliance.yaml deleted file mode 100644 index 3b59a046..00000000 --- a/.github/workflows/dependency_compliance.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: dependency-compliance - -on: [ push ] - -jobs: - compliance: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Advance Security Policy as Code - uses: advanced-security/policy-as-code@v2.7.2 - with: - policy: it-at-m/policy-as-code - policy-path: default.yaml - token: ${{ secrets.GITHUB_TOKEN }} - argvs: "--disable-dependabot --disable-secret-scanning --disable-code-scanning --display" diff --git a/.github/workflows/dependency_review.yaml b/.github/workflows/dependency_review.yaml new file mode 100644 index 00000000..56feaa13 --- /dev/null +++ b/.github/workflows/dependency_review.yaml @@ -0,0 +1,17 @@ +name: dependency-review + +on: + pull_request: + branches: + - main + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Dependency Review + uses: actions/dependency-review-action@v4 + with: + config-file: it-at-m/.github/workflow-configs/dependency_review.yaml@main From c975fd1f7a2f58cd4a92125b63e7b56ef35e0bff Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 5 Jul 2024 14:29:37 +0200 Subject: [PATCH 25/48] init README.md --- README.md | 59 +++++++++++-------------------------------------------- 1 file changed, 11 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 7bdf9b82..5318b025 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,23 @@ -## Customize this file after creating the new REPO and remove this lines. -What to adjust: -* Add the your project or repo name direct under the logo. -* Add a short and long desciption. -* Add links for your final repo to report a bug or request a feature. -* Add list of used technologies. -* If you have, add a roadmap or remove this section. -* Fill up the section for set up and documentation. - * Start in this file only with documentation and link to the docs folder. -* Add more project shields. Use [shields.io](https://shields.io/) with style `for-the-badge`. - -## ------- end to remove ------- - - -# repo or project name +# Refarch [![Made with love by it@M][made-with-love-shield]][itm-opensource] -*Add a description from your project here.* +Collection of different reference architecture (Refarch) components developed by it@M. +## Usage -### Built With +The usage of the different components is described in their corresponding README.md -The documentation project is built with technologies we use in our projects: - -* *write here the list of used technologies* - -## Roadmap - -*if you have a ROADMAP for your project add this here* - - -See the [open issues](#) for a full list of proposed features (and known issues). - - -## Set up -*how can i start and fly this project* - -## Documentation -*what insights do you have to tell* - -```mermaid -graph TD; - A-->B; - A-->C; - B-->D; - C-->D; -``` - -use [diagrams](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams). +- [refarch-gateway](./refarch-gateway/README.md) ## Contributing -Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. +Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any +contributions you make are **greatly appreciated**. -If you have a suggestion that would make this better, please open an issue with the tag "enhancement", fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". +If you have a suggestion that would make this better, please open an issue with the tag "enhancement", fork the repo and +create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again! 1. Open an issue with the tag "enhancement" @@ -66,16 +29,16 @@ Don't forget to give the project a star! Thanks again! More about this in the [CODE_OF_CONDUCT](/CODE_OF_CONDUCT.md) file. - ## License Distributed under the MIT License. See [LICENSE](LICENSE) file for more information. - ## Contact it@M - opensource@muenchen.de + [made-with-love-shield]: https://img.shields.io/badge/made%20with%20%E2%9D%A4%20by-it%40M-yellow?style=for-the-badge + [itm-opensource]: https://opensource.muenchen.de/ From ed30b6ee81aa4b91aae53764cd42c526de0b3e8e Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:13:53 +0200 Subject: [PATCH 26/48] ci github dependency review run for all prs --- .github/workflows/dependency_review.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/dependency_review.yaml b/.github/workflows/dependency_review.yaml index 56feaa13..273bef70 100644 --- a/.github/workflows/dependency_review.yaml +++ b/.github/workflows/dependency_review.yaml @@ -2,8 +2,6 @@ name: dependency-review on: pull_request: - branches: - - main jobs: dependency-review: From 5801c1b2e9db5163ee4ae01d0d58d63f47072b78 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:22:25 +0200 Subject: [PATCH 27/48] ci maven build refactor token usage --- .github/workflows/maven.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index e8d040e8..e8d5ea3d 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -39,8 +39,6 @@ jobs: name: target path: "**/target" retention-days: 5 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} build-image: if: inputs.build-images == true From 9d9e72e92b36bb43bdc6a493996cd377efebb5cb Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:29:01 +0200 Subject: [PATCH 28/48] Revert "init ci" This reverts commit fcc4abace0469e3cc3595e1468b0b03bdf5be838. --- .github/workflows/build.yaml | 4 +--- .github/workflows/maven.yaml | 2 +- .github/workflows/release.yaml | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7bc4e489..89dfb126 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,5 +1,3 @@ -name: build - on: pull_request: push: @@ -7,7 +5,7 @@ on: - main jobs: - maven: + build: uses: ./.github/workflows/maven.yaml with: build-images: ${{ github.ref_name == 'main' }} diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index e8d5ea3d..f38ebe87 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -20,7 +20,7 @@ on: required: false jobs: - build-maven: + release: runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c2c2e3bc..5615e269 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,5 +1,3 @@ -name: release - on: workflow_dispatch: inputs: From 76d976a1cc35f62c31e17a263adac4ce98e922c5 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:30:22 +0200 Subject: [PATCH 29/48] ci fix naming --- .github/workflows/build.yaml | 2 ++ .github/workflows/release.yaml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 89dfb126..62575314 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,3 +1,5 @@ +name: build + on: pull_request: push: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5615e269..c2c2e3bc 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,3 +1,5 @@ +name: release + on: workflow_dispatch: inputs: From e6e56c6c9991a4525533ceb51452af11ff8c0705 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:31:31 +0200 Subject: [PATCH 30/48] ci fix naming --- .github/workflows/maven.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index f38ebe87..e8d5ea3d 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -20,7 +20,7 @@ on: required: false jobs: - release: + build-maven: runs-on: ubuntu-latest steps: - name: Checkout code From 6d4b0e8d53433e892e26e1718cf6805d44ef4be2 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:33:00 +0200 Subject: [PATCH 31/48] ci fix naming --- .github/workflows/maven.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index e8d5ea3d..d7b24c0a 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -20,7 +20,7 @@ on: required: false jobs: - build-maven: + build: runs-on: ubuntu-latest steps: - name: Checkout code From 80245c5b7ffc48e417e0f5fc729587a53fb67af4 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:34:28 +0200 Subject: [PATCH 32/48] ci fix naming --- .github/workflows/build.yaml | 2 +- .github/workflows/maven.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 62575314..7bc4e489 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -7,7 +7,7 @@ on: - main jobs: - build: + maven: uses: ./.github/workflows/maven.yaml with: build-images: ${{ github.ref_name == 'main' }} diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index d7b24c0a..f38ebe87 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -20,7 +20,7 @@ on: required: false jobs: - build: + release: runs-on: ubuntu-latest steps: - name: Checkout code From 66f5de5b9a0858a17b1cde9db646a5048c4969f7 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:36:59 +0200 Subject: [PATCH 33/48] ci maven update names --- .github/workflows/maven.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index f38ebe87..950d3c5c 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -33,7 +33,7 @@ jobs: cache: "maven" - name: Maven build run: mvn --batch-mode clean install - - name: "Upload Artifact" + - name: "Upload target artifacts" uses: actions/upload-artifact@v4 with: name: target @@ -47,7 +47,7 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 - - name: Download a single artifact + - name: Download target artifacts uses: actions/download-artifact@v4 with: name: target From 532d8c665462360e7c25c180db9a570ede3f5b2c Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:38:42 +0200 Subject: [PATCH 34/48] ci maven rename --- .github/workflows/maven.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index 950d3c5c..d5b28a6a 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -20,7 +20,7 @@ on: required: false jobs: - release: + build-maven: runs-on: ubuntu-latest steps: - name: Checkout code From 255aa1c5e26868d73e7a2dacc05ca2251e6f61ac Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 08:41:26 +0200 Subject: [PATCH 35/48] ci maven rename --- .github/workflows/maven.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index d5b28a6a..8feaccc4 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -40,9 +40,9 @@ jobs: path: "**/target" retention-days: 5 - build-image: + build-images: if: inputs.build-images == true - needs: release + needs: build-maven runs-on: ubuntu-latest steps: - name: Checkout code From c5137dbb51a94e92fd4fc94b889e2a3530c450c6 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 09:36:44 +0200 Subject: [PATCH 36/48] gateway rm frontend configurations --- .../configuration/GuiConfiguration.java | 44 ------------------- .../configuration/VueCacheConfiguration.java | 35 --------------- 2 files changed, 79 deletions(-) delete mode 100644 refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java delete mode 100644 refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java deleted file mode 100644 index 6068a561..00000000 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/GuiConfiguration.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ -package de.muenchen.oss.refarch.gateway.configuration; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.Resource; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.ServerResponse; - -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RouterFunctions.route; -import static org.springframework.web.reactive.function.server.ServerResponse.ok; - -/** - * This class supplies the endpoint which provides the gui. - *

- * The default path to the gui entry point is "classpath:/static/index.html". - */ -@Configuration -@Slf4j -public class GuiConfiguration { - - /** - * A router which returns the index.html as a resource. - * - * @param indexHtml The path to the index.html which serves as the starting point. - * @return the index.html as a resource. - */ - @Bean - public RouterFunction indexRouter( - @Value("classpath:/static/index.html") final Resource indexHtml) { - log.debug("Location gui entry point: {}", indexHtml); - return route(GET("/"), - request -> ok().contentType(MediaType.TEXT_HTML) - .bodyValue(indexHtml)); - } - -} diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java deleted file mode 100644 index d08eb7a2..00000000 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/VueCacheConfiguration.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ -package de.muenchen.oss.refarch.gateway.configuration; - -import org.springframework.context.annotation.Configuration; -import org.springframework.http.CacheControl; -import org.springframework.web.reactive.config.ResourceHandlerRegistry; -import org.springframework.web.reactive.config.WebFluxConfigurer; - -import java.time.Duration; - -/** - * VueCacheConfigurer setzt Cache Header für die von Vue gebauten Resourcen. Sie enthalten im Namen - * ein Hash, deswegen sollte das Caching hier keine Probleme machen. - */ -@Configuration -public class VueCacheConfiguration implements WebFluxConfigurer { - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/js/**") - .addResourceLocations("classpath:/static/js/") - .setCacheControl(CacheControl.maxAge(Duration.ofDays(30))); - registry.addResourceHandler("/css/**") - .addResourceLocations("classpath:/static/css/") - .setCacheControl(CacheControl.maxAge(Duration.ofDays(30))); - registry.addResourceHandler("/fonts/**") - .addResourceLocations("classpath:/static/fonts/") - .setCacheControl(CacheControl.maxAge(Duration.ofDays(30))); - registry.addResourceHandler("/img/**") - .addResourceLocations("classpath:/static/img/") - .setCacheControl(CacheControl.maxAge(Duration.ofDays(30))); - } -} From 9ebd1b44fc8e7a4805ca9c44e572193ef3e4422c Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 12:37:04 +0200 Subject: [PATCH 37/48] dependencies use spring boot 3.3.1 and cloud 2023.0.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 23ff09fd..a0c36397 100644 --- a/pom.xml +++ b/pom.xml @@ -20,8 +20,8 @@ 0.2.0 1.5.5.Final - 3.2.4 - 2023.0.1 + 3.3.1 + 2023.0.2 From a6f3e7db609d31504cec2d2d85416338a0d878d3 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 12:37:23 +0200 Subject: [PATCH 38/48] ci use matrix for image build --- .github/workflows/maven.yaml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index 8feaccc4..afa9b3cf 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -44,6 +44,11 @@ jobs: if: inputs.build-images == true needs: build-maven runs-on: ubuntu-latest + strategy: + matrix: + include: + - name: refarch-gateway + path: ./refarch-gateway steps: - name: Checkout code uses: actions/checkout@v4 @@ -57,20 +62,18 @@ jobs: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - # refarch-gateway - - name: Extract metadata (tags, labels) for gateway image + - name: Extract metadata (tags, labels) for image id: gateway_meta uses: docker/metadata-action@v5 with: - images: "${{ env.REGISTRY }}/${{ github.repository }}/refarch-gateway" + images: "${{ env.REGISTRY }}/${{ github.repository }}/${{ matrix.name }}" tags: | type=raw,value=${{ inputs.release-version }} type=raw,value=latest,enable=${{ inputs.snapshot-release == false }} - - name: Build and push gateway image + - name: Build and push image uses: docker/build-push-action@v4 with: - context: ./refarch-gateway + context: ${{ matrix.path }} push: true tags: ${{ steps.gateway_meta.outputs.tags }} labels: ${{ steps.gateway_meta.outputs.labels }} From 97ced8d2514e72270b6fddc2be3cfe680ec5f6ed Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 13:26:55 +0200 Subject: [PATCH 39/48] ci use matrix for image build --- .github/workflows/maven.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index afa9b3cf..8a0a90b2 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -63,7 +63,7 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata (tags, labels) for image - id: gateway_meta + id: meta uses: docker/metadata-action@v5 with: images: "${{ env.REGISTRY }}/${{ github.repository }}/${{ matrix.name }}" @@ -75,5 +75,5 @@ jobs: with: context: ${{ matrix.path }} push: true - tags: ${{ steps.gateway_meta.outputs.tags }} - labels: ${{ steps.gateway_meta.outputs.labels }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} From 5afb3e30787a3067e23890cae791a48cdcbe252b Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 13:27:54 +0200 Subject: [PATCH 40/48] ci add release logic --- .github/workflows/maven.yaml | 14 ++++++++++++++ .github/workflows/release.yaml | 22 +++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index 8a0a90b2..037005eb 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -18,6 +18,12 @@ on: description: 'Release version' type: string required: false + default: "X.Y.Z" + next-version: + description: "Next version to use after release." + type: string + required: false + default: "X.Y.Z-SNAPSHOT" jobs: build-maven: @@ -32,7 +38,15 @@ jobs: distribution: "temurin" cache: "maven" - name: Maven build + if: ${{ inputs.snapshot-release != false }} run: mvn --batch-mode clean install + - name: Maven release + if: ${{ inputs.snapshot-release == false }} + run: | + git config --global user.email "github-actions@github.com" + git config --global user.name "GitHub Actions" + mvn release:prepare -f ./pom.xml -B -DreleaseVersion=${{ inputs.release-version }} -DdevelopmentVersion=${{ inputs.next-version }} + mvn release:perform -f ./pom.xml -Darguments="-Dmaven.deploy.skip=true" - name: "Upload target artifacts" uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c2c2e3bc..2f17ed70 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,7 +14,13 @@ on: release-version: description: 'Release version' type: string - required: false + required: true + default: "X.Y.Z" + next-version: + description: "Next version to use after release." + type: string + required: true + default: "X.Y.Z-SNAPSHOT" jobs: build: @@ -24,3 +30,17 @@ jobs: build-images: true release-version: ${{ inputs.release-version }} secrets: inherit + + create-github-release: + if: ${{ inputs.snapshot-release == false }} + needs: build + runs-on: ubuntu-latest + steps: + - name: Create GitHub Release + id: create_release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ github.event.inputs.release-version }} + draft: false + prerelease: false + generate_release_notes: false From adfebadba376dfe665c64f46c9448aeb542e7910 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 13:34:41 +0200 Subject: [PATCH 41/48] rm duplicate .gitignore --- refarch-gateway/.gitignore | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 refarch-gateway/.gitignore diff --git a/refarch-gateway/.gitignore b/refarch-gateway/.gitignore deleted file mode 100644 index b547ab07..00000000 --- a/refarch-gateway/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -# Covers Maven specific -target/ -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties -!/.mvn/wrapper/maven-wrapper.jar - -# Covers Eclipse specific: -.settings/ -.classpath -.project - -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm -.idea -*.iml - -# Covers Netbeans: -**/nbproject/private/ -**/nbproject/Makefile-*.mk -**/nbproject/Package-*.bash -build/ -nbbuild/ -dist/ -nbdist/ -.nb-gradle/ - - From f9dfd08907b9792cd55c2f50ca9ac7db7325b9dc Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 8 Jul 2024 13:35:40 +0200 Subject: [PATCH 42/48] rm unneeded start scripts --- refarch-gateway/runLocal.bat | 1 - refarch-gateway/runLocal.sh | 2 -- refarch-gateway/runLocalNoSecurity.bat | 1 - refarch-gateway/runLocalNoSecurity.sh | 2 -- 4 files changed, 6 deletions(-) delete mode 100644 refarch-gateway/runLocal.bat delete mode 100644 refarch-gateway/runLocal.sh delete mode 100644 refarch-gateway/runLocalNoSecurity.bat delete mode 100644 refarch-gateway/runLocalNoSecurity.sh diff --git a/refarch-gateway/runLocal.bat b/refarch-gateway/runLocal.bat deleted file mode 100644 index 39976102..00000000 --- a/refarch-gateway/runLocal.bat +++ /dev/null @@ -1 +0,0 @@ -mvn clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=local" diff --git a/refarch-gateway/runLocal.sh b/refarch-gateway/runLocal.sh deleted file mode 100644 index 4ecb1945..00000000 --- a/refarch-gateway/runLocal.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -mvn clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=local" diff --git a/refarch-gateway/runLocalNoSecurity.bat b/refarch-gateway/runLocalNoSecurity.bat deleted file mode 100644 index e1571711..00000000 --- a/refarch-gateway/runLocalNoSecurity.bat +++ /dev/null @@ -1 +0,0 @@ -mvn clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=local,no-security" diff --git a/refarch-gateway/runLocalNoSecurity.sh b/refarch-gateway/runLocalNoSecurity.sh deleted file mode 100644 index 69535f25..00000000 --- a/refarch-gateway/runLocalNoSecurity.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -mvn clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=local,no-security" From deac417d2d2bfc14569e2c0c3e56ae7f6a54f9ae Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Tue, 9 Jul 2024 10:05:03 +0200 Subject: [PATCH 43/48] gateway rm copyright notice --- .../ApiGatewayApplication.java | 4 ---- .../configuration/NoSecurityConfiguration.java | 4 ---- .../configuration/SecurityConfiguration.java | 4 ---- .../configuration/WebSessionConfiguration.java | 4 ---- .../exception/ParameterPollutionException.java | 4 ---- .../filter/CsrfTokenAppendingHelperFilter.java | 4 ---- .../filter/DistributedTracingFilter.java | 4 ---- .../filter/GlobalAuthenticationErrorFilter.java | 4 ---- .../filter/GlobalBackend5xxTo400Mapper.java | 4 ---- .../filter/GlobalRequestParameterPollutionFilter.java | 4 ---- .../java/de.muenchen.oss.refarch.gateway/TestConstants.java | 4 ---- .../controller/ActuatorInfoEndpointTest.java | 4 ---- .../filter/CsrfTokenAppendingHelperFilterTest.java | 4 ---- .../filter/GlobalAuthenticationErrorFilterTest.java | 4 ---- .../filter/GlobalBackend5xxTo400MapperTest.java | 4 ---- .../filter/GlobalBackendErrorFilterTest.java | 6 +----- .../filter/GlobalRequestParameterPollutionFilterTest.java | 4 ---- .../route/BackendRouteTest.java | 4 ---- 18 files changed, 1 insertion(+), 73 deletions(-) diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java index 8761d099..aa410fda 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway; import de.muenchen.oss.refarch.gateway.configuration.SecurityProperties; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java index 93ff102e..9d2631d8 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/NoSecurityConfiguration.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.configuration; import org.springframework.context.annotation.Bean; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java index e1a1e3eb..024a34f3 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.configuration; import lombok.RequiredArgsConstructor; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java index 8155bdc5..bce99dd2 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.configuration; import com.hazelcast.config.Config; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/exception/ParameterPollutionException.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/exception/ParameterPollutionException.java index f93ef68c..f0d7ef6e 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/exception/ParameterPollutionException.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/exception/ParameterPollutionException.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.exception; import de.muenchen.oss.refarch.gateway.filter.GlobalRequestParameterPollutionFilter; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java index 8c5751f3..fa049939 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import de.muenchen.oss.refarch.gateway.configuration.SecurityConfiguration; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java index 39292216..6b81ab54 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import io.micrometer.tracing.Tracer; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java index c576bf60..51b9bdfd 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import lombok.NonNull; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java index 13e443d1..7503eb3c 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import lombok.NonNull; diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java index 41e06cb4..a1e2c332 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import de.muenchen.oss.refarch.gateway.exception.ParameterPollutionException; diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/TestConstants.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/TestConstants.java index 7e0bb707..44c801d9 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/TestConstants.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/TestConstants.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway; import lombok.AccessLevel; diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java index b1d9227f..bb2ff167 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.controller; import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java index 7d0ba1a4..f5286780 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java index b818b8e1..16e66df4 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import com.github.tomakehurst.wiremock.http.HttpHeader; diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java index 22b31e4f..ec9ed7f8 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import com.github.tomakehurst.wiremock.http.HttpHeader; diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java index c353bec4..4e5a8d25 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import com.github.tomakehurst.wiremock.http.HttpHeader; @@ -32,7 +28,7 @@ @AutoConfigureWireMock @TestPropertySource( properties = { - "config.map5xxto400:false", + "config.map5xxto400=false", } ) class GlobalBackendErrorFilterTest { diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java index 60ac71e8..cfc163e9 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.filter; import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java index ad7dfc9e..75764509 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java @@ -1,7 +1,3 @@ -/* - * Copyright (c): it@M - Dienstleister für Informations- und Telekommunikationstechnik - * der Landeshauptstadt München, 2024 - */ package de.muenchen.oss.refarch.gateway.route; import com.github.tomakehurst.wiremock.http.HttpHeader; From 82f1bb7bd0c5f665ed7cbdc4d78336cc3b68bbfa Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Thu, 11 Jul 2024 06:36:02 +0200 Subject: [PATCH 44/48] gateway replace hazlecast codec dependency --- refarch-gateway/pom.xml | 14 ++++---------- .../filter/GlobalAuthenticationErrorFilter.java | 5 +++-- .../filter/GlobalBackend5xxTo400Mapper.java | 5 ++--- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index b808dede..d886da98 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 @@ -20,10 +20,9 @@ refarch-gateway - 7.0.1 + 7.4 5.4.0 - 3.12.0 - 1.17.0 + 3.14.0 @@ -76,11 +75,6 @@ hazelcast-spring ${hazelcast.version} - - commons-codec - commons-codec - ${apache.commons.codec.version} - diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java index 51b9bdfd..88f7e818 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java @@ -2,7 +2,6 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.StringUtils; import org.apache.commons.lang3.ObjectUtils; import org.reactivestreams.Publisher; import org.springframework.cloud.gateway.filter.GatewayFilterChain; @@ -21,6 +20,8 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.nio.charset.StandardCharsets; + /** * This {@link GlobalFilter} replaces the body by a generic authentication error body, * when a server responses with a {@link HttpStatus#UNAUTHORIZED}. @@ -67,7 +68,7 @@ public Mono writeWith(@NonNull Publisher body) { if (body instanceof Flux flux && responseHttpStatus.equals(httpStatus)) { final DataBufferFactory dataBufferFactory = response.bufferFactory(); final DataBuffer newDataBuffer = dataBufferFactory.wrap( - StringUtils.getBytesUtf8(ObjectUtils.defaultIfNull(newResponseBody, EMPTY_JSON_OBJECT))); + ObjectUtils.defaultIfNull(newResponseBody, EMPTY_JSON_OBJECT).getBytes(StandardCharsets.UTF_8)); log.debug("Response from upstream {} get new response body: {}", httpStatus, newResponseBody); getDelegate().getHeaders().setContentLength(newDataBuffer.readableByteCount()); diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java index 7503eb3c..918f7a0b 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java @@ -2,7 +2,6 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.StringUtils; import org.apache.commons.lang3.ObjectUtils; import org.reactivestreams.Publisher; import org.springframework.beans.factory.annotation.Value; @@ -83,11 +82,11 @@ public Mono writeWith(@NonNull Publisher body) { if (MAP_5xx_TO_400) { getDelegate().setStatusCode(HttpStatus.BAD_REQUEST); newDataBuffer = dataBufferFactory.wrap( - StringUtils.getBytesUtf8(ObjectUtils.defaultIfNull(GENERIC_ERROR_400, EMPTY_JSON_OBJECT))); + ObjectUtils.defaultIfNull(GENERIC_ERROR_400, EMPTY_JSON_OBJECT).getBytes(StandardCharsets.UTF_8)); } else { getDelegate().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); newDataBuffer = dataBufferFactory.wrap( - StringUtils.getBytesUtf8(ObjectUtils.defaultIfNull(GENERIC_ERROR_500, EMPTY_JSON_OBJECT))); + ObjectUtils.defaultIfNull(GENERIC_ERROR_500, EMPTY_JSON_OBJECT).getBytes(StandardCharsets.UTF_8)); } getDelegate().getHeaders().setContentLength(newDataBuffer.readableByteCount()); From 7637091dcd2ec1ddacbd66386f1138686bb3d364 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Fri, 12 Jul 2024 11:46:30 +0200 Subject: [PATCH 45/48] gateway fix typo --- .../configuration/WebSessionConfiguration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java index bce99dd2..ddc222ec 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java @@ -83,9 +83,9 @@ public Config config(@Value("${spring.session.timeout}") int timeout) { hazelcastConfig.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); hazelcastConfig.getNetworkConfig().getJoin().getKubernetesConfig().setEnabled(true) - // explicitely configure namespace because default env lookup is not alway correct + // explicitly configure namespace because default env lookup is not always correct .setProperty("namespace", openshiftNamespace) - //If we dont set a specific name, it would call -all- services within a namespace + //If we don't set a specific name, it would call -all- services within a namespace .setProperty("service-name", openshiftServiceName); return hazelcastConfig; From 649354516e2e156da9d268ee5699cee4cfb82871 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Mon, 15 Jul 2024 14:15:41 +0200 Subject: [PATCH 46/48] refactor maven build config --- pom.xml | 369 ---------------------------------------- refarch-gateway/pom.xml | 87 +++++----- 2 files changed, 47 insertions(+), 409 deletions(-) diff --git a/pom.xml b/pom.xml index a0c36397..035e649f 100644 --- a/pom.xml +++ b/pom.xml @@ -10,20 +10,6 @@ pom refarch - - UTF-8 - 17 - 17 - 17 - - 1.18.34 - 0.2.0 - 1.5.5.Final - - 3.3.1 - 2023.0.2 - - refarch-gateway @@ -38,359 +24,4 @@ MIT - - - - org.mapstruct - mapstruct - ${org.mapstruct.version} - - - org.projectlombok - lombok - ${lombok.version} - provided - - - - - - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring.cloud.version} - pom - import - - - - - - - - - org.apache.maven.plugins - maven-clean-plugin - 3.4.0 - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - true - ${java.version} - ${java.version} - true - - - org.projectlombok - lombok - - ${lombok.version} - - - org.projectlombok - lombok-mapstruct-binding - ${lombok.mapstruct.binding.version} - - - org.mapstruct - mapstruct-processor - ${org.mapstruct.version} - - - - - -Amapstruct.defaultComponentModel=spring - - - - - - org.apache.maven.plugins - maven-resources-plugin - 3.3.1 - - UTF-8 - - - - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 - - - org.apache.maven.plugins - maven-install-plugin - 3.1.2 - - - org.apache.maven.plugins - maven-release-plugin - 3.1.0 - - false - false - release - deploy - @{project.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.1.2 - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.3.0 - - random - - - - org.apache.maven.plugins - maven-failsafe-plugin - 3.3.0 - - - run-itests - integration-test - - integration-test - verify - - - - - ${project.build.outputDirectory} - @{argLine} -Xms256m -Xmx2048m -Dfile.encoding=${project.build.sourceEncoding} - - - - org.jacoco - jacoco-maven-plugin - 0.8.12 - - - prepare-agent - - prepare-agent - - - - report - test - - report - - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.5.0 - - - enforce-maven - - enforce - - - - - ${java.version} - - - [3.8,) - - - - - - - - org.sonatype.central - central-publishing-maven-plugin - 0.5.0 - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - - repackage - - - - - - org.openapitools - openapi-generator-maven-plugin - 7.7.0 - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.7.0 - - - org.apache.maven.plugins - maven-gpg-plugin - 3.2.4 - - - org.codehaus.mojo - versions-maven-plugin - 2.17.0 - - - org.apache.maven.plugins - maven-source-plugin - 3.3.1 - - - de.juplo - hibernate-maven-plugin - 2.1.1 - - - org.apache.cxf - cxf-codegen-plugin - 4.0.4 - - - org.codehaus.mojo - build-helper-maven-plugin - 3.6.0 - - - com.github.eirslett - frontend-maven-plugin - 1.15.0 - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - org.jacoco - jacoco-maven-plugin - - - org.apache.maven.plugins - maven-release-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - - - - - - release - - - - - org.sonatype.central - central-publishing-maven-plugin - true - - true - true - ${project.groupId}:${project.version} - - - refarch-gateway - - - - - - - org.codehaus.mojo - versions-maven-plugin - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar-no-fork - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - none - - **/*.java - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - - - sign-artifacts - verify - - sign - - - - - --pinentry-mode - loopback - - - - - - - - - diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index d886da98..700a5ff7 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -4,15 +4,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - de.muenchen.oss - refarch - ../pom.xml - 1.0.0-SNAPSHOT + org.springframework.boot + spring-boot-starter-parent + 3.3.1 + - de.muenchen.oss.refarch refarch-gateway 1.0.0-SNAPSHOT @@ -20,35 +18,32 @@ refarch-gateway + 17 + 2023.0.2 7.4 5.4.0 3.14.0 + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + - - - org.springframework.cloud - spring-cloud-starter - + org.springframework.cloud spring-cloud-starter-gateway - - - org.springframework.boot - spring-boot-starter-hateoas - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot @@ -76,24 +71,11 @@ ${hazelcast.version} - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.security - spring-security-test - test - - org.springframework.cloud - spring-cloud-starter-contract-stub-runner - test + org.projectlombok + lombok + true - - org.apache.commons commons-lang3 @@ -118,6 +100,23 @@ io.micrometer micrometer-registry-prometheus + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + org.springframework.cloud + spring-cloud-starter-contract-stub-runner + test + @@ -131,6 +130,14 @@ org.springframework.boot spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + From dfed9e733c45d9b984a667f1c3db45de28cfbbeb Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Tue, 16 Jul 2024 09:10:13 +0200 Subject: [PATCH 47/48] refactor maven build config and reformat --- refarch-gateway/checkstyle.xml | 6 +- refarch-gateway/pom.xml | 100 ++++++++++++++++++ .../ApiGatewayApplication.java | 14 ++- .../configuration/CsrfProtectionMatcher.java | 10 +- .../configuration/SecurityConfiguration.java | 54 ++++------ .../configuration/SecurityProperties.java | 3 +- .../WebSessionConfiguration.java | 12 +-- .../CsrfTokenAppendingHelperFilter.java | 9 +- .../filter/DistributedTracingFilter.java | 13 ++- .../GlobalAuthenticationErrorFilter.java | 12 +-- .../filter/GlobalBackend5xxTo400Mapper.java | 7 +- ...GlobalRequestParameterPollutionFilter.java | 16 +-- .../controller/ActuatorInfoEndpointTest.java | 6 +- .../CsrfTokenAppendingHelperFilterTest.java | 6 +- .../GlobalAuthenticationErrorFilterTest.java | 11 +- .../GlobalBackend5xxTo400MapperTest.java | 8 +- .../filter/GlobalBackendErrorFilterTest.java | 11 +- ...alRequestParameterPollutionFilterTest.java | 16 ++- .../route/BackendRouteTest.java | 8 +- 19 files changed, 202 insertions(+), 120 deletions(-) diff --git a/refarch-gateway/checkstyle.xml b/refarch-gateway/checkstyle.xml index 37f7f0e7..e586d12e 100644 --- a/refarch-gateway/checkstyle.xml +++ b/refarch-gateway/checkstyle.xml @@ -3,7 +3,7 @@ "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd"> - + @@ -18,8 +18,8 @@ - - + + diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index 700a5ff7..d975350c 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -19,6 +19,15 @@ 17 + + -Dorg.conscrypt.native.workdir=$(pwd) + 0.8.11 + 3.2.5 + 2.34.0 + 1.0.9 + 3.3.1 + 9.3 + 2023.0.2 7.4 5.4.0 @@ -127,6 +136,14 @@ + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire.plugin.version} + + ${jvm.options} + + org.springframework.boot spring-boot-maven-plugin @@ -138,6 +155,89 @@ + + + + repackage + + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + + + com.diffplug.spotless + spotless-maven-plugin + ${spotless.maven.plugin.version} + + + de.muenchen.oss + itm-java-codeformat + ${itm.java.codeformat.version} + + + + + + src/main/java/**/*.java + src/test/java/**/*.java + + + itm-java-codeformat/java_codestyle_formatter.xml + + + + + + + + + check + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${maven.checkstyle.plugin.version} + + checkstyle.xml + + + + + check + + + + + + com.puppycrawl.tools + checkstyle + ${checkstyle.version} + + diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java index aa410fda..2f09da74 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/ApiGatewayApplication.java @@ -5,16 +5,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; - /** - * To do some base configuration for the non blocking client-server framework - * named Netty via properties use the properties listed in the link down below: - * - * @see + * https://projectreactor.io/docs/netty/release/api/constant-values.html *

- * As listed below, this above mentioned properties should be set before the application - * startup: + * As listed below, this above-mentioned properties should be set before the application startup: * *

    *
  • As command line argument: e.g. -Dreactor.netty.pool.maxConnections=1000. @@ -26,7 +24,7 @@ *
*

* To get more information about Spring Cloud Gateway visit the following link: - * @see https://cloud.spring.io/spring-cloud-gateway/reference/html/ */ @SpringBootApplication diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/CsrfProtectionMatcher.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/CsrfProtectionMatcher.java index 2f970e48..c54bb9b7 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/CsrfProtectionMatcher.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/CsrfProtectionMatcher.java @@ -1,5 +1,8 @@ package de.muenchen.oss.refarch.gateway.configuration; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @@ -10,10 +13,6 @@ import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - @Configuration @Profile("!no-security") @RequiredArgsConstructor @@ -45,7 +44,6 @@ private boolean isWhitelisted(String path) { return false; } - private record MethodAndPath(HttpMethod method, String path) { } -} \ No newline at end of file +} diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java index 024a34f3..72fa12c2 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityConfiguration.java @@ -1,5 +1,7 @@ package de.muenchen.oss.refarch.gateway.configuration; +import java.net.URI; +import java.time.Duration; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -19,10 +21,6 @@ import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers; import reactor.core.publisher.Mono; -import java.net.URI; -import java.time.Duration; - - @Configuration @Profile("!no-security") @RequiredArgsConstructor @@ -41,8 +39,8 @@ public class SecurityConfiguration { private long springSessionTimeoutSeconds; /** - * This method creates the {@link ServerLogoutSuccessHandler} for handling a successful logout. - * The usage is necessary in {@link SecurityWebFilterChain}. + * This method creates the {@link ServerLogoutSuccessHandler} for handling a successful logout. The + * usage is necessary in {@link SecurityWebFilterChain}. * * @param uri to forward after an successful logout. * @return The handler for forwarding after an succesful logout. @@ -58,15 +56,12 @@ public static ServerLogoutSuccessHandler createLogoutSuccessHandler(final String public SecurityWebFilterChain clientAccessFilterChain(ServerHttpSecurity http) { http .securityMatcher(ServerWebExchangeMatchers.pathMatchers("/clients/**")) - .authorizeExchange(authorizeExchangeSpec -> - authorizeExchangeSpec - .pathMatchers(HttpMethod.OPTIONS, "/clients/**").permitAll() - .anyExchange().authenticated()) + .authorizeExchange(authorizeExchangeSpec -> authorizeExchangeSpec + .pathMatchers(HttpMethod.OPTIONS, "/clients/**").permitAll() + .anyExchange().authenticated()) .cors(corsSpec -> { }) - .oauth2ResourceServer(oauth2 -> - oauth2.jwt(Customizer.withDefaults()) - ); + .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())); return http.build(); } @@ -74,11 +69,9 @@ public SecurityWebFilterChain clientAccessFilterChain(ServerHttpSecurity http) { @Order(1) public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http - .logout(logoutSpec -> - logoutSpec.logoutSuccessHandler(createLogoutSuccessHandler(LOGOUT_SUCCESS_URL)) - .logoutUrl(LOGOUT_URL) - .requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, LOGOUT_URL)) - ) + .logout(logoutSpec -> logoutSpec.logoutSuccessHandler(createLogoutSuccessHandler(LOGOUT_SUCCESS_URL)) + .logoutUrl(LOGOUT_URL) + .requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, LOGOUT_URL))) .authorizeExchange(authorizeExchangeSpec -> { // permitAll authorizeExchangeSpec.pathMatchers(HttpMethod.OPTIONS, "/api/**").permitAll() @@ -86,7 +79,8 @@ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) .pathMatchers("/api/*/info", "/actuator/health", "/actuator/info", - "/actuator/metrics").permitAll() + "/actuator/metrics") + .permitAll() .pathMatchers(HttpMethod.OPTIONS, "/public/**").permitAll() .pathMatchers(HttpMethod.GET, "/public/**").permitAll() // only authenticated @@ -97,7 +91,8 @@ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) .csrf(csrfSpec -> { /* * Custom csrf request handler for spa and BREACH attack protection. - * https://docs.spring.io/spring-security/reference/6.1-SNAPSHOT/servlet/exploits/csrf.html#csrf-integration-javascript-spa + * https://docs.spring.io/spring-security/reference/6.1-SNAPSHOT/servlet/exploits/csrf.html#csrf- + * integration-javascript-spa */ csrfSpec.csrfTokenRequestHandler(new SpaServerCsrfTokenRequestHandler()); /* @@ -107,17 +102,14 @@ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) csrfSpec.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse()); csrfSpec.requireCsrfProtectionMatcher(csrfProtectionMatcher); }) - .oauth2Login(oAuth2LoginSpec -> - oAuth2LoginSpec.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler() { - @Override - public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { - webFilterExchange.getExchange().getSession().subscribe( - webSession -> webSession.setMaxIdleTime(Duration.ofSeconds(springSessionTimeoutSeconds)) - ); - return super.onAuthenticationSuccess(webFilterExchange, authentication); - } - }) - ); + .oauth2Login(oAuth2LoginSpec -> oAuth2LoginSpec.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler() { + @Override + public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { + webFilterExchange.getExchange().getSession().subscribe( + webSession -> webSession.setMaxIdleTime(Duration.ofSeconds(springSessionTimeoutSeconds))); + return super.onAuthenticationSuccess(webFilterExchange, authentication); + } + })); return http.build(); } diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityProperties.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityProperties.java index afb6e2a7..99336803 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityProperties.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/SecurityProperties.java @@ -1,11 +1,10 @@ package de.muenchen.oss.refarch.gateway.configuration; +import java.util.List; import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; -import java.util.List; - @Getter @Setter @ConfigurationProperties("refarch.security") diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java index ddc222ec..e0c070fa 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/configuration/WebSessionConfiguration.java @@ -51,9 +51,9 @@ public ReactiveSessionRepository reactiveSessionRepository(@Qualifie } @Bean - @Profile({"local", "test"}) + @Profile({ "local", "test" }) public Config localConfig(@Value( - "${spring.session.timeout}" + "${spring.session.timeout}" ) int timeout) { final var hazelcastConfig = new Config(); hazelcastConfig.setInstanceName(hazelcastInstanceName); @@ -73,7 +73,7 @@ public Config localConfig(@Value( } @Bean - @Profile({"dev", "kon", "prod"}) + @Profile({ "dev", "kon", "prod" }) public Config config(@Value("${spring.session.timeout}") int timeout) { final var hazelcastConfig = new Config(); hazelcastConfig.setInstanceName(hazelcastInstanceName); @@ -94,11 +94,11 @@ public Config config(@Value("${spring.session.timeout}") int timeout) { /** * Adds the session timeout in seconds to the hazelcast configuration. *

- * Since we are creating the map it's important to evict sessions - * by setting a reasonable value for time to live. + * Since we are creating the map it's important to evict sessions by setting a reasonable value for + * time to live. * * @param hazelcastConfig to add the timeout. - * @param sessionTimeout for security session. + * @param sessionTimeout for security session. */ private void addSessionTimeoutToHazelcastConfig(final Config hazelcastConfig, final int sessionTimeout) { final var sessionConfig = new MapConfig(); diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java index fa049939..b7490680 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilter.java @@ -13,10 +13,11 @@ import reactor.core.publisher.Mono; /** - * This class subscribes the {@link ServerWebExchange} for csrf token attachment - * within the classes {@link CookieServerCsrfTokenRepository} and {@link CsrfWebFilter}. - * The csrf configuration done only in {@link SecurityConfiguration#springSecurityFilterChain} is - * not sufficient for csrf token attachment to a {@link ServerHttpResponse}. + * This class subscribes the {@link ServerWebExchange} for csrf token attachment within the classes + * {@link CookieServerCsrfTokenRepository} and + * {@link CsrfWebFilter}. The csrf configuration done only in + * {@link SecurityConfiguration#springSecurityFilterChain} is not sufficient for csrf token + * attachment to a {@link ServerHttpResponse}. */ @Component @Slf4j diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java index 6b81ab54..06048ed1 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/DistributedTracingFilter.java @@ -12,8 +12,7 @@ import reactor.core.publisher.Mono; /** - * This class adds the sleuth headers "X-B3-SpanId" and "X-B3-TraceId" - * to each route response. + * This class adds the sleuth headers "X-B3-SpanId" and "X-B3-TraceId" to each route response. */ @Component @Slf4j @@ -26,17 +25,17 @@ public class DistributedTracingFilter implements WebFilter { private Tracer tracer; /** - * This method adds the zipkin headers "X-B3-SpanId" and "X-B3-TraceId" - * to each response in {@link ServerWebExchange}. + * This method adds the zipkin headers "X-B3-SpanId" and "X-B3-TraceId" to each response in + * {@link ServerWebExchange}. * * @param serverWebExchange the current server exchange without zipkin headers - * @param webFilterChain provides a way to delegate to the next filter + * @param webFilterChain provides a way to delegate to the next filter * @return {@code Mono} to indicate when request processing for adding zipkin headers is - * complete + * complete */ @Override public Mono filter(ServerWebExchange serverWebExchange, - WebFilterChain webFilterChain) { + WebFilterChain webFilterChain) { ServerHttpResponse response = serverWebExchange.getResponse(); response.beforeCommit(() -> { var span = tracer.currentSpan(); diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java index 88f7e818..c8b534c4 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilter.java @@ -1,5 +1,6 @@ package de.muenchen.oss.refarch.gateway.filter; +import java.nio.charset.StandardCharsets; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -20,14 +21,13 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.nio.charset.StandardCharsets; - /** - * This {@link GlobalFilter} replaces the body by a generic authentication error body, - * when a server responses with a {@link HttpStatus#UNAUTHORIZED}. + * This {@link GlobalFilter} replaces the body by a generic authentication error body, when a server + * responses with a {@link HttpStatus#UNAUTHORIZED}. *

- * The header {@link HttpHeaders#WWW_AUTHENTICATE} containing the access token is removed - * by the property 'RemoveResponseHeader' in the corresponding route within 'application.yml'. + * The header {@link HttpHeaders#WWW_AUTHENTICATE} containing the access token is removed by the + * property 'RemoveResponseHeader' in the corresponding route + * within 'application.yml'. */ @Component @Slf4j diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java index 918f7a0b..e9abf1be 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400Mapper.java @@ -1,5 +1,6 @@ package de.muenchen.oss.refarch.gateway.filter; +import java.nio.charset.StandardCharsets; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -23,11 +24,9 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.nio.charset.StandardCharsets; - /** - * This {@link GlobalFilter} replaces the body by a generic error body, when a server responses - * with a {@link HttpStatus#INTERNAL_SERVER_ERROR}. + * This {@link GlobalFilter} replaces the body by a generic error body, when a server responses with + * a {@link HttpStatus#INTERNAL_SERVER_ERROR}. */ @Component @Slf4j diff --git a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java index a1e2c332..58138c92 100644 --- a/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java +++ b/refarch-gateway/src/main/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilter.java @@ -1,6 +1,8 @@ package de.muenchen.oss.refarch.gateway.filter; import de.muenchen.oss.refarch.gateway.exception.ParameterPollutionException; +import java.util.List; +import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; @@ -14,15 +16,12 @@ import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; -import java.util.List; -import java.util.Map; - /** * This {@link GlobalFilter} is used to detect and to fend off a parameter pollution attack. *

- * Within a {@link HttpRequest} each request parameter should only exist once. - * This check is necessary to avoid e.g. SQL injection split over multiple request parameters with - * the same name. + * Within a {@link HttpRequest} each request parameter should only exist once. This check is + * necessary to avoid e.g. SQL injection split over multiple request + * parameters with the same name. */ @Component @Slf4j @@ -38,8 +37,9 @@ public int getOrder() { /** * See {@link GlobalFilter#filter(ServerWebExchange, GatewayFilterChain)} * - * @throws ParameterPollutionException is throw when a request parameter exists multiple times. - * The exception represents a http response with status {@link HttpStatus#BAD_REQUEST}. + * @throws ParameterPollutionException is throw when a request parameter exists multiple times. The + * exception represents a http response with status + * {@link HttpStatus#BAD_REQUEST}. */ @Override public Mono filter(final ServerWebExchange exchange, final GatewayFilterChain chain) throws ParameterPollutionException { diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java index bb2ff167..9d625fae 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/controller/ActuatorInfoEndpointTest.java @@ -1,5 +1,7 @@ package de.muenchen.oss.refarch.gateway.controller; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; + import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -9,11 +11,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; - @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = {ApiGatewayApplication.class}, + classes = { ApiGatewayApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java index f5286780..23b8e40d 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/CsrfTokenAppendingHelperFilterTest.java @@ -1,5 +1,7 @@ package de.muenchen.oss.refarch.gateway.filter; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; + import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -10,11 +12,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; - @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = {ApiGatewayApplication.class}, + classes = { ApiGatewayApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java index 16e66df4..20aae12c 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalAuthenticationErrorFilterTest.java @@ -1,5 +1,8 @@ package de.muenchen.oss.refarch.gateway.filter; +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; + import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; @@ -15,12 +18,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; - @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = {ApiGatewayApplication.class}, + classes = { ApiGatewayApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) @@ -38,8 +38,7 @@ void setup() { .withHeaders(new HttpHeaders( new HttpHeader("Content-Type", "application/json"), new HttpHeader("WWW-Authenticate", "Bearer realm=\"Access to the staging site\", charset=\"UTF-8\""), - new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT") - )) + new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) .withBody("{ \"testkey\" : \"testvalue\" }"))); } diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java index ec9ed7f8..0ff54a18 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackend5xxTo400MapperTest.java @@ -1,5 +1,8 @@ package de.muenchen.oss.refarch.gateway.filter; +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; + import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; @@ -15,12 +18,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; - @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = {ApiGatewayApplication.class}, + classes = { ApiGatewayApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java index 4e5a8d25..9517f320 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalBackendErrorFilterTest.java @@ -1,5 +1,8 @@ package de.muenchen.oss.refarch.gateway.filter; +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; + import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; @@ -16,12 +19,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; - @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = {ApiGatewayApplication.class}, + classes = { ApiGatewayApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) @@ -44,8 +44,7 @@ void setup() { .withHeaders(new HttpHeaders( new HttpHeader("Content-Type", "application/json"), new HttpHeader("WWW-Authenticate", "Bearer realm=\"Access to the staging site\", charset=\"UTF-8\""), - new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT") - )) + new HttpHeader("Expires", "Wed, 21 Oct 2099 07:28:06 GMT"))) .withBody("{ \"testkey\" : \"testvalue\" }"))); } diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java index cfc163e9..a5a4dbfa 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/filter/GlobalRequestParameterPollutionFilterTest.java @@ -1,6 +1,11 @@ package de.muenchen.oss.refarch.gateway.filter; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; +import static org.junit.jupiter.api.Assertions.assertTrue; + import de.muenchen.oss.refarch.gateway.ApiGatewayApplication; +import java.nio.charset.StandardCharsets; +import java.util.Objects; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -11,15 +16,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import java.nio.charset.StandardCharsets; -import java.util.Objects; - -import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; -import static org.junit.jupiter.api.Assertions.assertTrue; - @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = {ApiGatewayApplication.class}, + classes = { ApiGatewayApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) @@ -38,8 +37,7 @@ void parameterPollutionAttack() { .isEqualTo(HttpStatus.BAD_REQUEST) .expectBody() .consumeWith(responseBody -> jsonResponseBody.append( - new String(Objects.requireNonNull(responseBody.getResponseBody()), StandardCharsets.UTF_8) - )); + new String(Objects.requireNonNull(responseBody.getResponseBody()), StandardCharsets.UTF_8))); assertTrue(jsonResponseBody.toString().contains("\"message\" : \"parameter pollution\"")); } diff --git a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java index 75764509..ddda03c1 100644 --- a/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java +++ b/refarch-gateway/src/test/java/de.muenchen.oss.refarch.gateway/route/BackendRouteTest.java @@ -1,5 +1,8 @@ package de.muenchen.oss.refarch.gateway.route; +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; + import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; import com.github.tomakehurst.wiremock.matching.EqualToPattern; @@ -16,12 +19,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; -import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static de.muenchen.oss.refarch.gateway.TestConstants.SPRING_TEST_PROFILE; - @ExtendWith(SpringExtension.class) @SpringBootTest( - classes = {ApiGatewayApplication.class}, + classes = { ApiGatewayApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) @ActiveProfiles(SPRING_TEST_PROFILE) From 7d864d89b7ac38c4b6468506c87f9962bceac53a Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter Date: Tue, 16 Jul 2024 09:10:55 +0200 Subject: [PATCH 48/48] use hazelcast 5.3.6 --- refarch-gateway/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refarch-gateway/pom.xml b/refarch-gateway/pom.xml index d975350c..aec0607c 100644 --- a/refarch-gateway/pom.xml +++ b/refarch-gateway/pom.xml @@ -30,7 +30,7 @@ 2023.0.2 7.4 - 5.4.0 + 5.3.6 3.14.0