diff --git a/pom.xml b/pom.xml index 3c0eefc97..5052bc294 100644 --- a/pom.xml +++ b/pom.xml @@ -239,14 +239,19 @@ no.nav.security - token-validation-core + token-client-spring ${token-validation-spring.version} no.nav.familie.felles - http-client + log ${felles.version} + + no.nav.security + token-validation-core + ${token-validation-spring.version} + ch.qos.logback logback-classic diff --git a/src/main/kotlin/no/nav/familie/tilbake/config/ApplicationConfig.kt b/src/main/kotlin/no/nav/familie/tilbake/config/ApplicationConfig.kt index 2c129488d..fe237b433 100644 --- a/src/main/kotlin/no/nav/familie/tilbake/config/ApplicationConfig.kt +++ b/src/main/kotlin/no/nav/familie/tilbake/config/ApplicationConfig.kt @@ -2,12 +2,6 @@ package no.nav.familie.tilbake.config import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.KotlinModule -import no.nav.familie.http.client.RetryOAuth2HttpClient -import no.nav.familie.http.config.RestTemplateAzure -import no.nav.familie.log.filter.LogFilter -import no.nav.familie.prosessering.config.ProsesseringInfoProvider -import no.nav.security.token.support.client.core.http.OAuth2HttpClient -import no.nav.security.token.support.client.core.oauth2.OAuth2AccessTokenResponse import no.nav.security.token.support.client.spring.oauth2.EnableOAuth2Client import no.nav.security.token.support.spring.SpringTokenValidationContextHolder import no.nav.security.token.support.spring.api.EnableJwtTokenValidation @@ -21,19 +15,18 @@ import org.springframework.boot.web.servlet.server.ServletWebServerFactory import org.springframework.cache.annotation.EnableCaching import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Import import org.springframework.context.annotation.Primary import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter import org.springframework.scheduling.annotation.EnableScheduling -import org.springframework.web.client.RestClient import org.springframework.web.client.RestTemplate import java.time.Duration import java.time.temporal.ChronoUnit +import no.nav.familie.log.filter.LogFilter +import no.nav.familie.prosessering.config.ProsesseringInfoProvider @SpringBootConfiguration -@ComponentScan(ApplicationConfig.PAKKE_NAVN, "no.nav.familie.sikkerhet", "no.nav.familie.prosessering", "no.nav.familie.unleash") +@ComponentScan(ApplicationConfig.PAKKE_NAVN, "no.nav.familie.prosessering", "no.nav.familie.unleash") @EnableJwtTokenValidation(ignore = ["org.springframework", "org.springdoc"]) -@Import(RestTemplateAzure::class) @EnableOAuth2Client(cacheEnabled = true) @EnableScheduling @EnableCaching @@ -65,28 +58,11 @@ class ApplicationConfig { fun restTemplateBuilder(objectMapper: ObjectMapper): RestTemplateBuilder { val jackson2HttpMessageConverter = MappingJackson2HttpMessageConverter(objectMapper) return RestTemplateBuilder() - .setConnectTimeout(Duration.of(2, ChronoUnit.SECONDS)) - .setReadTimeout(Duration.of(30, ChronoUnit.SECONDS)) + .connectTimeout(Duration.of(2, ChronoUnit.SECONDS)) + .readTimeout(Duration.of(30, ChronoUnit.SECONDS)) .additionalMessageConverters(listOf(jackson2HttpMessageConverter) + RestTemplate().messageConverters) } - /** - * Overskriver OAuth2HttpClient som settes opp i token-support som ikke kan få med objectMapper fra felles - * pga. .setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE) - * og [OAuth2AccessTokenResponse] som burde settes med setters, då feltnavn heter noe annet enn feltet i json - */ - @Bean - @Primary - fun oAuth2HttpClient(): OAuth2HttpClient = - RetryOAuth2HttpClient( - RestClient.create( - RestTemplateBuilder() - .setConnectTimeout(Duration.of(2, ChronoUnit.SECONDS)) - .setReadTimeout(Duration.of(4, ChronoUnit.SECONDS)) - .build(), - ), - ) - @Bean fun prosesseringInfoProvider( @Value("\${rolle.prosessering}") prosesseringRolle: String, diff --git a/src/main/kotlin/no/nav/familie/tilbake/config/HttpClientConfig.kt b/src/main/kotlin/no/nav/familie/tilbake/config/HttpClientConfig.kt new file mode 100644 index 000000000..71428d304 --- /dev/null +++ b/src/main/kotlin/no/nav/familie/tilbake/config/HttpClientConfig.kt @@ -0,0 +1,36 @@ +package no.nav.familie.tilbake.config + +import no.nav.familie.tilbake.http.BearerTokenClientInterceptor +import no.nav.familie.tilbake.http.ConsumerIdClientInterceptor +import no.nav.familie.tilbake.http.MdcValuesPropagatingClientInterceptor +import org.springframework.boot.web.client.RestTemplateBuilder +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.client.RestOperations + +@Configuration +class HttpClientConfig { + private val restTemplateBuilder = RestTemplateBuilder() + + @Bean("azure") + fun restTemplateEntraIDBearer( + consumerIdClientInterceptor: ConsumerIdClientInterceptor, + bearerTokenClientInterceptor: BearerTokenClientInterceptor, + ): RestOperations = restTemplateBuilder + .additionalInterceptors( + consumerIdClientInterceptor, + bearerTokenClientInterceptor, + MdcValuesPropagatingClientInterceptor(), + ).build() + + @Bean("azureClientCredential") + fun restTemplateClientCredentialEntraIdBearer( + consumerIdClientInterceptor: ConsumerIdClientInterceptor, + bearerTokenClientInterceptor: BearerTokenClientInterceptor, + ): RestOperations = restTemplateBuilder + .additionalInterceptors( + consumerIdClientInterceptor, + bearerTokenClientInterceptor, + MdcValuesPropagatingClientInterceptor() + ).build() +} diff --git "a/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/pdf/Journalf\303\270ringService.kt" "b/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/pdf/Journalf\303\270ringService.kt" index f9673706e..30bee6094 100644 --- "a/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/pdf/Journalf\303\270ringService.kt" +++ "b/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/pdf/Journalf\303\270ringService.kt" @@ -44,6 +44,7 @@ class JournalføringService( fun hentJournalposter(behandlingId: UUID): List { val behandling = behandlingRepository.findById(behandlingId).orElseThrow() val fagsak = behandling.let { fagsakRepository.findById(it.fagsakId).orElseThrow() } + val logContext = SecureLog.Context.medBehandling(fagsak.eksternFagsakId, behandling.id.toString()) val journalposter = fagsak.let { integrasjonerClient.hentJournalposterForBruker( @@ -56,6 +57,7 @@ class JournalføringService( ), tema = listOf(hentTema(fagsystem = fagsak.fagsystem)), ), + logContext, ) } return journalposter.filter { it.sak?.fagsakId == fagsak.eksternFagsakId } diff --git a/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/pdf/PdfBrevService.kt b/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/pdf/PdfBrevService.kt index 102b72fb2..3285b11db 100644 --- a/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/pdf/PdfBrevService.kt +++ b/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/pdf/PdfBrevService.kt @@ -1,6 +1,5 @@ package no.nav.familie.tilbake.dokumentbestilling.felles.pdf -import no.nav.familie.http.client.RessursException import no.nav.familie.kontrakter.felles.dokdist.Distribusjonstidspunkt import no.nav.familie.kontrakter.felles.dokdist.Distribusjonstype import no.nav.familie.kontrakter.felles.objectMapper @@ -26,6 +25,7 @@ import org.springframework.http.HttpStatus import org.springframework.stereotype.Service import java.util.Base64 import java.util.Properties +import no.nav.familie.tilbake.http.RessursException @Service class PdfBrevService( diff --git "a/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/task/DistribuerDokumentVedD\303\270dsfallTask.kt" "b/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/task/DistribuerDokumentVedD\303\270dsfallTask.kt" index 1b23efd45..d54b5acbf 100644 --- "a/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/task/DistribuerDokumentVedD\303\270dsfallTask.kt" +++ "b/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/task/DistribuerDokumentVedD\303\270dsfallTask.kt" @@ -1,6 +1,5 @@ package no.nav.familie.tilbake.dokumentbestilling.felles.task -import no.nav.familie.http.client.RessursException import no.nav.familie.kontrakter.felles.Fagsystem import no.nav.familie.kontrakter.felles.dokdist.Distribusjonstidspunkt import no.nav.familie.kontrakter.felles.dokdist.Distribusjonstype @@ -19,6 +18,7 @@ import org.springframework.http.HttpStatus import org.springframework.stereotype.Service import java.time.LocalDateTime import java.util.UUID +import no.nav.familie.tilbake.http.RessursException const val ANTALL_SEKUNDER_I_EN_UKE = 604800L diff --git a/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/task/PubliserJournalpostTask.kt b/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/task/PubliserJournalpostTask.kt index fb1fe3a1a..3b9b611aa 100644 --- a/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/task/PubliserJournalpostTask.kt +++ b/src/main/kotlin/no/nav/familie/tilbake/dokumentbestilling/felles/task/PubliserJournalpostTask.kt @@ -1,6 +1,5 @@ package no.nav.familie.tilbake.dokumentbestilling.felles.task -import no.nav.familie.http.client.RessursException import no.nav.familie.kontrakter.felles.Fagsystem import no.nav.familie.kontrakter.felles.dokdist.Distribusjonstidspunkt import no.nav.familie.kontrakter.felles.dokdist.Distribusjonstype @@ -17,6 +16,7 @@ import no.nav.familie.tilbake.log.TracedLogger import org.springframework.http.HttpStatus import org.springframework.stereotype.Service import java.util.UUID +import no.nav.familie.tilbake.http.RessursException @Service @TaskStepBeskrivelse( diff --git a/src/main/kotlin/no/nav/familie/tilbake/http/AbstractBearerTokenInterceptor.kt b/src/main/kotlin/no/nav/familie/tilbake/http/AbstractBearerTokenInterceptor.kt new file mode 100644 index 000000000..a6736d489 --- /dev/null +++ b/src/main/kotlin/no/nav/familie/tilbake/http/AbstractBearerTokenInterceptor.kt @@ -0,0 +1,32 @@ +package no.nav.familie.tilbake.http + +import com.nimbusds.oauth2.sdk.GrantType +import java.net.URI +import no.nav.security.token.support.client.core.ClientProperties +import no.nav.security.token.support.client.core.oauth2.OAuth2AccessTokenService +import no.nav.security.token.support.client.spring.ClientConfigurationProperties +import no.nav.security.token.support.core.exceptions.JwtTokenValidatorException +import org.springframework.http.client.ClientHttpRequestInterceptor + +abstract class AbstractBearerTokenInterceptor( + protected val oAuth2AccessTokenService: OAuth2AccessTokenService, + protected val clientConfigurationProperties: ClientConfigurationProperties, +) : ClientHttpRequestInterceptor { + protected fun genererAccessToken(clientProperties: ClientProperties): String { + return oAuth2AccessTokenService + .getAccessToken(clientProperties).access_token ?: throw JwtTokenValidatorException("Kunne ikke hente accesstoken") + } + + + protected fun ClientConfigurationProperties.findByURI(uri: URI) = registration + .values + .filter { uri.toString().startsWith(it.resourceUrl.toString()) } + + protected fun clientPropertiesForGrantType( + values: List, + grantType: GrantType, + uri: URI, + ): ClientProperties = + values.firstOrNull { grantType == it.grantType } + ?: error("could not find oauth2 client config for uri=$uri and grant type=$grantType") +} diff --git a/src/main/kotlin/no/nav/familie/tilbake/http/AbstractPingableRestClient.kt b/src/main/kotlin/no/nav/familie/tilbake/http/AbstractPingableRestClient.kt new file mode 100644 index 000000000..fc85b00fd --- /dev/null +++ b/src/main/kotlin/no/nav/familie/tilbake/http/AbstractPingableRestClient.kt @@ -0,0 +1,115 @@ +import com.fasterxml.jackson.module.kotlin.readValue +import io.micrometer.core.instrument.Counter +import io.micrometer.core.instrument.Metrics +import io.micrometer.core.instrument.Timer +import java.net.URI +import java.util.concurrent.TimeUnit +import no.nav.familie.kontrakter.felles.Ressurs +import no.nav.familie.kontrakter.felles.objectMapper +import no.nav.familie.tilbake.http.RessursException +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.http.HttpEntity +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod +import org.springframework.http.ResponseEntity +import org.springframework.web.client.HttpClientErrorException +import org.springframework.web.client.HttpServerErrorException +import org.springframework.web.client.ResourceAccessException +import org.springframework.web.client.RestClientResponseException +import org.springframework.web.client.RestOperations +import org.springframework.web.client.exchange + +abstract class AbstractPingableRestClient( + val operations: RestOperations, + metricsPrefix: String, +) { + private val secureLogger = LoggerFactory.getLogger("secureLogger") + protected val log: Logger = LoggerFactory.getLogger(this::class.java) + private val responstid: Timer = Metrics.timer("$metricsPrefix.tid") + private val responsSuccess: Counter = Metrics.counter("$metricsPrefix.response", "status", "success") + private val responsFailure: Counter = Metrics.counter("$metricsPrefix.response", "status", "failure") + + inline fun getForEntity( + uri: URI, + httpHeaders: HttpHeaders? = null, + ): T = executeMedMetrics(uri) { operations.exchange(uri, HttpMethod.GET, HttpEntity(null, httpHeaders)) } + + inline fun postForEntity( + uri: URI, + payload: Any, + httpHeaders: HttpHeaders? = null, + ): T = executeMedMetrics(uri) { operations.exchange(uri, HttpMethod.POST, HttpEntity(payload, httpHeaders)) } + + inline fun putForEntity( + uri: URI, + payload: Any, + httpHeaders: HttpHeaders? = null, + ): T = executeMedMetrics(uri) { operations.exchange(uri, HttpMethod.PUT, HttpEntity(payload, httpHeaders)) } + + inline fun patchForEntity( + uri: URI, + payload: Any, + httpHeaders: HttpHeaders? = null, + ): T = executeMedMetrics(uri) { operations.exchange(uri, HttpMethod.PATCH, HttpEntity(payload, httpHeaders)) } + + inline fun deleteForEntity( + uri: URI, + payload: Any? = null, + httpHeaders: HttpHeaders? = null, + ): T = executeMedMetrics(uri) { operations.exchange(uri, HttpMethod.DELETE, HttpEntity(payload, httpHeaders)) } + + private fun validerOgPakkUt( + respons: ResponseEntity, + uri: URI, + ): T { + if (!respons.statusCode.is2xxSuccessful) { + secureLogger.info("Kall mot $uri feilet: ${respons.body}") + log.info("Kall mot $uri feilet: ${respons.statusCode}") + throw HttpServerErrorException(respons.statusCode, "", respons.body?.toString()?.toByteArray(), Charsets.UTF_8) + } + return respons.body as T + } + + fun executeMedMetrics( + uri: URI, + function: () -> ResponseEntity, + ): T { + try { + val startTime = System.nanoTime() + val responseEntity = function.invoke() + responstid.record(System.nanoTime() - startTime, TimeUnit.NANOSECONDS) + responsSuccess.increment() + return validerOgPakkUt(responseEntity, uri) + } catch (e: RestClientResponseException) { + responsFailure.increment() + secureLogger.warn("RestClientResponseException ved kall mot uri=$uri", e) + lesRessurs(e)?.let { throw RessursException(it, e) } ?: throw e + } catch (e: HttpClientErrorException) { + responsFailure.increment() + secureLogger.warn("HttpClientErrorException ved kall mot uri=$uri", e) + lesRessurs(e)?.let { throw RessursException(it, e) } ?: throw e + } catch (e: ResourceAccessException) { + responsFailure.increment() + secureLogger.warn("ResourceAccessException ved kall mot uri=$uri", e) + throw e + } catch (e: Exception) { + responsFailure.increment() + secureLogger.warn("Feil ved kall mot uri=$uri", e) + throw RuntimeException("Feil ved kall mot uri=$uri", e) + } + } + + private fun lesRessurs(e: RestClientResponseException): Ressurs? = + try { + if (e.responseBodyAsString.contains("status")) { + objectMapper.readValue>(e.responseBodyAsString) + } else { + null + } + } catch (ex: Exception) { + null + } + + override fun toString(): String = this::class.simpleName + " [operations=" + operations + "]" +} diff --git a/src/main/kotlin/no/nav/familie/tilbake/http/BearerTokenClientCredentialClientInterceptor.kt b/src/main/kotlin/no/nav/familie/tilbake/http/BearerTokenClientCredentialClientInterceptor.kt new file mode 100644 index 000000000..a9714763c --- /dev/null +++ b/src/main/kotlin/no/nav/familie/tilbake/http/BearerTokenClientCredentialClientInterceptor.kt @@ -0,0 +1,27 @@ +package no.nav.familie.tilbake.http + +import com.nimbusds.oauth2.sdk.GrantType +import no.nav.security.token.support.client.core.oauth2.OAuth2AccessTokenService +import no.nav.security.token.support.client.spring.ClientConfigurationProperties +import org.springframework.http.HttpRequest +import org.springframework.http.client.ClientHttpRequestExecution +import org.springframework.http.client.ClientHttpResponse +import org.springframework.stereotype.Component + +@Component +class BearerTokenClientCredentialsClientInterceptor( + oAuth2AccessTokenService: OAuth2AccessTokenService, + clientConfigurationProperties: ClientConfigurationProperties, +) : AbstractBearerTokenInterceptor(oAuth2AccessTokenService, clientConfigurationProperties) { + override fun intercept( + request: HttpRequest, + body: ByteArray, + execution: ClientHttpRequestExecution, + ): ClientHttpResponse { + val clientProperties = clientPropertiesForGrantType(clientConfigurationProperties.findByURI(request.uri), GrantType.CLIENT_CREDENTIALS, request.uri) + request.headers.setBearerAuth( + genererAccessToken(clientProperties) + ) + return execution.execute(request, body) + } +} diff --git a/src/main/kotlin/no/nav/familie/tilbake/http/BearerTokenClientInterceptor.kt b/src/main/kotlin/no/nav/familie/tilbake/http/BearerTokenClientInterceptor.kt new file mode 100644 index 000000000..4688626fc --- /dev/null +++ b/src/main/kotlin/no/nav/familie/tilbake/http/BearerTokenClientInterceptor.kt @@ -0,0 +1,50 @@ +package no.nav.familie.tilbake.http + +import com.nimbusds.oauth2.sdk.GrantType +import java.net.URI +import no.nav.security.token.support.client.core.ClientProperties +import no.nav.security.token.support.client.core.oauth2.OAuth2AccessTokenService +import no.nav.security.token.support.client.spring.ClientConfigurationProperties +import no.nav.security.token.support.core.exceptions.JwtTokenValidatorException +import no.nav.security.token.support.spring.SpringTokenValidationContextHolder +import org.springframework.http.HttpRequest +import org.springframework.http.client.ClientHttpRequestExecution +import org.springframework.http.client.ClientHttpResponse +import org.springframework.stereotype.Component + +@Component("entraTokenInterceptor") +class BearerTokenClientInterceptor( + oAuth2AccessTokenService: OAuth2AccessTokenService, + clientConfigurationProperties: ClientConfigurationProperties, +) : AbstractBearerTokenInterceptor(oAuth2AccessTokenService, clientConfigurationProperties) { + override fun intercept( + request: HttpRequest, + body: ByteArray, + execution: ClientHttpRequestExecution, + ): ClientHttpResponse { + request.headers.setBearerAuth(genererAccessToken(clientPropertiesFor(request.uri))) + return execution.execute(request, body) + } + + private fun clientPropertiesFor(uri: URI): ClientProperties { + val clientProperties = clientConfigurationProperties.findByURI(uri) + return if (clientProperties.size == 1) { + clientProperties.first() + } else { + clientPropertiesForGrantType(clientProperties, clientCredentialOrJwtBearer(), uri) + } + } + + private fun clientCredentialOrJwtBearer() = if (erSystembruker()) GrantType.CLIENT_CREDENTIALS else GrantType.JWT_BEARER + + private fun erSystembruker(): Boolean { + return try { + val preferredUsername = + SpringTokenValidationContextHolder().getTokenValidationContext().getClaims("azuread").get("preferred_username") + return preferredUsername == null + } catch (e: Throwable) { + // Ingen request context. Skjer ved kall som har opphav i kjørende applikasjon. Ping etc. + true + } + } +} diff --git a/src/main/kotlin/no/nav/familie/tilbake/http/ConsumerIdClientInterceptor.kt b/src/main/kotlin/no/nav/familie/tilbake/http/ConsumerIdClientInterceptor.kt new file mode 100644 index 000000000..e504f528c --- /dev/null +++ b/src/main/kotlin/no/nav/familie/tilbake/http/ConsumerIdClientInterceptor.kt @@ -0,0 +1,22 @@ +package no.nav.familie.tilbake.http + +import org.springframework.beans.factory.annotation.Value +import org.springframework.http.HttpRequest +import org.springframework.http.client.ClientHttpRequestExecution +import org.springframework.http.client.ClientHttpRequestInterceptor +import org.springframework.http.client.ClientHttpResponse +import org.springframework.stereotype.Component + +@Component +class ConsumerIdClientInterceptor( + @Value("\${application.name}") private val appName: String +) : ClientHttpRequestInterceptor { + override fun intercept( + request: HttpRequest, + body: ByteArray, + execution: ClientHttpRequestExecution, + ): ClientHttpResponse { + request.headers.add("Nav-Consumer-Id", appName) + return execution.execute(request, body) + } +} diff --git a/src/main/kotlin/no/nav/familie/tilbake/http/MdcValuesPropagatingClientInterceptor.kt b/src/main/kotlin/no/nav/familie/tilbake/http/MdcValuesPropagatingClientInterceptor.kt new file mode 100644 index 000000000..4dd5d6be8 --- /dev/null +++ b/src/main/kotlin/no/nav/familie/tilbake/http/MdcValuesPropagatingClientInterceptor.kt @@ -0,0 +1,19 @@ +package no.nav.familie.tilbake.http + +import java.util.UUID +import org.slf4j.MDC +import org.springframework.http.HttpRequest +import org.springframework.http.client.ClientHttpRequestExecution +import org.springframework.http.client.ClientHttpRequestInterceptor +import org.springframework.http.client.ClientHttpResponse + +class MdcValuesPropagatingClientInterceptor : ClientHttpRequestInterceptor { + override fun intercept(request: HttpRequest, body: ByteArray, execution: ClientHttpRequestExecution): ClientHttpResponse { + val callId = MDC.get("callId") ?: UUID.randomUUID().toString() + val requestId = MDC.get("requestId") ?: callId + request.headers.add("Nav-Call-Id", callId) + request.headers.add("X-Request-ID", requestId) + + return execution.execute(request, body) + } +} diff --git a/src/main/kotlin/no/nav/familie/tilbake/http/RessursException.kt b/src/main/kotlin/no/nav/familie/tilbake/http/RessursException.kt new file mode 100644 index 000000000..7456afe7f --- /dev/null +++ b/src/main/kotlin/no/nav/familie/tilbake/http/RessursException.kt @@ -0,0 +1,11 @@ +package no.nav.familie.tilbake.http + +import no.nav.familie.kontrakter.felles.Ressurs +import org.springframework.http.HttpStatus +import org.springframework.web.client.RestClientResponseException + +class RessursException( + val ressurs: Ressurs, + cause: RestClientResponseException, + val httpStatus: HttpStatus = HttpStatus.valueOf(cause.statusCode.value()), +) : RuntimeException(cause) diff --git a/src/main/kotlin/no/nav/familie/tilbake/integration/familie/IntegrasjonerClient.kt b/src/main/kotlin/no/nav/familie/tilbake/integration/familie/IntegrasjonerClient.kt index c08c7ae89..3e27b72aa 100644 --- a/src/main/kotlin/no/nav/familie/tilbake/integration/familie/IntegrasjonerClient.kt +++ b/src/main/kotlin/no/nav/familie/tilbake/integration/familie/IntegrasjonerClient.kt @@ -1,6 +1,6 @@ package no.nav.familie.tilbake.integration.familie -import no.nav.familie.http.client.AbstractPingableRestClient +import AbstractPingableRestClient import no.nav.familie.kontrakter.felles.Fagsystem import no.nav.familie.kontrakter.felles.Fil import no.nav.familie.kontrakter.felles.Ressurs @@ -34,19 +34,13 @@ import org.springframework.stereotype.Component import org.springframework.web.client.RestOperations import org.springframework.web.util.UriComponentsBuilder import java.net.URI +import no.nav.familie.tilbake.log.SecureLog @Component class IntegrasjonerClient( @Qualifier("azure") restOperations: RestOperations, private val integrasjonerConfig: IntegrasjonerConfig, ) : AbstractPingableRestClient(restOperations, "familie.integrasjoner") { - override val pingUri: URI = - UriComponentsBuilder - .fromUri(integrasjonerConfig.integrasjonUri) - .path(IntegrasjonerConfig.PATH_PING) - .build() - .toUri() - private val arkiverUri: URI = UriComponentsBuilder .fromUri(integrasjonerConfig.integrasjonUri) @@ -265,11 +259,16 @@ class IntegrasjonerClient( ) } - fun hentJournalposterForBruker(journalposterForBrukerRequest: JournalposterForBrukerRequest): List { - secureLogger.info( - "henter journalposter for bruker med ident ${journalposterForBrukerRequest.brukerId} " + - "og data $journalposterForBrukerRequest", - ) + fun hentJournalposterForBruker( + journalposterForBrukerRequest: JournalposterForBrukerRequest, + logContext: SecureLog.Context, + ): List { + SecureLog.medContext(logContext) { + info( + "henter journalposter for bruker med ident ${journalposterForBrukerRequest.brukerId} " + + "og data $journalposterForBrukerRequest", + ) + } return postForEntity>>(hentJournalpostUri(), journalposterForBrukerRequest).getDataOrThrow() } diff --git a/src/main/kotlin/no/nav/familie/tilbake/integration/pdl/PdlClient.kt b/src/main/kotlin/no/nav/familie/tilbake/integration/pdl/PdlClient.kt index 065b068a0..b645dcae4 100644 --- a/src/main/kotlin/no/nav/familie/tilbake/integration/pdl/PdlClient.kt +++ b/src/main/kotlin/no/nav/familie/tilbake/integration/pdl/PdlClient.kt @@ -1,6 +1,6 @@ package no.nav.familie.tilbake.integration.pdl -import no.nav.familie.http.client.AbstractPingableRestClient +import AbstractPingableRestClient import no.nav.familie.kontrakter.felles.Fagsystem import no.nav.familie.kontrakter.felles.Tema import no.nav.familie.kontrakter.felles.objectMapper @@ -54,7 +54,9 @@ class PdlClient( logger.medContext(logContext) { warn("Advarsel ved henting av personinfo fra PDL. Se securelogs for detaljer.") } - secureLogger.warn("Advarsel ved henting av personinfo fra PDL: ${respons.extensions?.warnings}") + SecureLog.medContext(logContext) { + warn("Advarsel ved henting av personinfo fra PDL: ${respons.extensions?.warnings}") + } } if (!respons.harFeil()) { return respons.data.person!!.let { @@ -100,7 +102,9 @@ class PdlClient( logger.medContext(logContext) { warn("Advarsel ved henting av personidenter fra PDL. Se securelogs for detaljer.") } - secureLogger.warn("Advarsel ved henting av personidenter fra PDL: ${response.extensions?.warnings}") + SecureLog.medContext(logContext) { + warn("Advarsel ved henting av personidenter fra PDL: ${response.extensions?.warnings}") + } } if (!response.harFeil()) return response throw Feil( @@ -139,13 +143,6 @@ class PdlClient( add("behandlingsnummer", tema.behandlingsnummer) } - override val pingUri: URI - get() = pdlConfig.pdlUri - - override fun ping() { - operations.optionsForAllow(pingUri) - } - private fun mapTilTema(fagsystem: Fagsystem): Tema = when (fagsystem) { Fagsystem.EF -> Tema.ENF diff --git "a/src/main/kotlin/no/nav/familie/tilbake/integration/\303\270konomi/OppdragClient.kt" "b/src/main/kotlin/no/nav/familie/tilbake/integration/\303\270konomi/OppdragClient.kt" index 853d26181..5258db750 100644 --- "a/src/main/kotlin/no/nav/familie/tilbake/integration/\303\270konomi/OppdragClient.kt" +++ "b/src/main/kotlin/no/nav/familie/tilbake/integration/\303\270konomi/OppdragClient.kt" @@ -1,6 +1,6 @@ package no.nav.familie.tilbake.integration.økonomi -import no.nav.familie.http.client.AbstractPingableRestClient +import AbstractPingableRestClient import no.nav.familie.kontrakter.felles.Ressurs import no.nav.familie.kontrakter.felles.getDataOrThrow import no.nav.familie.kontrakter.felles.objectMapper @@ -83,13 +83,6 @@ class DefaultOppdragClient( OppdragClient { private val logger = TracedLogger.getLogger() - override val pingUri: URI = - UriComponentsBuilder - .fromUri(familieOppdragUrl) - .path(PING_PATH) - .build() - .toUri() - private fun iverksettelseUri(behandlingId: UUID): URI = UriComponentsBuilder .fromUri(familieOppdragUrl) diff --git a/src/main/kotlin/no/nav/familie/tilbake/sikkerhet/OIDCUtil.kt b/src/main/kotlin/no/nav/familie/tilbake/sikkerhet/OIDCUtil.kt new file mode 100644 index 000000000..40284fdf6 --- /dev/null +++ b/src/main/kotlin/no/nav/familie/tilbake/sikkerhet/OIDCUtil.kt @@ -0,0 +1,5 @@ +package no.nav.familie.tilbake.sikkerhet + +class OIDCUtil { + +} diff --git a/src/test/kotlin/no/nav/familie/tilbake/config/IntegrasjonerClientConfig.kt b/src/test/kotlin/no/nav/familie/tilbake/config/IntegrasjonerClientConfig.kt index 39df503b9..472cfce09 100644 --- a/src/test/kotlin/no/nav/familie/tilbake/config/IntegrasjonerClientConfig.kt +++ b/src/test/kotlin/no/nav/familie/tilbake/config/IntegrasjonerClientConfig.kt @@ -5,7 +5,6 @@ import io.mockk.every import io.mockk.just import io.mockk.mockk import io.mockk.slot -import no.nav.familie.http.client.RessursException import no.nav.familie.kontrakter.felles.Ressurs import no.nav.familie.kontrakter.felles.dokarkiv.ArkiverDokumentResponse import no.nav.familie.kontrakter.felles.dokarkiv.v2.ArkiverDokumentRequest @@ -29,6 +28,7 @@ import org.springframework.http.HttpStatus import org.springframework.web.client.RestClientResponseException import java.time.LocalDateTime import java.util.UUID +import no.nav.familie.tilbake.http.RessursException @Configuration @Profile("mock-integrasjoner") @@ -100,7 +100,7 @@ class IntegrasjonerClientConfig { every { integrasjonerClient.hentDokument(any(), any()) } returns readMockfileFromResources() - every { integrasjonerClient.hentJournalposterForBruker(any()) } + every { integrasjonerClient.hentJournalposterForBruker(any(), any()) } .returns( listOf( Journalpost(