From 59de112a5e1d5047a1e3bd3b76f1b854df1dcd9b Mon Sep 17 00:00:00 2001 From: Chris Searle Date: Tue, 11 Jun 2024 14:18:20 +0200 Subject: [PATCH] ktlint 1.3.0 --- .../src/main/kotlin/Application.kt | 16 +- .../src/main/kotlin/JsonUtils.kt | 11 +- .../src/main/kotlin/Notifikasjon.kt | 59 +++---- .../src/main/kotlin/SendNotifikasjon.kt | 34 ++-- .../src/main/kotlin/Soeknad.kt | 2 +- .../src/test/kotlin/NotifikasjonTest.kt | 147 +++++++++--------- .../src/test/kotlin/SendNotifikasjonTest.kt | 20 ++- .../src/main/kotlin/Application.kt | 7 +- .../src/main/kotlin/auth/Authentication.kt | 15 +- .../auth/ClientCredentialAuthProvider.kt | 61 ++++---- ...tpClient.kt => DefaultOAuth2HttpClient.kt} | 39 ++--- .../src/main/kotlin/auth/sts/StsSoapClient.kt | 41 ++--- .../src/main/kotlin/config/Config.kt | 49 +++--- .../kotlin/config/SimuleringOppdragConfig.kt | 68 ++++---- .../config/SoapSecurityMaskSensitiveHelper.kt | 5 +- .../kotlin/config/TilbakekrevingConfig.kt | 46 +++--- .../src/main/kotlin/routes/Http.kt | 119 +++++++++----- .../src/main/kotlin/routes/InternalRoute.kt | 7 +- .../kotlin/routes/SimuleringOppdragRoute.kt | 4 +- .../main/kotlin/routes/TilbakekrevingRoute.kt | 4 +- .../src/test/kotlin/ApplicationTest.kt | 19 ++- 21 files changed, 435 insertions(+), 338 deletions(-) rename apps/etterlatte-proxy/src/main/kotlin/auth/{DefaultOauth2HttpClient.kt => DefaultOAuth2HttpClient.kt} (55%) diff --git a/apps/etterlatte-notifikasjoner/src/main/kotlin/Application.kt b/apps/etterlatte-notifikasjoner/src/main/kotlin/Application.kt index 51231649a..d9da6eedc 100644 --- a/apps/etterlatte-notifikasjoner/src/main/kotlin/Application.kt +++ b/apps/etterlatte-notifikasjoner/src/main/kotlin/Application.kt @@ -2,13 +2,15 @@ package no.nav.etterlatte import no.nav.helse.rapids_rivers.RapidApplication - fun main() { - val env = System.getenv().toMutableMap().apply { - put("KAFKA_CONSUMER_GROUP_ID", get("NAIS_APP_NAME")!!.replace("-", "")) - } + val env = + System.getenv().toMutableMap().apply { + put("KAFKA_CONSUMER_GROUP_ID", get("NAIS_APP_NAME")!!.replace("-", "")) + } val sendNotifikasjonApp = SendNotifikasjon(env) - RapidApplication.create(env).also { - Notifikasjon(sendNotifikasjonApp,it) - }.start() + RapidApplication + .create(env) + .also { + Notifikasjon(sendNotifikasjonApp, it) + }.start() } \ No newline at end of file diff --git a/apps/etterlatte-notifikasjoner/src/main/kotlin/JsonUtils.kt b/apps/etterlatte-notifikasjoner/src/main/kotlin/JsonUtils.kt index 60de52876..1478968ae 100644 --- a/apps/etterlatte-notifikasjoner/src/main/kotlin/JsonUtils.kt +++ b/apps/etterlatte-notifikasjoner/src/main/kotlin/JsonUtils.kt @@ -6,8 +6,9 @@ import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -val mapper: ObjectMapper = jacksonObjectMapper() - .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) - .registerModule(JavaTimeModule()) +val mapper: ObjectMapper = + jacksonObjectMapper() + .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .registerModule(JavaTimeModule()) \ No newline at end of file diff --git a/apps/etterlatte-notifikasjoner/src/main/kotlin/Notifikasjon.kt b/apps/etterlatte-notifikasjoner/src/main/kotlin/Notifikasjon.kt index 01392baa7..eb73c5eb6 100644 --- a/apps/etterlatte-notifikasjoner/src/main/kotlin/Notifikasjon.kt +++ b/apps/etterlatte-notifikasjoner/src/main/kotlin/Notifikasjon.kt @@ -1,6 +1,5 @@ package no.nav.etterlatte -import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.module.kotlin.readValue import kotlinx.coroutines.runBlocking import no.nav.helse.rapids_rivers.JsonMessage @@ -10,47 +9,51 @@ import no.nav.helse.rapids_rivers.River import org.slf4j.Logger import org.slf4j.LoggerFactory - -class Notifikasjon(private val sendNotifikasjon: SendNotifikasjon, rapidsConnection: RapidsConnection) : - River.PacketListener { - +class Notifikasjon( + private val sendNotifikasjon: SendNotifikasjon, + rapidsConnection: RapidsConnection +) : River.PacketListener { private val logger: Logger = LoggerFactory.getLogger(Notifikasjon::class.java) private val rapid = rapidsConnection init { - River(rapidsConnection).apply { - validate { it.demandValue("@event_name", "soeknad_innsendt") } - validate { it.requireKey("@dokarkivRetur") } - validate { it.requireKey("@fnr_soeker") } - validate { it.requireKey("@skjema_info") } - validate { it.requireKey("@lagret_soeknad_id") } - }.register(this) + River(rapidsConnection) + .apply { + validate { it.demandValue("@event_name", "soeknad_innsendt") } + validate { it.requireKey("@dokarkivRetur") } + validate { it.requireKey("@fnr_soeker") } + validate { it.requireKey("@skjema_info") } + validate { it.requireKey("@lagret_soeknad_id") } + }.register(this) } - override fun onPacket(packet: JsonMessage, context: MessageContext) { + override fun onPacket( + packet: JsonMessage, + context: MessageContext + ) { runBlocking { val soeknad = mapper.readValue(packet["@skjema_info"].toString()) sendNotifikasjon.sendMessage(soeknad) val journalpostId = packet["@dokarkivRetur"]["journalpostId"] - JsonMessage.newMessage( - mapOf( - "@event_name" to "notifikasjon_sendt", - "@lagret_soeknad_id" to packet["@lagret_soeknad_id"], - "@journalpostId" to journalpostId, - "@notifikasjon" to "Notifikasjon sendt", - ) - ).apply { - try { - rapid.publish("SendNotifikasjon " + journalpostId.textValue(), toJson()) - } catch (err: Exception) { - logger.error("Uhaandtert feilsituasjon. Ingen notifikasjon opprettet: ", err) + JsonMessage + .newMessage( + mapOf( + "@event_name" to "notifikasjon_sendt", + "@lagret_soeknad_id" to packet["@lagret_soeknad_id"], + "@journalpostId" to journalpostId, + "@notifikasjon" to "Notifikasjon sendt" + ) + ).apply { + try { + rapid.publish("SendNotifikasjon " + journalpostId.textValue(), toJson()) + } catch (err: Exception) { + logger.error("Uhaandtert feilsituasjon. Ingen notifikasjon opprettet: ", err) + } } - - } logger.info("Notifikasjon til bruker opprettet") } } -} +} \ No newline at end of file diff --git a/apps/etterlatte-notifikasjoner/src/main/kotlin/SendNotifikasjon.kt b/apps/etterlatte-notifikasjoner/src/main/kotlin/SendNotifikasjon.kt index cec08d86e..c4ece88e3 100644 --- a/apps/etterlatte-notifikasjoner/src/main/kotlin/SendNotifikasjon.kt +++ b/apps/etterlatte-notifikasjoner/src/main/kotlin/SendNotifikasjon.kt @@ -1,6 +1,5 @@ package no.nav.etterlatte -import com.fasterxml.jackson.databind.JsonNode import no.nav.brukernotifikasjon.schemas.builders.BeskjedInputBuilder import no.nav.brukernotifikasjon.schemas.builders.NokkelInputBuilder import no.nav.brukernotifikasjon.schemas.input.BeskjedInput @@ -37,11 +36,12 @@ class SendNotifikasjon( internal fun opprettBeskjed(type: Soeknad.Type): BeskjedInput { val now = LocalDateTime.now(ZoneOffset.UTC) val weekFromNow = now.plusDays(7) - val tekst = when (type) { - Soeknad.Type.GJENLEVENDEPENSJON -> "Vi har mottatt søknaden din om gjenlevendepensjon" - Soeknad.Type.BARNEPENSJON -> "Vi har mottatt søknaden din om barnepensjon" - Soeknad.Type.OMSTILLINGSSTOENAD -> "Vi har mottatt søknaden din om omstillingsstønad" - } + val tekst = + when (type) { + Soeknad.Type.GJENLEVENDEPENSJON -> "Vi har mottatt søknaden din om gjenlevendepensjon" + Soeknad.Type.BARNEPENSJON -> "Vi har mottatt søknaden din om barnepensjon" + Soeknad.Type.OMSTILLINGSSTOENAD -> "Vi har mottatt søknaden din om omstillingsstønad" + } return BeskjedInputBuilder() .withTidspunkt(LocalDateTime.now(ZoneOffset.UTC)) @@ -52,15 +52,19 @@ class SendNotifikasjon( .build() } - private fun opprettNokkel(ident: String) = NokkelInputBuilder() - .withEventId(UUID.randomUUID().toString()) - .withGrupperingsId(grupperingsId) - .withNamespace(namespace) - .withAppnavn(appname) - .withFodselsnummer(ident) - .build() + private fun opprettNokkel(ident: String) = + NokkelInputBuilder() + .withEventId(UUID.randomUUID().toString()) + .withGrupperingsId(grupperingsId) + .withNamespace(namespace) + .withAppnavn(appname) + .withFodselsnummer(ident) + .build() - private fun send(nokkel: NokkelInput, beskjed: BeskjedInput) = try { + private fun send( + nokkel: NokkelInput, + beskjed: BeskjedInput + ) = try { producer.send(ProducerRecord(brukernotifikasjontopic, nokkel, beskjed)).get(10, TimeUnit.SECONDS) } catch (e: Exception) { logger.error( @@ -68,4 +72,4 @@ class SendNotifikasjon( e ) } -} +} \ No newline at end of file diff --git a/apps/etterlatte-notifikasjoner/src/main/kotlin/Soeknad.kt b/apps/etterlatte-notifikasjoner/src/main/kotlin/Soeknad.kt index 230c2bdf4..b409a05d9 100644 --- a/apps/etterlatte-notifikasjoner/src/main/kotlin/Soeknad.kt +++ b/apps/etterlatte-notifikasjoner/src/main/kotlin/Soeknad.kt @@ -22,4 +22,4 @@ data class Innsender( data class Foedselsnummer( @JsonProperty("svar") val value: String -) +) \ No newline at end of file diff --git a/apps/etterlatte-notifikasjoner/src/test/kotlin/NotifikasjonTest.kt b/apps/etterlatte-notifikasjoner/src/test/kotlin/NotifikasjonTest.kt index 036b410a0..4af8b5923 100644 --- a/apps/etterlatte-notifikasjoner/src/test/kotlin/NotifikasjonTest.kt +++ b/apps/etterlatte-notifikasjoner/src/test/kotlin/NotifikasjonTest.kt @@ -1,4 +1,3 @@ -import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.module.kotlin.readValue import io.mockk.mockk import no.nav.brukernotifikasjon.schemas.input.BeskjedInput @@ -20,14 +19,16 @@ internal class NotifikasjonTest { private val mockKafkaProducer = MockProducer(true, mockk(relaxed = true), mockk(relaxed = true)) - private val sendMelding = SendNotifikasjon( - mapOf( - "BRUKERNOTIFIKASJON_BESKJED_TOPIC" to "test_topic", - "BRUKERNOTIFIKASJON_KAFKA_GROUP_ID" to "bah", - "NAIS_NAMESPACE" to "etterlatte", - "NAIS_NAME" to "etterlatte-notifikasjoner" - ), mockKafkaProducer - ) + private val sendMelding = + SendNotifikasjon( + mapOf( + "BRUKERNOTIFIKASJON_BESKJED_TOPIC" to "test_topic", + "BRUKERNOTIFIKASJON_KAFKA_GROUP_ID" to "bah", + "NAIS_NAMESPACE" to "etterlatte", + "NAIS_NAME" to "etterlatte-notifikasjoner" + ), + mockKafkaProducer + ) @BeforeEach fun before() { @@ -39,28 +40,28 @@ internal class NotifikasjonTest { val json = this::class.java.getResource("gjenlevendepensjon.json")!!.readText() val soeknad: Soeknad = mapper.readValue(json) - val inspector = TestRapid() - .apply { - Notifikasjon( - sendMelding, - this - ) - } - .apply { - sendTestMessage( - JsonMessage.newMessage( - mapOf( - "@event_name" to "soeknad_innsendt", - "@dokarkivRetur" to "123456", - "@fnr_soeker" to "07106123912", - "@skjema_info" to mapper.readTree(json), - "@lagret_soeknad_id" to "4", - "@dokarkivRetur" to (mapOf("journalpostId" to "3")) - ) + val inspector = + TestRapid() + .apply { + Notifikasjon( + sendMelding, + this + ) + }.apply { + sendTestMessage( + JsonMessage + .newMessage( + mapOf( + "@event_name" to "soeknad_innsendt", + "@dokarkivRetur" to "123456", + "@fnr_soeker" to "07106123912", + "@skjema_info" to mapper.readTree(json), + "@lagret_soeknad_id" to "4", + "@dokarkivRetur" to (mapOf("journalpostId" to "3")) + ) + ).toJson() ) - .toJson() - ) - }.inspektør + }.inspektør assertEquals("notifikasjon_sendt", inspector.message(0).get("@event_name").asText()) assertEquals("Notifikasjon sendt", inspector.message(0).get("@notifikasjon").asText()) @@ -83,28 +84,28 @@ internal class NotifikasjonTest { val json = this::class.java.getResource("barnepensjon.json")!!.readText() val soeknad: Soeknad = mapper.readValue(json) - val inspector = TestRapid() - .apply { - Notifikasjon( - sendMelding, - this - ) - } - .apply { - sendTestMessage( - JsonMessage.newMessage( - mapOf( - "@event_name" to "soeknad_innsendt", - "@dokarkivRetur" to "123456", - "@fnr_soeker" to "07106123912", - "@skjema_info" to mapper.readTree(json), - "@lagret_soeknad_id" to "4", - "@dokarkivRetur" to (mapOf("journalpostId" to "5")) - ) + val inspector = + TestRapid() + .apply { + Notifikasjon( + sendMelding, + this ) - .toJson() - ) - }.inspektør + }.apply { + sendTestMessage( + JsonMessage + .newMessage( + mapOf( + "@event_name" to "soeknad_innsendt", + "@dokarkivRetur" to "123456", + "@fnr_soeker" to "07106123912", + "@skjema_info" to mapper.readTree(json), + "@lagret_soeknad_id" to "4", + "@dokarkivRetur" to (mapOf("journalpostId" to "5")) + ) + ).toJson() + ) + }.inspektør assertEquals("notifikasjon_sendt", inspector.message(0).get("@event_name").asText()) assertEquals("Notifikasjon sendt", inspector.message(0).get("@notifikasjon").asText()) @@ -124,28 +125,28 @@ internal class NotifikasjonTest { val json = this::class.java.getResource("omstillingsstoenad.json")!!.readText() val soeknad: Soeknad = mapper.readValue(json) - val inspector = TestRapid() - .apply { - Notifikasjon( - sendMelding, - this - ) - } - .apply { - sendTestMessage( - JsonMessage.newMessage( - mapOf( - "@event_name" to "soeknad_innsendt", - "@dokarkivRetur" to "123456", - "@fnr_soeker" to "07106123912", - "@skjema_info" to mapper.readTree(json), - "@lagret_soeknad_id" to "4", - "@dokarkivRetur" to (mapOf("journalpostId" to "5")) - ) + val inspector = + TestRapid() + .apply { + Notifikasjon( + sendMelding, + this + ) + }.apply { + sendTestMessage( + JsonMessage + .newMessage( + mapOf( + "@event_name" to "soeknad_innsendt", + "@dokarkivRetur" to "123456", + "@fnr_soeker" to "07106123912", + "@skjema_info" to mapper.readTree(json), + "@lagret_soeknad_id" to "4", + "@dokarkivRetur" to (mapOf("journalpostId" to "5")) + ) + ).toJson() ) - .toJson() - ) - }.inspektør + }.inspektør assertEquals("notifikasjon_sendt", inspector.message(0).get("@event_name").asText()) assertEquals("Notifikasjon sendt", inspector.message(0).get("@notifikasjon").asText()) @@ -162,4 +163,4 @@ internal class NotifikasjonTest { mockKafkaProducer.history()[0].key().fodselsnummer ) } -} +} \ No newline at end of file diff --git a/apps/etterlatte-notifikasjoner/src/test/kotlin/SendNotifikasjonTest.kt b/apps/etterlatte-notifikasjoner/src/test/kotlin/SendNotifikasjonTest.kt index ca0354fb1..12fcf980b 100644 --- a/apps/etterlatte-notifikasjoner/src/test/kotlin/SendNotifikasjonTest.kt +++ b/apps/etterlatte-notifikasjoner/src/test/kotlin/SendNotifikasjonTest.kt @@ -12,11 +12,13 @@ import java.time.ZoneOffset internal class SendNotifikasjonTest { private val mockKafkaProducer = mockk>() - private val sendNotifikasjon = SendNotifikasjon( - mapOf( - "BRUKERNOTIFIKASJON_BESKJED_TOPIC" to "test_topic", - ), mockKafkaProducer - ) + private val sendNotifikasjon = + SendNotifikasjon( + mapOf( + "BRUKERNOTIFIKASJON_BESKJED_TOPIC" to "test_topic" + ), + mockKafkaProducer + ) @Test fun `skal opprette melding for gjenlevendepensjon`() { @@ -70,7 +72,9 @@ internal class SendNotifikasjonTest { } } -fun isWithin10Seconds(actual: LocalDateTime, expected: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC)): Boolean = - actual.isBefore(expected.plusSeconds(10)) && actual.isAfter(expected.minusSeconds(10)) +fun isWithin10Seconds( + actual: LocalDateTime, + expected: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC) +): Boolean = actual.isBefore(expected.plusSeconds(10)) && actual.isAfter(expected.minusSeconds(10)) -fun Long.toLocalDateTime(): LocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(this), ZoneOffset.UTC) +fun Long.toLocalDateTime(): LocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(this), ZoneOffset.UTC) \ No newline at end of file diff --git a/apps/etterlatte-proxy/src/main/kotlin/Application.kt b/apps/etterlatte-proxy/src/main/kotlin/Application.kt index 6cc243a1b..e2708b0dc 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/Application.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/Application.kt @@ -23,7 +23,9 @@ import no.nav.etterlatte.routes.tilbakekrevingRoute import org.slf4j.event.Level import java.util.* -fun main(args: Array): Unit = io.ktor.server.netty.EngineMain.main(args) +fun main(args: Array): Unit = + io.ktor.server.netty.EngineMain + .main(args) fun Application.module() { val config = runBlocking { environment.config.load() } @@ -59,5 +61,4 @@ fun Application.module() { * nøyaktig 11 tall på rad ([ikke tall før, 11 tall, ikke tall etter] er tolkningen til regex'en), og bytte de * ut med 11 *. Ser ikke på "gyldigheten" til det som er potensielle fnr, bare fjerner alle slike forekomster. */ -fun skjulAllePotensielleFnr(url: String): String = url.replace(Regex("(? Unit) { with(ClientCredentialAuthConfig().apply(block)) { providers.add(ClientCredentialAuthProvider(config)) @@ -28,22 +27,28 @@ class ClientCredentialAuthConfig { lateinit var config: Map } -class ClientCredentialAuthProvider(config: Map) : AuthProvider { +class ClientCredentialAuthProvider( + config: Map +) : AuthProvider { override val sendWithoutRequest: Boolean = true - private val clientPropertiesConfig = ClientProperties( - tokenEndpointUrl = null, // URI(conf["token_endpoint_url"]!!), - wellKnownUrl = config["AZURE_APP_WELL_KNOWN_URL"]?.let { URI(it) }, - grantType = GrantType.CLIENT_CREDENTIALS, - scope = config["AZURE_APP_OUTBOUND_SCOPE"]?.split(",") ?: emptyList(), - authentication = ClientAuthenticationProperties.builder( - clientId = config.getOrThrow("AZURE_APP_CLIENT_ID"), - clientAuthMethod = ClientAuthenticationMethod.PRIVATE_KEY_JWT, - ).clientJwk(config.getOrThrow("AZURE_APP_JWK")) - .build(), - resourceUrl = null, // conf["resource_url"]?.let { URI(it) }, - tokenExchange = null - ) + private val clientPropertiesConfig = + ClientProperties( + tokenEndpointUrl = null, // URI(conf["token_endpoint_url"]!!), + wellKnownUrl = config["AZURE_APP_WELL_KNOWN_URL"]?.let { URI(it) }, + grantType = GrantType.CLIENT_CREDENTIALS, + scope = config["AZURE_APP_OUTBOUND_SCOPE"]?.split(",") ?: emptyList(), + authentication = + ClientAuthenticationProperties + .builder( + clientId = config.getOrThrow("AZURE_APP_CLIENT_ID"), + clientAuthMethod = ClientAuthenticationMethod.PRIVATE_KEY_JWT + ).clientJwk(config.getOrThrow("AZURE_APP_JWK")) + .build(), + resourceUrl = null, // conf["resource_url"]?.let { URI(it) }, + tokenExchange = null + ) + private fun Map.getOrThrow(key: String) = this[key] ?: throw IllegalArgumentException("Missing configuration property '$key'") @@ -51,27 +56,27 @@ class ClientCredentialAuthProvider(config: Map) : AuthProvider { private val httpClient = DefaultOAuth2HttpClient() private val accessTokenService = setupOAuth2AccessTokenService(httpClient = httpClient) - override fun isApplicable(auth: HttpAuthHeader): Boolean { - return true - } + override fun isApplicable(auth: HttpAuthHeader): Boolean = true - override suspend fun addRequestHeaders(request: HttpRequestBuilder, authHeader: HttpAuthHeader?) { + override suspend fun addRequestHeaders( + request: HttpRequestBuilder, + authHeader: HttpAuthHeader? + ) { accessTokenService.getAccessToken(clientPropertiesConfig)?.accessToken.also { request.headers[HttpHeaders.Authorization] = "Bearer $it" } } } -internal fun setupOAuth2AccessTokenService(httpClient: DefaultOAuth2HttpClient): OAuth2AccessTokenService { - return OAuth2AccessTokenService( +internal fun setupOAuth2AccessTokenService(httpClient: DefaultOAuth2HttpClient): OAuth2AccessTokenService = + OAuth2AccessTokenService( tokenResolver = { throw IllegalArgumentException("Skal ikke kalle denne") }, onBehalfOfTokenClient = OnBehalfOfTokenClient(httpClient), clientCredentialsTokenClient = ClientCredentialsTokenClient(httpClient), clientCredentialsGrantCache = - OAuth2CacheFactory.accessTokenResponseCache( - maximumSize = 10, - skewInSeconds = Duration.ofMinutes(50L).toSeconds(), - ), - tokenExchangeClient = TokenExchangeClient(httpClient), - ) -} \ No newline at end of file + OAuth2CacheFactory.accessTokenResponseCache( + maximumSize = 10, + skewInSeconds = Duration.ofMinutes(50L).toSeconds() + ), + tokenExchangeClient = TokenExchangeClient(httpClient) + ) \ No newline at end of file diff --git a/apps/etterlatte-proxy/src/main/kotlin/auth/DefaultOauth2HttpClient.kt b/apps/etterlatte-proxy/src/main/kotlin/auth/DefaultOAuth2HttpClient.kt similarity index 55% rename from apps/etterlatte-proxy/src/main/kotlin/auth/DefaultOauth2HttpClient.kt rename to apps/etterlatte-proxy/src/main/kotlin/auth/DefaultOAuth2HttpClient.kt index d65b84984..70bdfe350 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/auth/DefaultOauth2HttpClient.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/auth/DefaultOAuth2HttpClient.kt @@ -15,28 +15,29 @@ import no.nav.security.token.support.client.core.http.OAuth2HttpRequest import no.nav.security.token.support.client.core.oauth2.OAuth2AccessTokenResponse class DefaultOAuth2HttpClient : OAuth2HttpClient { - - private val defaultHttpClient = HttpClient(OkHttp) { - install(ContentNegotiation) { - expectSuccess = true - jackson { - configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - setSerializationInclusion(JsonInclude.Include.NON_NULL) + private val defaultHttpClient = + HttpClient(OkHttp) { + install(ContentNegotiation) { + expectSuccess = true + jackson { + configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + setSerializationInclusion(JsonInclude.Include.NON_NULL) + } } } - } // Override default POST with other form parameters specified for Idp request - override fun post(request: OAuth2HttpRequest): OAuth2AccessTokenResponse { - return runBlocking { - defaultHttpClient.submitForm( - url = request.tokenEndpointUrl.toString(), - formParameters = Parameters.build { - request.formParameters.forEach { - append(it.key, it.value) - } - } - ).body() + override fun post(request: OAuth2HttpRequest): OAuth2AccessTokenResponse = + runBlocking { + defaultHttpClient + .submitForm( + url = request.tokenEndpointUrl.toString(), + formParameters = + Parameters.build { + request.formParameters.forEach { + append(it.key, it.value) + } + } + ).body() } - } } \ No newline at end of file diff --git a/apps/etterlatte-proxy/src/main/kotlin/auth/sts/StsSoapClient.kt b/apps/etterlatte-proxy/src/main/kotlin/auth/sts/StsSoapClient.kt index 0002aa47c..3e98c3f95 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/auth/sts/StsSoapClient.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/auth/sts/StsSoapClient.kt @@ -16,7 +16,10 @@ import org.apache.cxf.ws.security.SecurityConstants import org.apache.cxf.ws.security.trust.STSClient import org.apache.neethi.Policy -data class ServiceUserConfig(val username: String, val password: String) +data class ServiceUserConfig( + val username: String, + val password: String +) internal const val STS_CLIENT_AUTHENTICATION_POLICY = "classpath:untPolicy.xml" internal const val STS_SAML_POLICY = "classpath:requestSamlPolicy.xml" @@ -24,34 +27,36 @@ internal const val STS_SAML_POLICY = "classpath:requestSamlPolicy.xml" internal inline fun ClientProxyFactoryBean.wrapInStsClient( stsSoapUrl: String, serviceUser: ServiceUserConfig, - disableCNCheck: Boolean, -): T { - return this.create(T::class.java).apply { + disableCNCheck: Boolean +): T = + this.create(T::class.java).apply { val bus: Bus = ExtensionManagerBus() - val sts = STSClient(bus).apply { - isEnableAppliesTo = false - isAllowRenewing = false + val sts = + STSClient(bus).apply { + isEnableAppliesTo = false + isAllowRenewing = false - location = stsSoapUrl - properties = mapOf( - SecurityConstants.USERNAME to serviceUser.username, - SecurityConstants.PASSWORD to serviceUser.password, - ) - setPolicy(bus.resolvePolicy(STS_CLIENT_AUTHENTICATION_POLICY)) - } + location = stsSoapUrl + properties = + mapOf( + SecurityConstants.USERNAME to serviceUser.username, + SecurityConstants.PASSWORD to serviceUser.password + ) + setPolicy(bus.resolvePolicy(STS_CLIENT_AUTHENTICATION_POLICY)) + } ClientProxy.getClient(this).apply { requestContext[SecurityConstants.STS_CLIENT] = sts requestContext[SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT] = true setClientEndpointPolicy(bus.resolvePolicy(STS_SAML_POLICY)) if (disableCNCheck) { val conduit = conduit as HTTPConduit - conduit.tlsClientParameters = TLSClientParameters().apply { - isDisableCNCheck = true - } + conduit.tlsClientParameters = + TLSClientParameters().apply { + isDisableCNCheck = true + } } } } -} internal fun Bus.resolvePolicy(policyUri: String): Policy { val registry = getExtension(PolicyEngine::class.java).registry diff --git a/apps/etterlatte-proxy/src/main/kotlin/config/Config.kt b/apps/etterlatte-proxy/src/main/kotlin/config/Config.kt index c911c1008..3559fecc9 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/config/Config.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/config/Config.kt @@ -10,46 +10,47 @@ data class Config( val sts: Sts, val aad: AAD, val tilbakekrevingUrl: String, - val simuleringOppdragUrl: String, + val simuleringOppdragUrl: String ) { - data class Sts( val soapUrl: String, - val serviceuser: ServiceUser, + val serviceuser: ServiceUser ) { data class ServiceUser( val name: String, - val password: String, + val password: String ) { - override fun toString(): String { - return "name=$name, password=" - } + override fun toString(): String = "name=$name, password=" } } data class AAD( val metadata: Metadata, - val clientId: String, + val clientId: String ) { data class Metadata( @JsonProperty("issuer") val issuer: String, - @JsonProperty("jwks_uri") val jwksUri: String, + @JsonProperty("jwks_uri") val jwksUri: String ) } } -suspend fun ApplicationConfig.load() = Config( - tilbakekrevingUrl = property("tilbakekreving.url").getString(), - simuleringOppdragUrl = property("simuleringOppdrag.url").getString(), - sts = Config.Sts( - soapUrl = property("sts.soapUrl").getString(), - serviceuser = Config.Sts.ServiceUser( - name = property("serviceuser.name").getString(), - password = property("serviceuser.password").getString(), - ) - ), - aad = Config.AAD( - metadata = httpClientWithProxy().use { it.get(property("aad.wellKnownUrl").getString()).body() }, - clientId = property("aad.clientId").getString() - ) -) +suspend fun ApplicationConfig.load() = + Config( + tilbakekrevingUrl = property("tilbakekreving.url").getString(), + simuleringOppdragUrl = property("simuleringOppdrag.url").getString(), + sts = + Config.Sts( + soapUrl = property("sts.soapUrl").getString(), + serviceuser = + Config.Sts.ServiceUser( + name = property("serviceuser.name").getString(), + password = property("serviceuser.password").getString() + ) + ), + aad = + Config.AAD( + metadata = httpClientWithProxy().use { it.get(property("aad.wellKnownUrl").getString()).body() }, + clientId = property("aad.clientId").getString() + ) + ) \ No newline at end of file diff --git a/apps/etterlatte-proxy/src/main/kotlin/config/SimuleringOppdragConfig.kt b/apps/etterlatte-proxy/src/main/kotlin/config/SimuleringOppdragConfig.kt index e100ce9f8..c49e7f864 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/config/SimuleringOppdragConfig.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/config/SimuleringOppdragConfig.kt @@ -10,8 +10,10 @@ import org.apache.cxf.ws.addressing.WSAddressingFeature import org.slf4j.LoggerFactory import javax.xml.namespace.QName -class SimuleringOppdragConfig(config: Config, private val enableLogging: Boolean = false) { - +class SimuleringOppdragConfig( + config: Config, + private val enableLogging: Boolean = false +) { private val simuleringOppdragUrl = config.simuleringOppdragUrl private val sts = config.sts private val logger = LoggerFactory.getLogger(javaClass) @@ -19,33 +21,41 @@ class SimuleringOppdragConfig(config: Config, private val enableLogging: Boolean fun createSimuleringOppdragService(): SimulerFpService { logger.info("Bruker simuleringOppdrag url $simuleringOppdragUrl") - val enabledFeatures = mutableListOf().apply { - add(WSAddressingFeature()) - if (enableLogging) add(LoggingFeature().apply { - setSensitiveDataHelper(SoapSecurityMaskSensitiveHelper()) - setVerbose(true) - setPrettyLogging(true) - setSensitiveElementNames(setOf( - /* request */ - "oppdragGjelderId", - "utbetalesTilId", - /* response */ - "gjelderId", - "gjelderNavn", - "utbetalesTilId", - "utbetalesTilNavn", - )) - }) - } + val enabledFeatures = + mutableListOf().apply { + add(WSAddressingFeature()) + if (enableLogging) { + add( + LoggingFeature().apply { + setSensitiveDataHelper(SoapSecurityMaskSensitiveHelper()) + setVerbose(true) + setPrettyLogging(true) + setSensitiveElementNames( + setOf( + // request + "oppdragGjelderId", + "utbetalesTilId", + // response + "gjelderId", + "gjelderNavn", + "utbetalesTilId", + "utbetalesTilNavn" + ) + ) + } + ) + } + } - return JaxWsProxyFactoryBean().apply { - address = simuleringOppdragUrl - wsdlURL = WSDL - serviceName = SERVICE - endpointName = PORT - serviceClass = SimulerFpService::class.java - features = enabledFeatures - }.wrapInStsClient(sts.soapUrl, ServiceUserConfig(sts.serviceuser.name, sts.serviceuser.password), true) + return JaxWsProxyFactoryBean() + .apply { + address = simuleringOppdragUrl + wsdlURL = WSDL + serviceName = SERVICE + endpointName = PORT + serviceClass = SimulerFpService::class.java + features = enabledFeatures + }.wrapInStsClient(sts.soapUrl, ServiceUserConfig(sts.serviceuser.name, sts.serviceuser.password), true) } private companion object { @@ -54,4 +64,4 @@ class SimuleringOppdragConfig(config: Config, private val enableLogging: Boolean private val SERVICE = QName(NAMESPACE, "simulerFpService") private val PORT = QName(NAMESPACE, "simulerFpServicePort") } -} +} \ No newline at end of file diff --git a/apps/etterlatte-proxy/src/main/kotlin/config/SoapSecurityMaskSensitiveHelper.kt b/apps/etterlatte-proxy/src/main/kotlin/config/SoapSecurityMaskSensitiveHelper.kt index 8b74f5b6c..9b04bc766 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/config/SoapSecurityMaskSensitiveHelper.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/config/SoapSecurityMaskSensitiveHelper.kt @@ -10,7 +10,10 @@ import java.util.regex.Pattern internal class SoapSecurityMaskSensitiveHelper : MaskSensitiveHelper() { private val matchPatternXML = Pattern.compile("()([\\s\\S.]*?)()") - override fun maskSensitiveElements(message: Message, originalLogString: String): String { + override fun maskSensitiveElements( + message: Message, + originalLogString: String + ): String { val resultString = matchPatternXML.matcher(originalLogString).replaceAll("$1***REDACTED***$3") return super.maskSensitiveElements(message, resultString) diff --git a/apps/etterlatte-proxy/src/main/kotlin/config/TilbakekrevingConfig.kt b/apps/etterlatte-proxy/src/main/kotlin/config/TilbakekrevingConfig.kt index c209be02d..3ebfc19e0 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/config/TilbakekrevingConfig.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/config/TilbakekrevingConfig.kt @@ -10,8 +10,10 @@ import org.apache.cxf.ws.addressing.WSAddressingFeature import org.slf4j.LoggerFactory import javax.xml.namespace.QName -class TilbakekrevingConfig(config: Config, private val enableLogging: Boolean = false) { - +class TilbakekrevingConfig( + config: Config, + private val enableLogging: Boolean = false +) { private val tilbakekrevingUrl = config.tilbakekrevingUrl private val sts = config.sts private val logger = LoggerFactory.getLogger(javaClass) @@ -19,23 +21,29 @@ class TilbakekrevingConfig(config: Config, private val enableLogging: Boolean = fun createTilbakekrevingService(): TilbakekrevingPortType { logger.info("Bruker tilbakekrevingService url $tilbakekrevingUrl") - val enabledFeatures = mutableListOf().apply { - add(WSAddressingFeature()) - if (enableLogging) add(LoggingFeature().apply { - setSensitiveDataHelper(SoapSecurityMaskSensitiveHelper()) - setVerbose(true) - setPrettyLogging(true) - }) - } + val enabledFeatures = + mutableListOf().apply { + add(WSAddressingFeature()) + if (enableLogging) { + add( + LoggingFeature().apply { + setSensitiveDataHelper(SoapSecurityMaskSensitiveHelper()) + setVerbose(true) + setPrettyLogging(true) + } + ) + } + } - return JaxWsProxyFactoryBean().apply { - address = tilbakekrevingUrl - wsdlURL = WSDL - serviceName = SERVICE - endpointName = PORT - serviceClass = TilbakekrevingPortType::class.java - features = enabledFeatures - }.wrapInStsClient(sts.soapUrl, ServiceUserConfig(sts.serviceuser.name, sts.serviceuser.password), true) + return JaxWsProxyFactoryBean() + .apply { + address = tilbakekrevingUrl + wsdlURL = WSDL + serviceName = SERVICE + endpointName = PORT + serviceClass = TilbakekrevingPortType::class.java + features = enabledFeatures + }.wrapInStsClient(sts.soapUrl, ServiceUserConfig(sts.serviceuser.name, sts.serviceuser.password), true) } private companion object { @@ -44,4 +52,4 @@ class TilbakekrevingConfig(config: Config, private val enableLogging: Boolean = private val SERVICE = QName(NAMESPACE, "TilbakekrevingService") private val PORT = QName(NAMESPACE, "TilbakekrevingServicePort") } -} +} \ No newline at end of file diff --git a/apps/etterlatte-proxy/src/main/kotlin/routes/Http.kt b/apps/etterlatte-proxy/src/main/kotlin/routes/Http.kt index 7430e78d9..ed3be3a5f 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/routes/Http.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/routes/Http.kt @@ -27,71 +27,106 @@ import io.ktor.utils.io.copyAndClose import org.apache.http.impl.conn.SystemDefaultRoutePlanner import java.net.ProxySelector +fun httpClient() = + HttpClient(Apache) { + install(Logging) { + level = LogLevel.INFO + } + }.also { Runtime.getRuntime().addShutdownHook(Thread { it.close() }) } -fun httpClient() = HttpClient(Apache){ - install(Logging) { - level = LogLevel.INFO - } -}.also { Runtime.getRuntime().addShutdownHook(Thread{it.close()}) } - -fun httpClientWithProxy() = HttpClient(Apache) { - install(ContentNegotiation) { - jackson { configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) } - } - engine { - customizeClient { - setRoutePlanner(SystemDefaultRoutePlanner(ProxySelector.getDefault())) +fun httpClientWithProxy() = + HttpClient(Apache) { + install(ContentNegotiation) { + jackson { configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) } + } + engine { + customizeClient { + setRoutePlanner(SystemDefaultRoutePlanner(ProxySelector.getDefault())) + } } } -} -val proxiedContenHeaders = listOf( - HttpHeaders.ContentType, - HttpHeaders.ContentLength, - HttpHeaders.TransferEncoding, -) -fun filterContenHeaders(requestHeaders: Headers): Headers{ - return Headers.build { appendAll(requestHeaders.filter { key, _ -> proxiedContenHeaders.any{it.equals(key, true)} }) } -} +val proxiedContenHeaders = + listOf( + HttpHeaders.ContentType, + HttpHeaders.ContentLength, + HttpHeaders.TransferEncoding + ) -class ProxiedContent(private val proxiedHeaders: Headers, private val content: ByteReadChannel, override val status: HttpStatusCode? = null): OutgoingContent.WriteChannelContent(){ - companion object{ - private val ignoredHeaders = listOf(HttpHeaders.ContentType, HttpHeaders.ContentLength, HttpHeaders.TransferEncoding, HttpHeaders.Authorization) +fun filterContenHeaders(requestHeaders: Headers): Headers = + Headers.build { + appendAll(requestHeaders.filter { key, _ -> proxiedContenHeaders.any { it.equals(key, true) } }) } + +class ProxiedContent( + private val proxiedHeaders: Headers, + private val content: ByteReadChannel, + override val status: HttpStatusCode? = null +) : OutgoingContent.WriteChannelContent() { + companion object { + private val ignoredHeaders = + listOf( + HttpHeaders.ContentType, + HttpHeaders.ContentLength, + HttpHeaders.TransferEncoding, + HttpHeaders.Authorization + ) + } + override val contentLength: Long? = proxiedHeaders[HttpHeaders.ContentLength]?.toLong() override val contentType: ContentType? = proxiedHeaders[HttpHeaders.ContentType]?.let { ContentType.parse(it) } - override val headers: Headers = Headers.build { - appendAll(proxiedHeaders.filter { key, _ -> - ignoredHeaders.none { it.equals(key, ignoreCase = true) } - }) - } + override val headers: Headers = + Headers.build { + appendAll( + proxiedHeaders.filter { key, _ -> + ignoredHeaders.none { it.equals(key, ignoreCase = true) } + } + ) + } + override suspend fun writeTo(channel: ByteWriteChannel) { content.copyAndClose(channel) } } -suspend fun HttpRequestBuilder.pipeRequest(call: ApplicationCall, customHeaders: List = emptyList()){ - val requestHeadersToProxy = listOf( - HttpHeaders.Accept, - HttpHeaders.AcceptCharset, - HttpHeaders.AcceptEncoding, - ) + customHeaders - headers.appendAll(call.request.headers.filter { key, _ -> - requestHeadersToProxy.any{it.equals(key, true)} - }) +suspend fun HttpRequestBuilder.pipeRequest( + call: ApplicationCall, + customHeaders: List = emptyList() +) { + val requestHeadersToProxy = + listOf( + HttpHeaders.Accept, + HttpHeaders.AcceptCharset, + HttpHeaders.AcceptEncoding + ) + customHeaders + headers.appendAll( + call.request.headers.filter { key, _ -> + requestHeadersToProxy.any { it.equals(key, true) } + } + ) setBody(ProxiedContent(filterContenHeaders(call.request.headers), call.receiveChannel())) } @OptIn(InternalAPI::class) suspend fun ApplicationCall.pipeResponse(response: HttpResponse) { - respond(ProxiedContent(response.headers, if(response.content.isClosedForRead) { response.body() } else { response.content }, response.status)) + respond( + ProxiedContent( + response.headers, + if (response.content.isClosedForRead) { + response.body() + } else { + response.content + }, + response.status + ) + ) } val HttpHeaders.NavCallId: String get() = "Nav-Call-Id" val HttpHeaders.NavConsumerId: String get() = "Nav-Consumer-Id" -val HttpHeaders.NavPersonident : String +val HttpHeaders.NavPersonident: String get() = "Nav-Personident" -val HttpHeaders.NavConsumerToken : String +val HttpHeaders.NavConsumerToken: String get() = "Nav-Consumer-Token" \ No newline at end of file diff --git a/apps/etterlatte-proxy/src/main/kotlin/routes/InternalRoute.kt b/apps/etterlatte-proxy/src/main/kotlin/routes/InternalRoute.kt index 5a3168652..1c68a99ab 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/routes/InternalRoute.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/routes/InternalRoute.kt @@ -19,10 +19,13 @@ fun Route.internalRoute() { call.respondText { "Ready" } } get("/metrics") { - val names = call.request.queryParameters.getAll("name[]")?.toSet() ?: emptySet() + val names = + call.request.queryParameters + .getAll("name[]") + ?.toSet() ?: emptySet() call.respondTextWriter(ContentType.parse(TextFormat.CONTENT_TYPE_004)) { TextFormat.write004(this, CollectorRegistry.defaultRegistry.filteredMetricFamilySamples(names)) } } } -} +} \ No newline at end of file diff --git a/apps/etterlatte-proxy/src/main/kotlin/routes/SimuleringOppdragRoute.kt b/apps/etterlatte-proxy/src/main/kotlin/routes/SimuleringOppdragRoute.kt index faf51cd28..eda6798cb 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/routes/SimuleringOppdragRoute.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/routes/SimuleringOppdragRoute.kt @@ -21,7 +21,9 @@ fun Route.simuleringOppdragRoute(simulerFpService: SimulerFpService) { post("/simuleringoppdrag/simulerberegning") { val request = call.receive() - logger.info("Videresender simuleringsberegning for fagsystemId=${request.request.oppdrag.fagsystemId} fra proxy") + logger.info( + "Videresender simuleringsberegning for fagsystemId=${request.request.oppdrag.fagsystemId} fra proxy" + ) try { val response = simulerFpService.simulerBeregning(request) call.respond(response) diff --git a/apps/etterlatte-proxy/src/main/kotlin/routes/TilbakekrevingRoute.kt b/apps/etterlatte-proxy/src/main/kotlin/routes/TilbakekrevingRoute.kt index 07a40e166..d081362a9 100644 --- a/apps/etterlatte-proxy/src/main/kotlin/routes/TilbakekrevingRoute.kt +++ b/apps/etterlatte-proxy/src/main/kotlin/routes/TilbakekrevingRoute.kt @@ -19,7 +19,9 @@ fun Route.tilbakekrevingRoute(tilbakekrevingService: TilbakekrevingPortType) { post("/tilbakekreving/tilbakekrevingsvedtak") { val request = call.receive() - logger.info("Videresender tilbakekrevingsvedtak med vedtakId=${request.tilbakekrevingsvedtak.vedtakId} fra proxy") + logger.info( + "Videresender tilbakekrevingsvedtak med vedtakId=${request.tilbakekrevingsvedtak.vedtakId} fra proxy" + ) val response = tilbakekrevingService.tilbakekrevingsvedtak(request) call.respond(response) } diff --git a/apps/etterlatte-proxy/src/test/kotlin/ApplicationTest.kt b/apps/etterlatte-proxy/src/test/kotlin/ApplicationTest.kt index 6e57cd209..37cd8ae79 100644 --- a/apps/etterlatte-proxy/src/test/kotlin/ApplicationTest.kt +++ b/apps/etterlatte-proxy/src/test/kotlin/ApplicationTest.kt @@ -17,20 +17,25 @@ import org.junit.jupiter.api.TestInstance @TestInstance(TestInstance.Lifecycle.PER_CLASS) internal class ApplicationTest { - private val mockOAuth2 = MockOAuth2Server() private lateinit var hoconApplicationConfig: HoconApplicationConfig @BeforeAll fun beforeAll() { mockOAuth2.start() - hoconApplicationConfig = HoconApplicationConfig(ConfigFactory.load() - .withValue("aad.wellKnownUrl", ConfigValueFactory.fromAnyRef(mockOAuth2.wellKnownUrl("aad").toString())) - ) - + hoconApplicationConfig = + HoconApplicationConfig( + ConfigFactory + .load() + .withValue( + "aad.wellKnownUrl", + ConfigValueFactory.fromAnyRef(mockOAuth2.wellKnownUrl("aad").toString()) + ) + ) } + @AfterAll - fun tearDown(){ + fun tearDown() { mockOAuth2.shutdown() } @@ -60,4 +65,4 @@ internal class ApplicationTest { } } } -} +} \ No newline at end of file