refactoring Gateway

This commit is contained in:
Stefan Mogeritsch 2025-10-10 12:31:53 +02:00
parent e8f4e9aef1
commit da7ea2c2da
9 changed files with 281 additions and 743 deletions

View File

@ -79,7 +79,7 @@ subprojects {
includeTags("perf")
}
shouldRunAfter("test")
// Keep same JVM settings for consistency
// Keep the same JVM settings for consistency
jvmArgs("-Xshare:auto", "-Djdk.instrument.traceUsage=false")
maxHeapSize = "2g"
dependsOn("testClasses")
@ -100,6 +100,12 @@ subprojects {
environment("CHROMIUM_BIN", "/usr/bin/chromium")
environment("PUPPETEER_EXECUTABLE_PATH", "/usr/bin/chromium")
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
compilerOptions {
freeCompilerArgs.add("-Xannotation-default-target=param-property")
}
}
}
// ##################################################################

View File

@ -251,7 +251,7 @@ flyway = [
]
spring-boot-essentials = [
"spring-boot-starter-web",
# "spring-boot-starter-web",
"spring-boot-starter-validation",
"spring-boot-starter-actuator"
]
@ -426,7 +426,7 @@ ktor-server-complete = [
# Complete Spring Boot Service bundle - combines all Spring Boot bundles for full-featured services
spring-boot-service-complete = [
"spring-boot-starter-web",
# "spring-boot-starter-web",
"spring-boot-starter-validation",
"spring-boot-starter-actuator",
"spring-boot-starter-security",

View File

@ -17,42 +17,45 @@ dependencies {
// Platform BOM für zentrale Versionsverwaltung
implementation(platform(projects.platform.platformBom))
// Core project dependencies
// Core project dependencies (sind korrekt)
implementation(projects.core.coreUtils)
implementation(projects.platform.platformDependencies)
// Spring Cloud Gateway und Service Discovery (Bundle)
// === BEREINIGTE ABHÄNGIGKEITEN ===
// 1. Spring Cloud Gateway & Service Discovery (dies ist die KERN-Abhängigkeit)
implementation(libs.bundles.spring.cloud.gateway)
// Spring Boot Service Complete Bundle (Web, Security, Data, Observability)
// Provides: spring-boot-starter-web, validation, actuator, security,
// oauth2-client, oauth2-resource-server, data-jpa, data-redis,
// micrometer-prometheus, tracing-bridge-brave, zipkin-reporter-brave
implementation(libs.bundles.spring.boot.service.complete)
// 2. Spring Boot Security (ersetzt das "service.complete"-Bundle)
// Dieses Bundle sollte spring-boot-starter-security, oauth2-client, oauth2-resource-server etc. enthalten
// Temporär auskommentieren, um das Bundle als Fehlerquelle auszuschließen
// implementation(libs.bundles.spring.boot.security)
// Reactive WebFlux for Gateway
implementation(libs.spring.boot.starter.webflux)
// Stattdessen die Abhängigkeiten direkt hinzufügen:
implementation(libs.spring.boot.starter.security)
implementation(libs.spring.boot.starter.oauth2.resource.server)
// Resilience4j Bundle (Circuit Breaker support)
// 3. Resilience4j & AOP für Circuit Breaker
implementation(libs.bundles.resilience)
// Spring Cloud CircuitBreaker for Gateway Filter Integration
implementation("org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j")
// Jackson Kotlin support
implementation(libs.bundles.jackson.kotlin)
// Logging Bundle (kotlin-logging, logback-classic, logback-core, slf4j-api)
implementation(libs.bundles.logging)
// Infrastructure dependencies
implementation(projects.infrastructure.auth.authClient)
// 4. Monitoring-Client (ist korrekt)
implementation(projects.infrastructure.monitoring.monitoringClient)
// Test dependencies
// 5. Auth-Client für JWT-Erstellung/Service (falls noch benötigt nach Schritt 2)
implementation(projects.infrastructure.auth.authClient)
// 6. Logging & Jackson (sind korrekt)
implementation(libs.bundles.logging)
implementation(libs.bundles.jackson.kotlin)
// FÜGEN SIE DIESE ZEILE HINZU, UM DIE FEHLER ZU BEHEBEN:
implementation(libs.spring.boot.starter.actuator)
// Test-Abhängigkeiten (sind korrekt)
testImplementation(projects.platform.platformTesting)
testImplementation(libs.bundles.testing.jvm)
testImplementation(libs.bundles.logging)
}
tasks.test {

View File

@ -1,55 +0,0 @@
package at.mocode.infrastructure.gateway.config
import at.mocode.infrastructure.auth.client.JwtService
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.validation.annotation.Validated
import jakarta.validation.constraints.Min
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Size
import kotlin.time.Duration.Companion.minutes
/**
* Spring-Konfiguration für JWT-Verarbeitung im Gateway.
* Stellt den JwtService-Bean für die Token-Validierung bereit.
*/
@Configuration
@EnableConfigurationProperties(JwtConfiguration.JwtProperties::class)
class JwtConfiguration {
/**
* Erstellt einen JwtService-Bean für JWT-Token-Validierung im Gateway.
*/
@Bean
fun jwtService(jwtProperties: JwtProperties): JwtService {
// Basic safeguard: warn if default secret is used
if (jwtProperties.secret == "default-secret-for-development-only-please-change-in-production") {
System.err.println("[GATEWAY SECURITY WARNING] Using default JWT secret DO NOT use this in production!")
}
return JwtService(
secret = jwtProperties.secret,
issuer = jwtProperties.issuer,
audience = jwtProperties.audience,
expiration = jwtProperties.expiration.minutes
)
}
/**
* Konfigurationseigenschaften für JWT-Einstellungen im Gateway.
*/
@ConfigurationProperties(prefix = "gateway.security.jwt")
@Validated
data class JwtProperties(
@field:NotBlank
@field:Size(min = 32, message = "JWT secret must be at least 32 characters for HMAC512")
val secret: String = "default-secret-for-development-only-please-change-in-production",
@field:NotBlank
val issuer: String = "meldestelle-auth-server",
@field:NotBlank
val audience: String = "meldestelle-services",
@field:Min(1)
val expiration: Long = 60 // minutes
)
}

View File

@ -1,148 +0,0 @@
package at.mocode.infrastructure.gateway.security
import at.mocode.infrastructure.auth.client.JwtService
import at.mocode.infrastructure.auth.client.model.BerechtigungE
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.cloud.gateway.filter.GatewayFilterChain
import org.springframework.cloud.gateway.filter.GlobalFilter
import org.springframework.core.Ordered
import org.springframework.http.HttpStatus
import org.springframework.http.server.reactive.ServerHttpResponse
import org.springframework.stereotype.Component
import org.springframework.util.AntPathMatcher
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono
/**
* JWT Authentication Filter für das Gateway.
* Validiert JWT-Tokens für alle geschützten Endpunkte.
*/
@Component
@ConditionalOnProperty(value = ["gateway.security.jwt.enabled"], havingValue = "true", matchIfMissing = true)
class JwtAuthenticationFilter(
private val jwtService: JwtService
) : GlobalFilter, Ordered {
private val pathMatcher = AntPathMatcher()
// Öffentliche Pfade, die keine Authentifizierung erfordern
private val publicPaths = listOf(
"/",
"/health",
"/actuator/**",
"/api/auth/login",
"/api/auth/register",
"/api/auth/refresh",
"/fallback/**",
"/docs/**",
"/swagger-ui/**",
"/api/ping/**" // Ping Service für Monitoring
)
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
val request = exchange.request
val path = request.path.value()
// Prüfe, ob der Pfad öffentlich zugänglich ist
if (isPublicPath(path)) {
return chain.filter(exchange)
}
// Extrahiere JWT aus Authorization Header
val authHeader = request.headers.getFirst("Authorization")
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
return handleUnauthorized(exchange, "Missing or invalid Authorization header")
}
val token = authHeader.substring(7)
// Hier würde normalerweise die JWT-Validierung mit dem auth-client erfolgen,
// für diese Implementation verwenden wir eine vereinfachte Validierung
return validateJwtToken(token, exchange, chain)
}
private fun isPublicPath(path: String): Boolean {
return publicPaths.any { publicPath ->
pathMatcher.match(publicPath, path)
}
}
private fun validateJwtToken(
token: String,
exchange: ServerWebExchange,
chain: GatewayFilterChain
): Mono<Void> {
// Use auth-client JwtService for comprehensive JWT validation
val validationResult = jwtService.validateToken(token)
if (validationResult.isFailure) {
return handleUnauthorized(exchange, "Invalid JWT token: ${validationResult.exceptionOrNull()?.message}")
}
try {
// Extract user ID using auth-client
val userIdResult = jwtService.getUserIdFromToken(token)
if (userIdResult.isFailure) {
return handleUnauthorized(exchange, "Failed to extract user ID from token")
}
val userId = userIdResult.getOrThrow()
// Extract permissions using auth-client
val permissionsResult = jwtService.getPermissionsFromToken(token)
val permissions = permissionsResult.getOrElse { emptyList() }
// Convert permissions to role for backward compatibility
val userRole = determineRoleFromPermissions(permissions)
val permissionsHeader = permissions.joinToString(",") { it.name }
val mutatedRequest = exchange.request.mutate()
.header("X-User-ID", userId)
.header("X-User-Role", userRole)
.header("X-User-Permissions", permissionsHeader)
.build()
val mutatedExchange = exchange.mutate()
.request(mutatedRequest)
.build()
return chain.filter(mutatedExchange)
} catch (e: Exception) {
return handleUnauthorized(exchange, "JWT processing failed: ${e.message}")
}
}
/**
* Determines the user role based on permissions for backward compatibility.
* Maps permissions to traditional role-based access control.
*/
private fun determineRoleFromPermissions(permissions: List<BerechtigungE>): String {
return when {
permissions.any { it.name.contains("ADMIN", ignoreCase = true) } -> "ADMIN"
permissions.any { it.name.contains("DELETE") } -> "ADMIN" // DELETE permissions indicate admin-level access
permissions.any { it.name.contains("WRITE") || it.name.contains("CREATE") } -> "USER"
permissions.isNotEmpty() -> "USER"
else -> "GUEST"
}
}
private fun handleUnauthorized(exchange: ServerWebExchange, message: String): Mono<Void> {
val response: ServerHttpResponse = exchange.response
response.statusCode = HttpStatus.UNAUTHORIZED
response.headers.add("Content-Type", "application/json")
val errorJson = """{
"error": "UNAUTHORIZED",
"message": "$message",
"timestamp": "${java.time.LocalDateTime.now()}",
"status": 401
}"""
val buffer = response.bufferFactory().wrap(errorJson.toByteArray())
return response.writeWith(Mono.just(buffer))
}
override fun getOrder(): Int = Ordered.HIGHEST_PRECEDENCE + 3
}

View File

@ -1,328 +1,100 @@
package at.mocode.infrastructure.gateway.security
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
import org.springframework.security.config.web.server.ServerHttpSecurity
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder
import org.springframework.security.config.web.server.invoke
import org.springframework.security.web.server.SecurityWebFilterChain
import org.springframework.web.cors.CorsConfiguration
import org.springframework.web.cors.reactive.CorsConfigurationSource
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource
import java.time.Duration
/**
* Erweiterte reaktive Sicherheitskonfiguration für das Gateway.
*
* ARCHITEKTUR-ÜBERBLICK:
* ======================
* Diese Konfiguration stellt die grundlegende Sicherheits-Schicht für das Spring Cloud Gateway bereit.
* Sie arbeitet zusammen mit mehreren weiteren Sicherheitskomponenten:
*
* 1. JwtAuthenticationFilter (GlobalFilter) Validiert JWT-Tokens und authentifiziert Benutzer
* 2. RateLimitingFilter (GlobalFilter) Bietet IP-basiertes Rate-Limiting mit benutzerbezogenen Limits
* 3. CorrelationIdFilter (GlobalFilter) Fügt Request-Tracing-Fähigkeiten hinzu
* 4. EnhancedLoggingFilter (GlobalFilter) Liefert strukturiertes Request/Response-Logging
*
* SICHERHEITSSTRATEGIE:
* =====================
* Das Gateway verwendet einen mehrschichtigen Sicherheitsansatz:
* - Diese SecurityWebFilterChain liefert grundlegende Einstellungen (CORS, CSRF, Basis-Header)
* - Der JwtAuthenticationFilter übernimmt die eigentliche Authentifizierung, wenn per Property aktiviert
* - Die SecurityWebFilterChain bleibt permissiv (permitAll), damit der JWT-Filter den Zugriff steuert
* - Rate-Limiting- und Logging-Filter liefern operative Sicherheit und Monitoring
*
* ENTWURFSBEGRÜNDUNG:
* ===================
* - Während Tests ist Spring Security auf dem Classpath (testImplementation), was
* die Auto-Konfiguration aktiviert und alle Endpunkte sperren kann, sofern keine SecurityWebFilterChain bereitgestellt wird
* - Das Gateway erzwingt Authentifizierung über den JwtAuthenticationFilter (falls per Property aktiviert),
* daher sollte die SecurityWebFilterChain permissiv bleiben und sich auf grundlegende Belange konzentrieren
* - Explizite CORS-Konfiguration stellt eine korrekte Behandlung von Cross-Origin-Anfragen aus Web-Clients sicher
* - Konfigurierbare Properties erlauben umgebungsspezifische Sicherheitseinstellungen ohne Codeänderungen
* - CSRF-Schutz ist deaktiviert, da er für zustandslose JWT-basierte Authentifizierung nicht benötigt wird
*
* CORS-INTEGRATION:
* =================
* Die CORS-Konfiguration arbeitet mit der bestehenden Filterkette zusammen:
* - Erlaubt Anfragen von konfigurierten Ursprüngen (Dev/Prod-Umgebungen)
* - Gibt benutzerdefinierte Header aus Gateway-Filtern frei (Korrelations-IDs, Rate-Limits)
* - Unterstützt Credentials für JWT-Authentifizierung
* - Cacht Preflight-Antworten für bessere Performance
*
* TESTHINWEISE:
* =============
* - Die Konfiguration ist so gestaltet, dass sie nahtlos mit bestehenden Sicherheitstests funktioniert
* - Das Test-Profil kann CORS-Einstellungen bei Bedarf überschreiben
* - Eine permissive Autorisierung stellt sicher, dass Tests sich auf die Sicherheit der Filterebene konzentrieren können
*/
@Configuration
@EnableWebFluxSecurity
@EnableConfigurationProperties(GatewaySecurityProperties::class)
class SecurityConfig(
private val securityProperties: GatewaySecurityProperties,
@Value($$"${keycloak.issuer-uri:}") private val issuerUri: String,
@Value($$"${keycloak.jwk-set-uri:}") private val jwkSetUri: String
private val securityProperties: GatewaySecurityProperties
) {
/**
* Hauptkonfiguration der Spring-Security-Filterkette.
* Konfiguriert die zentrale Security-Filter-Kette für das Gateway.
*
* Diese Methode konfiguriert die reaktive Sicherheits-Filterkette mit:
* - CSRF deaktiviert für zustandslosen API-Betrieb
* - Explizite CORS-Konfiguration für Cross-Origin-Unterstützung
* - Permissiver Autorisierung (Authentifizierung durch den JWT-Filter)
*
* Die Konfiguration bleibt kompatibel mit der bestehenden Filterarchitektur
* und bietet zugleich bessere CORS-Steuerung und Konfigurierbarkeit.
* Diese Konfiguration nutzt den Standard-OAuth2-Resource-Server von Spring Security,
* um JWTs (z.B. von Keycloak) automatisch zu validieren.
*/
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
val httpSecurity = http
.cors { it.configurationSource(corsConfigurationSource()) }
.csrf { it.disable() }
.authorizeExchange { exchanges ->
exchanges
// Public paths
.pathMatchers(
"/",
"/health/**",
"/actuator/**",
"/api/ping/**",
"/api/auth/**", // All auth endpoints (includes test endpoints)
"/api/auth/login",
"/api/auth/register",
"/api/auth/refresh",
"/fallback/**",
"/docs/**",
"/swagger-ui/**",
"/test/**", // Test paths for integration tests
"/mock/**" // Mock controller paths for tests
).permitAll()
.apply {
// Only enforce role-based authorization when oauth2ResourceServer is active
// In tests without oauth2, JwtAuthenticationFilter handles auth via GlobalFilter
if (jwkSetUri.isNotBlank()) {
// Admin paths
pathMatchers("/api/admin/**").hasRole("ADMIN")
// Monitoring paths
pathMatchers("/api/monitoring/**").hasAnyRole("ADMIN", "MONITORING")
// All other requests require authentication
anyExchange().authenticated()
} else {
// Permissive mode for tests - JwtAuthenticationFilter handles auth
anyExchange().permitAll()
}
}
return http { // Start der modernen Kotlin-DSL
// 1. CORS-Konfiguration anwenden
cors { }
// 2. CSRF deaktivieren (für zustandslose APIs)
csrf { disable() }
// 3. Routen-Berechtigungen definieren
authorizeExchange {
// Öffentlich zugängliche Pfade aus der .yml-Datei laden
pathMatchers(*securityProperties.publicPaths.toTypedArray()).permitAll()
// Alle anderen Pfade erfordern eine Authentifizierung
anyExchange.authenticated()
}
// Only configure oauth2ResourceServer if Keycloak JWK URI is configured
// In tests, this will be empty, allowing JwtAuthenticationFilter to handle auth
if (jwkSetUri.isNotBlank()) {
httpSecurity.oauth2ResourceServer { oauth2 ->
oauth2.jwt { jwt ->
jwt.jwtDecoder(jwtDecoder())
}
// 4. JWT-Validierung via Keycloak aktivieren
oauth2ResourceServer {
jwt { }
}
}
return httpSecurity.build()
}
@Bean
@ConditionalOnProperty(name = ["keycloak.jwk-set-uri"])
fun jwtDecoder(): ReactiveJwtDecoder {
return NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri)
.build()
}
/**
* Explizite CORS-Konfigurationsquelle.
*
* Dieser Bean bietet eine detaillierte Steuerung der Cross-Origin-Resource-Sharing-Einstellungen
* und ersetzt die leere Standard-CORS-Konfiguration durch explizite, konfigurierbare Einstellungen.
*
* Schlüsselfunktionen:
* - Umgebungsspezifische erlaubte Ursprünge (Allowed Origins)
* - Umfassende Unterstützung für HTTP-Methoden
* - JWT-bewusste Header-Konfiguration
* - Integration mit Headern aus Gateway-Filtern
* - Performance-optimiertes Preflight-Caching
*
* Die Konfiguration ist darauf ausgelegt, mit typischen Webanwendungs-Architekturen zu funktionieren,
* bei denen ein JavaScript-Frontend API-Aufrufe an das Gateway sendet.
* Definiert die zentrale und einzige CORS-Konfiguration für das Gateway.
*/
@Bean
fun corsConfigurationSource(): CorsConfigurationSource {
val configuration = CorsConfiguration().apply {
// Erlaubte Ursprünge pro Umgebung konfigurierbar
// Entwicklung: localhost-URLs für lokale Tests
// Produktion: domainspezifische URLs für ausgelieferte Anwendungen
allowedOrigins = securityProperties.cors.allowedOrigins.toList()
// Erlaubte HTTP-Methoden umfassende REST-API-Unterstützung
// Enthält alle Standardmethoden plus OPTIONS für Preflight-Anfragen
allowedOriginPatterns = securityProperties.cors.allowedOriginPatterns.toList()
allowedMethods = securityProperties.cors.allowedMethods.toList()
// Erlaubte Request-Header beinhaltet JWT und benutzerdefinierte Header
// Authorization: für JWT Bearer Tokens
// X-Correlation-ID: für Request-Tracing
// Standard-Header: Content-Type, Accept, etc.
allowedHeaders = securityProperties.cors.allowedHeaders.toList()
// Sichtbare Response-Header ermöglicht Client-Zugriff auf benutzerdefinierte Header
// Beinhaltet Header, die von Gateway-Filtern hinzugefügt werden:
// - X-Correlation-ID vom CorrelationIdFilter
// - X-RateLimit-* vom RateLimitingFilter
exposedHeaders = securityProperties.cors.exposedHeaders.toList()
// Credentials erlauben erforderlich für JWT-Authentifizierung
// Aktiviert Cookies und Authorization-Header in Cross-Origin-Anfragen
allowCredentials = securityProperties.cors.allowCredentials
// Preflight-Cache-Dauer Performance-Optimierung
// Reduziert die Anzahl an OPTIONS-Anfragen für wiederholte API-Aufrufe
maxAge = securityProperties.cors.maxAge.seconds
}
return UrlBasedCorsConfigurationSource().apply {
// CORS-Konfiguration auf alle Gateway-Routen anwenden
registerCorsConfiguration("/**", configuration)
}
}
}
/**
* Konfigurationseigenschaften für die Sicherheits-Einstellungen des Gateways.
*
* Ermöglicht umgebungsspezifische Sicherheitskonfiguration über application.yml/-properties.
* Dieser Ansatz erlaubt unterschiedliche Sicherheitseinstellungen für Entwicklung, Test und
* Produktion, ohne Codeänderungen vornehmen zu müssen.
*
* Beispielkonfiguration in application.yml:
* ```yaml
* gateway:
* security:
* cors:
* allowed-origins:
* - http://localhost:3000
* - https://app.meldestelle.at
* allowed-methods:
* - GET
* - POST
* - PUT
* - DELETE
* allow-credentials: true
* max-age: PT2H
* ```
* Konfigurations-Properties für alle sicherheitsrelevanten Einstellungen des Gateways.
*/
@ConfigurationProperties(prefix = "gateway.security")
data class GatewaySecurityProperties(
val cors: CorsProperties = CorsProperties()
val cors: CorsProperties = CorsProperties(),
val publicPaths: List<String> = listOf(
"/",
"/fallback/**",
"/actuator/**",
"/webjars/**",
"/v3/api-docs/**",
"/api/auth/**" // Alle Auth-Endpunkte
)
)
/**
* CORS-spezifische Konfigurationseigenschaften mit sinnvollen Defaults.
*
* Die Default-Werte sind so gewählt, dass sie mit typischen Entwicklungs- und Produktions-Setups funktionieren:
* - Übliche Entwicklungs-URLs (localhost mit Standardports)
* - Produktions-Domain-Muster
* - Volle Unterstützung der REST-API-Methoden
* - Unterstützung für JWT- und Gateway-Filter-Header
* - Sinnvolle Preflight-Cache-Dauer
* DTO für CORS-Properties mit sinnvollen Standardwerten.
*/
data class CorsProperties(
/**
* Erlaubte Ursprünge (Allowed Origins) für CORS-Anfragen.
*
* Defaults unterstützen gängige Entwicklungs- und Produktionsszenarien:
* - localhost:3000 typischer React-Entwicklungsserver
* - localhost:8080 gängiger alternativer Entwicklungsport
* - localhost:4200 typischer Angular-Entwicklungsserver
* - Spezifische Subdomains von meldestelle.at für die Produktion
*
* Kann je Umgebung bei Bedarf überschrieben werden.
*/
val allowedOrigins: Set<String> = setOf(
"http://localhost:3000",
"http://localhost:8080",
"http://localhost:4200",
"https://app.meldestelle.at",
"https://frontend.meldestelle.at",
"https://www.meldestelle.at"
),
/**
* Erlaubte HTTP-Methoden für CORS-Anfragen.
*
* Enthält alle Standard-REST-API-Methoden sowie OPTIONS für Preflight-
* und HEAD für Metadaten-Anfragen.
*/
val allowedMethods: Set<String> = setOf(
"GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "PATCH"
),
/**
* Erlaubte Request-Header für CORS-Anfragen.
*
* Beinhaltet:
* - Standard-Header: Content-Type, Accept, etc.
* - JWT-Authentifizierung: Authorization
* - Gateway-Tracing: X-Correlation-ID
* - Cache-Steuerung: Cache-Control, Pragma
*/
val allowedHeaders: Set<String> = setOf(
"Authorization",
"Content-Type",
"X-Requested-With",
"X-Correlation-ID",
"Accept",
"Origin",
"Cache-Control",
"Pragma"
),
/**
* Sichtbare Response-Header für CORS-Anfragen.
*
* Header, auf die Client-JavaScript in Antworten zugreifen darf.
* Beinhaltet benutzerdefinierte Header, die von Gateway-Filtern hinzugefügt werden:
* - X-Correlation-ID: Request-Tracing (CorrelationIdFilter)
* - X-RateLimit-*: Informationen zum Rate-Limiting (RateLimitingFilter)
* - Standard-Header: Content-Length, Date
*/
val exposedHeaders: Set<String> = setOf(
"X-Correlation-ID",
"X-RateLimit-Limit",
"X-RateLimit-Remaining",
"X-RateLimit-Enabled",
"Content-Length",
"Date"
),
/**
* Credentials in CORS-Anfragen erlauben.
*
* Auf true setzen, um zu unterstützen:
* - JWT Bearer Tokens im Authorization-Header
* - Cookies (falls verwendet)
* - Client-Zertifikate (falls verwendet)
*/
val allowedOriginPatterns: Set<String> = setOf("http://localhost:[*]", "https://*.meldestelle.at"),
val allowedMethods: Set<String> = setOf("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"),
val allowedHeaders: Set<String> = setOf("*"),
val exposedHeaders: Set<String> = setOf("X-Correlation-ID", "X-RateLimit-Limit", "X-RateLimit-Remaining"),
val allowCredentials: Boolean = true,
/**
* Maximales Alter für das Caching von Preflight-Anfragen.
*
* Dauer, für die Browser Preflight-Antworten cachen können, wodurch
* die Anzahl der OPTIONS-Anfragen für wiederholte API-Aufrufe reduziert wird.
* Default: 1 Stunde (guter Kompromiss zwischen Performance und Flexibilität)
*/
val maxAge: Duration = Duration.ofHours(1)
)

View File

@ -1,187 +0,0 @@
# ===================================================================
# Meldestelle API Gateway Configuration
# ===================================================================
server:
port: ${GATEWAY_PORT:8081}
spring:
application:
name: meldestelle-api-gateway
profiles:
active: ${SPRING_PROFILES_ACTIVE:dev,keycloak}
# Security Configuration
security:
oauth2:
resourceserver:
jwt:
issuer-uri: ${KEYCLOAK_ISSUER_URI:http://keycloak:8080/realms/meldestelle}
jwk-set-uri: ${KEYCLOAK_JWK_SET_URI:http://keycloak:8080/realms/meldestelle/protocol/openid-connect/certs}
# Spring Cloud Gateway Configuration
cloud:
gateway:
routes:
# Ping Service Route
- id: ping-service
uri: lb://ping-service
predicates:
- Path=/api/ping/**
filters:
- StripPrefix=2
- name: CircuitBreaker
args:
name: ping-service-cb
fallbackUri: forward:/fallback/ping
# Auth Service Route
- id: auth-service
uri: lb://auth-server
predicates:
- Path=/api/auth/**
filters:
- StripPrefix=2
- name: CircuitBreaker
args:
name: auth-service-cb
fallbackUri: forward:/fallback/auth
# Global CORS Configuration
globalcors:
corsConfigurations:
'[/**]':
allowedOriginPatterns:
- "http://localhost:*"
- "http://127.0.0.1:*"
- "http://web-app:*"
allowedMethods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
- PATCH
allowedHeaders: "*"
allowCredentials: true
exposedHeaders:
- Authorization
- X-User-ID
- X-User-Name
- X-User-Role
# Keycloak Integration Settings
keycloak:
server-url: ${KEYCLOAK_SERVER_URL:http://keycloak:8080}
realm: ${KEYCLOAK_REALM:meldestelle}
client-id: ${KEYCLOAK_CLIENT_ID:api-gateway}
client-secret: ${KEYCLOAK_CLIENT_SECRET:api-gateway-secret-key-change-in-production}
issuer-uri: ${KEYCLOAK_ISSUER_URI:http://keycloak:8080/realms/meldestelle}
jwk-set-uri: ${KEYCLOAK_JWK_SET_URI:http://keycloak:8080/realms/meldestelle/protocol/openid-connect/certs}
# Gateway Security Settings
gateway:
security:
keycloak:
enabled: ${GATEWAY_SECURITY_KEYCLOAK_ENABLED:true}
public-paths: >
/,
/health/**,
/actuator/**,
/api/ping/health,
/api/auth/login,
/api/auth/register,
/api/auth/refresh,
/fallback/**,
/docs/**,
/swagger-ui/**
# Consul Service Discovery
consul:
host: ${CONSUL_HOST:consul}
port: ${CONSUL_PORT:8500}
enabled: ${CONSUL_ENABLED:true}
# Circuit Breaker Configuration
resilience4j:
circuitbreaker:
instances:
ping-service-cb:
registerHealthIndicator: true
slidingWindowSize: 10
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 10s
failureRateThreshold: 50
auth-service-cb:
registerHealthIndicator: true
slidingWindowSize: 10
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 10s
failureRateThreshold: 50
# Actuator Management
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: always
# Logging Configuration
logging:
level:
at.mocode.infrastructure.gateway: DEBUG
org.springframework.security: DEBUG
org.springframework.cloud.gateway: DEBUG
pattern:
console: "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
---
# Development Profile
spring:
config:
activate:
on-profile: dev
keycloak:
server-url: http://localhost:8180
issuer-uri: http://localhost:8180/realms/meldestelle
jwk-set-uri: http://localhost:8180/realms/meldestelle/protocol/openid-connect/certs
logging:
level:
root: INFO
at.mocode: DEBUG
---
# Production Profile
spring:
config:
activate:
on-profile: prod
keycloak:
server-url: ${KEYCLOAK_SERVER_URL}
issuer-uri: ${KEYCLOAK_ISSUER_URI}
jwk-set-uri: ${KEYCLOAK_JWK_SET_URI}
client-secret: ${KEYCLOAK_CLIENT_SECRET}
logging:
level:
root: WARN
at.mocode: INFO
gateway:
security:
public-paths: >
/,
/health,
/api/auth/login,
/api/auth/register

View File

@ -36,23 +36,6 @@ spring:
pool:
max-idle-time: 15s
max-life-time: 60s
globalcors:
cors-configurations:
'[/**]':
allowedOriginPatterns:
- "https://*.meldestelle.at"
- "http://localhost:*"
allowedMethods:
- GET
- POST
- PUT
- DELETE
- PATCH
- OPTIONS
allowedHeaders:
- "*"
allowCredentials: true
maxAge: 3600
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
- name: CircuitBreaker
@ -282,20 +265,3 @@ logging:
max-file-size: 100MB
total-size-cap: 1GB
max-history: 30
# Gateway Security Configuration - JWT Authentication with auth-client
gateway:
security:
jwt:
# Enable JWT authentication via auth-client
enabled: ${GATEWAY_JWT_ENABLED:true}
# JWT secret key for token validation (must match auth-server secret)
secret: ${JWT_SECRET:default-secret-for-development-only-please-change-in-production}
# JWT issuer (must match auth-server issuer)
issuer: ${JWT_ISSUER:meldestelle-auth-server}
# JWT audience (must match auth-server audience)
audience: ${JWT_AUDIENCE:meldestelle-services}
# JWT expiration in minutes
expiration: ${JWT_EXPIRATION:60}

View File

@ -1,27 +1,208 @@
2025-10-05 21:49:40.525 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2025-10-05 21:49:40.564 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 783949 (/home/stefan-mo/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan-mo in /home/stefan-mo/WsMeldestelle/Meldestelle)
2025-10-05 21:49:40.565 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10
2025-10-05 21:49:40.565 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev"
2025-10-05 21:49:41.913 [main] INFO [] o.s.cloud.context.scope.GenericScope - BeanFactory id=548af07a-4d4c-30b3-8388-eaf5c0d95d23
2025-10-05 21:49:44.188 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [After]
2025-10-05 21:49:44.188 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Before]
2025-10-05 21:49:44.188 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Between]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Cookie]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Header]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Host]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Method]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Path]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Query]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [ReadBody]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [RemoteAddr]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [XForwardedRemoteAddr]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Weight]
2025-10-05 21:49:44.189 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [CloudFoundryRouteService]
2025-10-05 21:49:44.880 [main] INFO [] o.s.b.a.e.web.EndpointLinksResolver - Exposing 6 endpoints beneath base path '/actuator'
2025-10-05 21:49:45.585 [main] WARN [] o.s.c.l.c.LoadBalancerCacheAutoConfiguration$LoadBalancerCaffeineWarnLogger - Spring Cloud LoadBalancer is currently working with the default cache. While this cache implementation is useful for development and tests, it's recommended to use Caffeine cache in production.You can switch to using Caffeine cache, by adding it and org.springframework.cache.caffeine.CaffeineCacheManager to the classpath.
2025-10-05 21:49:45.714 [main] INFO [] o.s.b.w.e.netty.NettyWebServer - Netty started on port 8080 (http)
2025-10-05 21:49:45.716 [main] INFO [] o.s.c.c.s.ConsulServiceRegistry - Registering service with consul: NewService{id='meldestelle-8080-2567c504-f48c-4f6e-918e-23b80c37675e', name='meldestelle', tags=[], address='10.0.0.18', meta={secure=false}, port=8080, enableTagOverride=null, check=Check{script='null', dockerContainerID='null', shell='null', interval='10s', ttl='null', http='http://10.0.0.18:8080/actuator/health', method='null', header={}, tcp='null', timeout='null', deregisterCriticalServiceAfter='null', tlsSkipVerify=null, status='null', grpc='null', grpcUseTLS=null}, checks=null}
2025-10-05 21:49:45.865 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Started GatewayApplicationKt in 5.753 seconds (process running for 6.365)
2025-10-05 21:53:53.365 [SpringApplicationShutdownHook] INFO [] o.s.b.w.e.netty.GracefulShutdown - Commencing graceful shutdown. Waiting for active requests to complete
2025-10-05 21:53:53.367 [netty-shutdown] INFO [] o.s.b.w.e.netty.GracefulShutdown - Graceful shutdown complete
2025-10-05 21:53:55.378 [SpringApplicationShutdownHook] INFO [] o.s.c.c.s.ConsulServiceRegistry - Deregistering service with consul: meldestelle-8080-2567c504-f48c-4f6e-918e-23b80c37675e
2025-10-10 09:04:14.977 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2025-10-10 09:04:15.011 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 5959 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle)
2025-10-10 09:04:15.011 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10
2025-10-10 09:04:15.011 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev"
2025-10-10 09:04:16.127 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:04:16.128 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-10-10 09:04:16.144 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 8 ms. Found 0 JPA repository interfaces.
2025-10-10 09:04:16.153 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:04:16.154 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-10-10 09:04:16.162 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 1 ms. Found 0 Redis repository interfaces.
2025-10-10 09:04:16.172 [main] WARN [] o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'conversionServicePostProcessor' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Cannot register bean definition [Root bean: class=org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]] for bean 'conversionServicePostProcessor' since there is already [Root bean: class=org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class]] bound.
2025-10-10 09:04:16.183 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger -
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-10-10 09:04:16.196 [main] ERROR [] o.s.b.d.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'conversionServicePostProcessor', defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
2025-10-10 09:06:36.886 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2025-10-10 09:06:36.993 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 6261 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle)
2025-10-10 09:06:36.993 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10
2025-10-10 09:06:36.994 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev"
2025-10-10 09:06:38.221 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:06:38.223 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-10-10 09:06:38.289 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 58 ms. Found 0 JPA repository interfaces.
2025-10-10 09:06:38.299 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:06:38.300 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-10-10 09:06:38.356 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 48 ms. Found 0 Redis repository interfaces.
2025-10-10 09:06:38.370 [main] WARN [] o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'conversionServicePostProcessor' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Cannot register bean definition [Root bean: class=org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]] for bean 'conversionServicePostProcessor' since there is already [Root bean: class=org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class]] bound.
2025-10-10 09:06:38.383 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger -
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-10-10 09:06:38.400 [main] ERROR [] o.s.b.d.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'conversionServicePostProcessor', defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
2025-10-10 09:52:44.759 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2025-10-10 09:52:44.795 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 11271 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle)
2025-10-10 09:52:44.797 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10
2025-10-10 09:52:44.798 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev"
2025-10-10 09:52:45.840 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:52:45.841 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-10-10 09:52:45.856 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 8 ms. Found 0 JPA repository interfaces.
2025-10-10 09:52:45.864 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:52:45.865 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-10-10 09:52:45.872 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 1 ms. Found 0 Redis repository interfaces.
2025-10-10 09:52:45.881 [main] WARN [] o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'conversionServicePostProcessor' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Cannot register bean definition [Root bean: class=org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]] for bean 'conversionServicePostProcessor' since there is already [Root bean: class=org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class]] bound.
2025-10-10 09:52:45.893 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger -
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-10-10 09:52:45.905 [main] ERROR [] o.s.b.d.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'conversionServicePostProcessor', defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
2025-10-10 09:53:33.524 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2025-10-10 09:53:33.553 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 11704 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle)
2025-10-10 09:53:33.553 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10
2025-10-10 09:53:33.554 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev"
2025-10-10 09:53:34.618 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:53:34.619 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-10-10 09:53:34.634 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 8 ms. Found 0 JPA repository interfaces.
2025-10-10 09:53:34.642 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:53:34.643 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-10-10 09:53:34.650 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 1 ms. Found 0 Redis repository interfaces.
2025-10-10 09:53:34.659 [main] WARN [] o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'conversionServicePostProcessor' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Cannot register bean definition [Root bean: class=org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]] for bean 'conversionServicePostProcessor' since there is already [Root bean: class=org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class]] bound.
2025-10-10 09:53:34.670 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger -
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-10-10 09:53:34.682 [main] ERROR [] o.s.b.d.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'conversionServicePostProcessor', defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
2025-10-10 09:54:30.831 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2025-10-10 09:54:30.929 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 11934 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle)
2025-10-10 09:54:30.930 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10
2025-10-10 09:54:30.930 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev"
2025-10-10 09:54:32.127 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:54:32.128 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-10-10 09:54:32.187 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 52 ms. Found 0 JPA repository interfaces.
2025-10-10 09:54:32.198 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 09:54:32.199 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-10-10 09:54:32.247 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 40 ms. Found 0 Redis repository interfaces.
2025-10-10 09:54:32.261 [main] WARN [] o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'conversionServicePostProcessor' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Cannot register bean definition [Root bean: class=org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]] for bean 'conversionServicePostProcessor' since there is already [Root bean: class=org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; fallback=false; factoryBeanName=null; factoryMethodName=conversionServicePostProcessor; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class]] bound.
2025-10-10 09:54:32.274 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger -
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-10-10 09:54:32.290 [main] ERROR [] o.s.b.d.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'conversionServicePostProcessor', defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
2025-10-10 10:37:24.357 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2025-10-10 10:37:24.386 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 19202 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle)
2025-10-10 10:37:24.387 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10
2025-10-10 10:37:24.387 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev"
2025-10-10 10:37:25.381 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 10:37:25.382 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-10-10 10:37:25.397 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 9 ms. Found 0 JPA repository interfaces.
2025-10-10 10:37:25.406 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 10:37:25.406 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-10-10 10:37:25.414 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 1 ms. Found 0 Redis repository interfaces.
2025-10-10 10:37:25.626 [main] INFO [] o.s.cloud.context.scope.GenericScope - BeanFactory id=3aaa65ed-d935-335c-a017-0d94f6536018
2025-10-10 10:37:26.129 [main] WARN [] o.s.b.w.r.c.AnnotationConfigReactiveWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Failed to initialize dependency 'flyway' of LoadTimeWeaverAware bean 'entityManagerFactory': Error creating bean with name 'flyway' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Failed to instantiate [org.flywaydb.core.Flyway]: Factory method 'flyway' threw exception with message: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception with message: Failed to determine a suitable driver class
2025-10-10 10:37:26.142 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger -
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-10-10 10:37:26.155 [main] ERROR [] o.s.b.d.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (the profiles dev are currently active).
2025-10-10 10:51:40.233 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2025-10-10 10:51:40.328 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 29930 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle)
2025-10-10 10:51:40.328 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10
2025-10-10 10:51:40.329 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev"
2025-10-10 10:51:41.798 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 10:51:41.800 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-10-10 10:51:41.859 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 52 ms. Found 0 JPA repository interfaces.
2025-10-10 10:51:41.869 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-10 10:51:41.870 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-10-10 10:51:41.915 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 39 ms. Found 0 Redis repository interfaces.
2025-10-10 10:51:42.198 [main] INFO [] o.s.cloud.context.scope.GenericScope - BeanFactory id=3aaa65ed-d935-335c-a017-0d94f6536018
2025-10-10 10:51:42.855 [main] WARN [] o.s.b.w.r.c.AnnotationConfigReactiveWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Failed to initialize dependency 'flyway' of LoadTimeWeaverAware bean 'entityManagerFactory': Error creating bean with name 'flyway' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Failed to instantiate [org.flywaydb.core.Flyway]: Factory method 'flyway' threw exception with message: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception with message: Failed to determine a suitable driver class
2025-10-10 10:51:42.870 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger -
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-10-10 10:51:42.887 [main] ERROR [] o.s.b.d.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (the profiles dev are currently active).