diff --git a/build.gradle.kts b/build.gradle.kts index 1c840677..0aff5e97 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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 { + compilerOptions { + freeCompilerArgs.add("-Xannotation-default-target=param-property") + } + } } // ################################################################## diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 614c3b30..75ae87db 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -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", diff --git a/infrastructure/gateway/build.gradle.kts b/infrastructure/gateway/build.gradle.kts index 1856690c..f5e6f8aa 100644 --- a/infrastructure/gateway/build.gradle.kts +++ b/infrastructure/gateway/build.gradle.kts @@ -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 { diff --git a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/config/JwtConfiguration.kt b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/config/JwtConfiguration.kt deleted file mode 100644 index 295152e1..00000000 --- a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/config/JwtConfiguration.kt +++ /dev/null @@ -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 - ) -} diff --git a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/JwtAuthenticationFilter.kt b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/JwtAuthenticationFilter.kt deleted file mode 100644 index b5cbdd49..00000000 --- a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/JwtAuthenticationFilter.kt +++ /dev/null @@ -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 { - 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 { - - // 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): 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 { - 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 -} diff --git a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/SecurityConfig.kt b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/SecurityConfig.kt index 31e6125c..403857fa 100644 --- a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/SecurityConfig.kt +++ b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/SecurityConfig.kt @@ -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 = 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 = 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 = 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 = 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 = 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 = setOf("http://localhost:[*]", "https://*.meldestelle.at"), + val allowedMethods: Set = setOf("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"), + val allowedHeaders: Set = setOf("*"), + val exposedHeaders: Set = 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) ) diff --git a/infrastructure/gateway/src/main/resources/application-keycloak-complete.yml b/infrastructure/gateway/src/main/resources/application-keycloak-complete.yml deleted file mode 100644 index 6476081f..00000000 --- a/infrastructure/gateway/src/main/resources/application-keycloak-complete.yml +++ /dev/null @@ -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 diff --git a/infrastructure/gateway/src/main/resources/application.yml b/infrastructure/gateway/src/main/resources/application.yml index a1092379..183d79af 100644 --- a/infrastructure/gateway/src/main/resources/application.yml +++ b/infrastructure/gateway/src/main/resources/application.yml @@ -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} - - diff --git a/logs/gateway.log b/logs/gateway.log index b35cb8ba..34efadec 100644 --- a/logs/gateway.log +++ b/logs/gateway.log @@ -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). +