From d530487084276510e7b9d18eb14e372ec61b77b6 Mon Sep 17 00:00:00 2001 From: Jamie Albinson Date: Mon, 21 Oct 2024 14:24:18 -0400 Subject: [PATCH 1/3] 15864 Spring Cloud Gate configuration with Swagger --- auth/build.gradle.kts | 5 +- .../auth/AuthApplicationConstants.kt | 9 +- .../auth/config/ApplicationConfig.kt | 17 +- .../reportstream/auth/config/RouteConfig.kt | 28 ++++ .../auth/config/SecurityConfig.kt | 17 +- .../auth/config/SubmissionsConfig.kt | 13 ++ .../auth/controller/AuthController.kt | 47 ------ .../reportstream/auth/model/Environment.kt | 10 ++ .../auth/service/ProxyURIStrategy.kt | 55 ------- auth/src/main/resources/application.yml | 24 +-- .../auth/controller/AuthControllerTest.kt | 146 ------------------ auth/src/test/resources/application.yml | 12 +- 12 files changed, 96 insertions(+), 287 deletions(-) create mode 100644 auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/RouteConfig.kt create mode 100644 auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SubmissionsConfig.kt delete mode 100644 auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/controller/AuthController.kt create mode 100644 auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/model/Environment.kt delete mode 100644 auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/service/ProxyURIStrategy.kt delete mode 100644 auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/AuthControllerTest.kt diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index 9a8b9d8a923..e6d82c00810 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -21,11 +21,14 @@ dependencies { * Spring WebFlux was chosen for this project to be able to better handle periods of high traffic */ implementation("org.springframework.boot:spring-boot-starter-webflux") - implementation("org.springframework.cloud:spring-cloud-gateway-webflux") + implementation("org.springframework.cloud:spring-cloud-starter-gateway") implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server") runtimeOnly("com.nimbusds:oauth2-oidc-sdk:11.19.1") + // Swagger + implementation("org.springdoc:springdoc-openapi-starter-webflux-ui:2.6.0") + testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.security:spring-security-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/AuthApplicationConstants.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/AuthApplicationConstants.kt index 2c2909dd275..ce68c2e0efc 100644 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/AuthApplicationConstants.kt +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/AuthApplicationConstants.kt @@ -6,9 +6,16 @@ package gov.cdc.prime.reportstream.auth object AuthApplicationConstants { /** - * All endpoints defined here + * All Auth service endpoints defined here */ object Endpoints { const val HEALTHCHECK_ENDPOINT_V1 = "/api/v1/healthcheck" } + + /** + * All Submissions service endpoints defined here + */ + object SubmissionsEndpoints { + const val REPORTS_ENDPOINT_V1 = "/api/v1/reports" + } } \ No newline at end of file diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/ApplicationConfig.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/ApplicationConfig.kt index c0aeb78fdbe..77610e3d290 100644 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/ApplicationConfig.kt +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/ApplicationConfig.kt @@ -1,7 +1,7 @@ package gov.cdc.prime.reportstream.auth.config +import gov.cdc.prime.reportstream.auth.model.Environment 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 kotlin.time.TimeSource @@ -10,23 +10,14 @@ import kotlin.time.TimeSource * Simple class to automatically read configuration from application.yml (or environment variable overrides) */ @Configuration -@EnableConfigurationProperties(ProxyConfigurationProperties::class) +@ConfigurationProperties(prefix = "app") class ApplicationConfig( - val proxyConfig: ProxyConfigurationProperties, + var environment: Environment = Environment.LOCAL ) { @Bean fun timeSource(): TimeSource { return TimeSource.Monotonic } -} -@ConfigurationProperties("proxy") -data class ProxyConfigurationProperties( - val pathMappings: List, -) - -data class ProxyPathMapping( - val baseUrl: String, - val pathPrefix: String, -) \ No newline at end of file +} \ No newline at end of file diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/RouteConfig.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/RouteConfig.kt new file mode 100644 index 00000000000..32dc31b2e12 --- /dev/null +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/RouteConfig.kt @@ -0,0 +1,28 @@ +package gov.cdc.prime.reportstream.auth.config + +import gov.cdc.prime.reportstream.auth.AuthApplicationConstants +import org.springframework.cloud.gateway.route.RouteLocator +import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +/** + * Configuration class to set up route forwarding + */ +@Configuration +class RouteConfig( + private val submissionsConfig: SubmissionsConfig +) { + + @Bean + fun routes(builder: RouteLocatorBuilder): RouteLocator { + return builder.routes() + .route { + it + .path(AuthApplicationConstants.SubmissionsEndpoints.REPORTS_ENDPOINT_V1) + .uri(submissionsConfig.baseUrl) + } + .build() + } + +} \ No newline at end of file diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SecurityConfig.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SecurityConfig.kt index 004493a1646..e525d0a2e52 100644 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SecurityConfig.kt +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SecurityConfig.kt @@ -1,6 +1,8 @@ package gov.cdc.prime.reportstream.auth.config import gov.cdc.prime.reportstream.auth.AuthApplicationConstants +import gov.cdc.prime.reportstream.auth.model.Environment +import org.apache.logging.log4j.kotlin.Logging import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity @@ -14,7 +16,9 @@ import org.springframework.security.web.server.SecurityWebFilterChain */ @Configuration @EnableWebFluxSecurity -class SecurityConfig { +class SecurityConfig( + private val applicationConfig: ApplicationConfig +) : Logging { @Bean fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { @@ -23,8 +27,15 @@ class SecurityConfig { authorize // allow health endpoint without authentication .pathMatchers(AuthApplicationConstants.Endpoints.HEALTHCHECK_ENDPOINT_V1).permitAll() - // all other requests must be authenticated - .anyExchange().authenticated() + + // allow unauthenticated access to swagger on local environments + if (applicationConfig.environment == Environment.LOCAL) { + logger.info("Allowing unauthenticated Swagger access at http://localhost:9000/swagger/ui.html") + authorize.pathMatchers("/swagger/**").permitAll() + } + + // all other requests must be authenticated + authorize.anyExchange().authenticated() } .oauth2ResourceServer { it.opaqueToken { } diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SubmissionsConfig.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SubmissionsConfig.kt new file mode 100644 index 00000000000..6abe6ad3f52 --- /dev/null +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SubmissionsConfig.kt @@ -0,0 +1,13 @@ +package gov.cdc.prime.reportstream.auth.config + +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.context.annotation.Configuration + +/** + * Configuration for Submissions microservice + */ +@Configuration +@ConfigurationProperties(prefix = "submissions") +data class SubmissionsConfig( + var baseUrl: String = "http://localhost:8080" +) diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/controller/AuthController.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/controller/AuthController.kt deleted file mode 100644 index e62df018405..00000000000 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/controller/AuthController.kt +++ /dev/null @@ -1,47 +0,0 @@ -package gov.cdc.prime.reportstream.auth.controller - -import gov.cdc.prime.reportstream.auth.service.ProxyURIStrategy -import kotlinx.coroutines.reactive.awaitSingle -import org.apache.logging.log4j.kotlin.Logging -import org.springframework.cloud.gateway.webflux.ProxyExchange -import org.springframework.http.ResponseEntity -import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController -import org.springframework.web.server.ServerWebExchange - -@RestController -class AuthController( - private val proxyURIStrategy: ProxyURIStrategy, -) : Logging { - - /** - * Main workhorse of the application. Handles all incoming requests and properly forwards them given successful - * authentication. Missing or invalid bearer tokens will result in a 401 unauthorized response. - * - * Authentication will be handled by the OAuth 2.0 resource server opaque token configuration - * @see https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/opaque-token.html - * - * Proxying will be handled by the Spring Cloud Gateway library from which the ProxyExchange object is injected - */ - @RequestMapping("**") - suspend fun proxy( - exchange: ServerWebExchange, - proxy: ProxyExchange, - auth: BearerTokenAuthentication, - ): ResponseEntity { - val sub = auth.tokenAttributes["sub"] - val scopes = auth.tokenAttributes["scope"] - - logger.info("Token with sub=$sub and scopes=$scopes is authenticated with Okta") - - val uri = proxyURIStrategy.getTargetURI(exchange.request.uri) - proxy.uri(uri.toString()) - - logger.info("Proxying request to ${exchange.request.method} $uri") - val response = proxy.forward().awaitSingle() - logger.info("Proxy response from ${exchange.request.method} $uri status=${response.statusCode}") - - return response - } -} \ No newline at end of file diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/model/Environment.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/model/Environment.kt new file mode 100644 index 00000000000..55f0e37dfdb --- /dev/null +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/model/Environment.kt @@ -0,0 +1,10 @@ +package gov.cdc.prime.reportstream.auth.model + +/** + * All possible environments the auth app can be running + */ +enum class Environment { + LOCAL, + STAGING, + PRODUCTION +} \ No newline at end of file diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/service/ProxyURIStrategy.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/service/ProxyURIStrategy.kt deleted file mode 100644 index 38686400a11..00000000000 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/service/ProxyURIStrategy.kt +++ /dev/null @@ -1,55 +0,0 @@ -package gov.cdc.prime.reportstream.auth.service - -import gov.cdc.prime.reportstream.auth.config.ApplicationConfig -import org.springframework.context.annotation.Profile -import org.springframework.stereotype.Component -import java.net.URI - -/** - * Implementations are ways to decide the ultimate destination of an incoming request - */ -interface ProxyURIStrategy { - fun getTargetURI(incomingUri: URI): URI -} - -/** - * This implementation decides via the path prefix. Currently used locally for when all services are - * running on different ports of localhost. - * - * Configured under proxyConfig.pathMappings - * - * http://localhost:9000/submissions/health -> http://localhost:8880/health - */ -@Component -@Profile("local") -class PathPrefixProxyURIStrategy( - private val applicationConfig: ApplicationConfig, -) : ProxyURIStrategy { - override fun getTargetURI(incomingUri: URI): URI { - val proxyPathMappings = applicationConfig.proxyConfig.pathMappings - val maybePathMapping = proxyPathMappings.find { incomingUri.path.startsWith(it.pathPrefix) } - return if (maybePathMapping != null) { - val baseUri = URI(maybePathMapping.baseUrl) - val path = incomingUri.path.removePrefix(maybePathMapping.pathPrefix) - URI( - baseUri.scheme, - baseUri.userInfo, - baseUri.host, - baseUri.port, - path, - incomingUri.query, - incomingUri.fragment - ) - } else { - throw IllegalStateException("no configured proxy target in path mappings for path=${incomingUri.path}") - } - } -} - -@Component -@Profile("deployed") -class HostProxyPathURIStrategy : ProxyURIStrategy { - override fun getTargetURI(incomingUri: URI): URI { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/auth/src/main/resources/application.yml b/auth/src/main/resources/application.yml index 6a085c848dd..eea5a2c8ec6 100644 --- a/auth/src/main/resources/application.yml +++ b/auth/src/main/resources/application.yml @@ -1,26 +1,28 @@ spring: application: name: "auth" - profiles: - active: local security: oauth2: resourceserver: opaquetoken: # Set client secret in SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_SECRET env variable client-id: 0oaek8tip2lhrhHce1d7 introspection-uri: https://reportstream.oktapreview.com/oauth2/ausekaai7gUuUtHda1d7/v1/introspect - cloud: - gateway: - proxy: - sensitive: [] # pass authorization and cookie headers downstream (filtered by default) server.port: 9000 -proxy.pathMappings: - - pathPrefix: /reportstream - baseUrl: http://localhost:7071 - - pathPrefix: /submissions - baseUrl: http://localhost:8880 +app: + environment: local + +# submissions microservice configuration +submissions: + baseUrl: http://localhost:8080 + +# Ensure these are disabled in production +springdoc: + swagger-ui: + path: /swagger/ui.html + api-docs: + path: /swagger/api-docs #Uncomment for verbose logging #logging: diff --git a/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/AuthControllerTest.kt b/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/AuthControllerTest.kt deleted file mode 100644 index 8242e7a3780..00000000000 --- a/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/AuthControllerTest.kt +++ /dev/null @@ -1,146 +0,0 @@ -package gov.cdc.prime.reportstream.auth.controller - -import gov.cdc.prime.reportstream.auth.service.ProxyURIStrategy -import okhttp3.mockwebserver.MockResponse -import okhttp3.mockwebserver.MockWebServer -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.kotlin.any -import org.mockito.kotlin.given -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.test.mock.mockito.MockBean -import org.springframework.http.HttpHeaders -import org.springframework.http.MediaType -import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf -import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockOpaqueToken -import org.springframework.test.context.junit.jupiter.SpringExtension -import org.springframework.test.web.reactive.server.WebTestClient -import java.net.URI -import java.nio.charset.Charset -import kotlin.test.Test -import kotlin.test.assertEquals - -@ExtendWith(SpringExtension::class) -@SpringBootTest -@AutoConfigureWebTestClient -class AuthControllerTest @Autowired constructor( - private val webTestClient: WebTestClient, - @MockBean private val mockedUriStrategy: ProxyURIStrategy, -) { - - private val server: MockWebServer = MockWebServer() - - @BeforeEach - fun setUp() { - server.start() - } - - @AfterEach - fun tearDown() { - server.shutdown() - } - - @Test - fun `successful proxy`() { - server.enqueue( - MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN) - .setBody("hello world!") - ) - - val incomingUri = URI("/service/path") - val outgoingUri = URI(server.url("/path").toString()) - given(mockedUriStrategy.getTargetURI(incomingUri)).willReturn(outgoingUri) - - webTestClient - .mutateWith(csrf()) - .mutateWith( - mockOpaqueToken() - .attributes { map -> - map["sub"] = "sub" - map["scope"] = listOf("scope1", "scope2") - } - ) - .post() - .uri("/service/path") - .accept(MediaType.TEXT_PLAIN) - .headers { headers -> - headers.add("x-test-header", "Pass this along") - } - .bodyValue("body") - .exchange() - // assertions on the response received from the mock server - .expectStatus().isOk - .expectHeader().contentType(MediaType.TEXT_PLAIN) - .expectBody(String::class.java).isEqualTo("hello world!") - - // assertions on recorded request to proxy - val recordedRequest = server.takeRequest() - assertEquals( - recordedRequest.headers.get("x-test-header"), - "Pass this along" - ) - assertEquals( - recordedRequest.body.readString(Charset.defaultCharset()), - "body" - ) - } - - @Test - fun `authorization fails in proxied server`() { - server.enqueue(MockResponse().setResponseCode(403)) - - given(mockedUriStrategy.getTargetURI(any())) - .willReturn(URI(server.url("/").toString())) - - webTestClient - .mutateWith(csrf()) - .mutateWith( - mockOpaqueToken() - .attributes { map -> - map["sub"] = "sub" - map["scope"] = listOf("scope1", "scope2") - } - ) - .post() - .uri("/random") - .accept(MediaType.TEXT_PLAIN) - .headers { headers -> - headers.add("x-test-header", "Pass this along") - } - .bodyValue("body") - .exchange() - // assertions on the response received from the mock server - .expectStatus().isForbidden - - // assertions on recorded request to proxy - val recordedRequest = server.takeRequest() - assertEquals( - recordedRequest.headers.get("x-test-header"), - "Pass this along" - ) - assertEquals( - recordedRequest.body.readString(Charset.defaultCharset()), - "body" - ) - } - - @Test - fun `authentication fails`() { - given(mockedUriStrategy.getTargetURI(any())) - .willReturn(URI(server.url("/").toString())) - - webTestClient - .mutateWith(csrf()) - .post() - .uri("/random") - .exchange() - .expectStatus().isUnauthorized - - // no request should be made to server - assertEquals(server.requestCount, 0) - } -} \ No newline at end of file diff --git a/auth/src/test/resources/application.yml b/auth/src/test/resources/application.yml index 2925d96b9de..d4af5986529 100644 --- a/auth/src/test/resources/application.yml +++ b/auth/src/test/resources/application.yml @@ -10,15 +10,7 @@ spring: client-id: mockClient client-secret: mockSecret introspection-uri: https://localhost:9999/oauth2/default/v1/introspect # should never be hit - cloud: - gateway: - proxy: - sensitive: [] # pass authorization and cookie headers downstream (filtered by default) -server.port: 9000 -proxy.pathMappings: - - pathPrefix: /reportstream - baseUrl: http://localhost:7071 - - pathPrefix: /submissions - baseUrl: http://localhost:8880 +server.port: 9000 +app.environment: local From 3403b457cf3290576e04e2d56e21fb916300cae7 Mon Sep 17 00:00:00 2001 From: Jamie Albinson Date: Mon, 21 Oct 2024 14:52:53 -0400 Subject: [PATCH 2/3] add basic healthcheck test --- .../auth/controller/HealthControllerTest.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/HealthControllerTest.kt diff --git a/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/HealthControllerTest.kt b/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/HealthControllerTest.kt new file mode 100644 index 00000000000..4688d4a7808 --- /dev/null +++ b/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/HealthControllerTest.kt @@ -0,0 +1,32 @@ +package gov.cdc.prime.reportstream.auth.controller + +import gov.cdc.prime.reportstream.auth.AuthApplicationConstants +import gov.cdc.prime.reportstream.auth.model.ApplicationStatus +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf +import org.springframework.test.context.junit.jupiter.SpringExtension +import org.springframework.test.web.reactive.server.WebTestClient +import kotlin.test.Test + +@ExtendWith(SpringExtension::class) +@SpringBootTest +@AutoConfigureWebTestClient +class HealthControllerTest @Autowired constructor( + private val webTestClient: WebTestClient +) { + + @Test + fun `successful healthcheck`() { + webTestClient + .mutateWith(csrf()) + .get() + .uri(AuthApplicationConstants.Endpoints.HEALTHCHECK_ENDPOINT_V1) + .exchange() + .expectStatus().isOk + .expectBody(ApplicationStatus::class.java) + } + +} \ No newline at end of file From 9d0dc6f7471b173f2dd41fd15b9ea1afd7208bf0 Mon Sep 17 00:00:00 2001 From: Jamie Albinson Date: Tue, 22 Oct 2024 14:26:54 -0400 Subject: [PATCH 3/3] PR feedback --- .../prime/reportstream/auth/config/ApplicationConfig.kt | 3 +-- .../gov/cdc/prime/reportstream/auth/config/RouteConfig.kt | 3 +-- .../cdc/prime/reportstream/auth/config/SecurityConfig.kt | 3 ++- .../prime/reportstream/auth/config/SubmissionsConfig.kt | 4 ++-- .../gov/cdc/prime/reportstream/auth/model/Environment.kt | 2 +- .../reportstream/auth/controller/HealthControllerTest.kt | 5 +---- .../gov/cdc/prime/reportstream/shared/Submission.kt | 2 +- .../reportstream/submissions/config/SecurityConfig.kt | 1 + .../test/kotlin/SubmissionControllerIntegrationTest.kt | 2 -- submissions/src/test/kotlin/SubmissionControllerTest.kt | 8 -------- 10 files changed, 10 insertions(+), 23 deletions(-) diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/ApplicationConfig.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/ApplicationConfig.kt index 77610e3d290..7c8396fb173 100644 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/ApplicationConfig.kt +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/ApplicationConfig.kt @@ -12,12 +12,11 @@ import kotlin.time.TimeSource @Configuration @ConfigurationProperties(prefix = "app") class ApplicationConfig( - var environment: Environment = Environment.LOCAL + var environment: Environment = Environment.LOCAL, ) { @Bean fun timeSource(): TimeSource { return TimeSource.Monotonic } - } \ No newline at end of file diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/RouteConfig.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/RouteConfig.kt index 32dc31b2e12..d1aac8c15e6 100644 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/RouteConfig.kt +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/RouteConfig.kt @@ -11,7 +11,7 @@ import org.springframework.context.annotation.Configuration */ @Configuration class RouteConfig( - private val submissionsConfig: SubmissionsConfig + private val submissionsConfig: SubmissionsConfig, ) { @Bean @@ -24,5 +24,4 @@ class RouteConfig( } .build() } - } \ No newline at end of file diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SecurityConfig.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SecurityConfig.kt index e525d0a2e52..5e3a97f12dc 100644 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SecurityConfig.kt +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SecurityConfig.kt @@ -17,12 +17,13 @@ import org.springframework.security.web.server.SecurityWebFilterChain @Configuration @EnableWebFluxSecurity class SecurityConfig( - private val applicationConfig: ApplicationConfig + private val applicationConfig: ApplicationConfig, ) : Logging { @Bean fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { http + .csrf { it.disable() } // TODO: re-enable after 16312 .authorizeExchange { authorize -> authorize // allow health endpoint without authentication diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SubmissionsConfig.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SubmissionsConfig.kt index 6abe6ad3f52..5397b89032b 100644 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SubmissionsConfig.kt +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/config/SubmissionsConfig.kt @@ -9,5 +9,5 @@ import org.springframework.context.annotation.Configuration @Configuration @ConfigurationProperties(prefix = "submissions") data class SubmissionsConfig( - var baseUrl: String = "http://localhost:8080" -) + var baseUrl: String = "http://localhost:8080", +) \ No newline at end of file diff --git a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/model/Environment.kt b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/model/Environment.kt index 55f0e37dfdb..ec4f1cb9b0c 100644 --- a/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/model/Environment.kt +++ b/auth/src/main/kotlin/gov/cdc/prime/reportstream/auth/model/Environment.kt @@ -6,5 +6,5 @@ package gov.cdc.prime.reportstream.auth.model enum class Environment { LOCAL, STAGING, - PRODUCTION + PRODUCTION, } \ No newline at end of file diff --git a/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/HealthControllerTest.kt b/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/HealthControllerTest.kt index 4688d4a7808..9a643e15c11 100644 --- a/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/HealthControllerTest.kt +++ b/auth/src/test/kotlin/gov/cdc/prime/reportstream/auth/controller/HealthControllerTest.kt @@ -6,7 +6,6 @@ import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient import org.springframework.boot.test.context.SpringBootTest -import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf import org.springframework.test.context.junit.jupiter.SpringExtension import org.springframework.test.web.reactive.server.WebTestClient import kotlin.test.Test @@ -15,18 +14,16 @@ import kotlin.test.Test @SpringBootTest @AutoConfigureWebTestClient class HealthControllerTest @Autowired constructor( - private val webTestClient: WebTestClient + private val webTestClient: WebTestClient, ) { @Test fun `successful healthcheck`() { webTestClient - .mutateWith(csrf()) .get() .uri(AuthApplicationConstants.Endpoints.HEALTHCHECK_ENDPOINT_V1) .exchange() .expectStatus().isOk .expectBody(ApplicationStatus::class.java) } - } \ No newline at end of file diff --git a/shared/src/main/kotlin/gov/cdc/prime/reportstream/shared/Submission.kt b/shared/src/main/kotlin/gov/cdc/prime/reportstream/shared/Submission.kt index 33b44311ee9..8d8dd2e11d2 100644 --- a/shared/src/main/kotlin/gov/cdc/prime/reportstream/shared/Submission.kt +++ b/shared/src/main/kotlin/gov/cdc/prime/reportstream/shared/Submission.kt @@ -23,7 +23,7 @@ data class Submission( val bodyURL: String, @JsonIgnore val detail: String? = null, - val timestamp: OffsetDateTime? = null + val timestamp: OffsetDateTime? = null, ) { companion object { /** diff --git a/submissions/src/main/kotlin/gov/cdc/prime/reportstream/submissions/config/SecurityConfig.kt b/submissions/src/main/kotlin/gov/cdc/prime/reportstream/submissions/config/SecurityConfig.kt index cdfa64f27d4..437bebe4921 100644 --- a/submissions/src/main/kotlin/gov/cdc/prime/reportstream/submissions/config/SecurityConfig.kt +++ b/submissions/src/main/kotlin/gov/cdc/prime/reportstream/submissions/config/SecurityConfig.kt @@ -17,6 +17,7 @@ class SecurityConfig { @Bean fun filterChain(http: HttpSecurity): SecurityFilterChain { http + .csrf { it.disable() } // TODO: re-enable after 16312 .authorizeHttpRequests { authorize -> authorize // TODO: add routes which require authentication here when required diff --git a/submissions/src/test/kotlin/SubmissionControllerIntegrationTest.kt b/submissions/src/test/kotlin/SubmissionControllerIntegrationTest.kt index dbfcd9934dd..f2c87c11f50 100644 --- a/submissions/src/test/kotlin/SubmissionControllerIntegrationTest.kt +++ b/submissions/src/test/kotlin/SubmissionControllerIntegrationTest.kt @@ -21,7 +21,6 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock import org.springframework.boot.test.context.SpringBootTest import org.springframework.context.annotation.Import import org.springframework.http.MediaType -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.DynamicPropertyRegistry import org.springframework.test.context.DynamicPropertySource @@ -97,7 +96,6 @@ class SubmissionControllerIntegrationTest { mockMvc.perform( MockMvcRequestBuilders.post("/api/v1/reports") - .with(csrf()) .content(requestBody) .contentType(MediaType.valueOf("application/hl7-v2")) .header("client_id", "testClient") diff --git a/submissions/src/test/kotlin/SubmissionControllerTest.kt b/submissions/src/test/kotlin/SubmissionControllerTest.kt index 2c552872834..74314d5b291 100644 --- a/submissions/src/test/kotlin/SubmissionControllerTest.kt +++ b/submissions/src/test/kotlin/SubmissionControllerTest.kt @@ -35,7 +35,6 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest import org.springframework.boot.test.mock.mockito.MockBean import org.springframework.context.annotation.Import import org.springframework.http.MediaType -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders import org.springframework.test.web.servlet.result.MockMvcResultMatchers @@ -129,7 +128,6 @@ class SubmissionControllerTest { mockMvc.perform( MockMvcRequestBuilders.post("/api/v1/reports") - .with(csrf()) .content(requestBody) .contentType(MediaType.valueOf("application/hl7-v2")) .header("client_id", "testClient") @@ -176,7 +174,6 @@ class SubmissionControllerTest { mockMvc.perform( MockMvcRequestBuilders.post("/api/v1/reports") - .with(csrf()) .content(requestBody) .contentType(MediaType.valueOf("application/fhir+ndjson")) .header("client_id", "testClient") @@ -208,7 +205,6 @@ class SubmissionControllerTest { mockMvc.perform( MockMvcRequestBuilders.post("/api/v1/reports") - .with(csrf()) .content(requestBody) .contentType(MediaType.APPLICATION_JSON) .header("client_id", "testClient") @@ -225,7 +221,6 @@ class SubmissionControllerTest { mockMvc.perform( MockMvcRequestBuilders.post("/api/v1/reports") - .with(csrf()) .content(requestBody) .contentType(MediaType.valueOf("application/hl7-v2")) .header("payloadname", "testPayload") @@ -248,7 +243,6 @@ class SubmissionControllerTest { mockMvc.perform( MockMvcRequestBuilders.post("/api/v1/reports") - .with(csrf()) .content(requestBody) .contentType(MediaType.parseMediaType("application/hl7-v2")) .header("client_id", "testClient") @@ -271,7 +265,6 @@ class SubmissionControllerTest { mockMvc.perform( MockMvcRequestBuilders.post("/api/v1/reports") - .with(csrf()) .content(requestBody) .contentType(MediaType.parseMediaType("application/hl7-v2")) .header("client_id", "testClient") @@ -310,7 +303,6 @@ class SubmissionControllerTest { mockMvc.perform( MockMvcRequestBuilders.post("/api/v1/reports") - .with(csrf()) .content(requestBody) .contentType(MediaType.valueOf("application/hl7-v2")) .header("client_id", "testClient")