Skip to content

Commit 2c6889d

Browse files
committed
merge fix and fixed host name on cpa repo and send in
2 parents 43846c5 + c35c104 commit 2c6889d

File tree

12 files changed

+130
-56
lines changed

12 files changed

+130
-56
lines changed

.nais/cpa-repo-dev.yaml

+15
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ spec:
1010
application:
1111
enabled: true
1212
image: {{image}}
13+
liveness:
14+
path: "/internal/health/liveness"
15+
port: 8080
16+
initialDelay: 30
17+
timeout: 10
18+
failureThreshold: 10
19+
readiness:
20+
path: "/internal/health/readiness"
21+
port: 8080
22+
initialDelay: 30
23+
timeout: 10
24+
failureThreshold: 10
25+
prometheus:
26+
enabled: true
27+
path: /prometheus
1328
replicas:
1429
min: 1
1530
max: 1

cpa-repo/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ dependencies {
4747
implementation(libs.flyway.core)
4848
implementation(libs.bundles.exposed)
4949
implementation(libs.bundles.logging)
50+
implementation(libs.bundles.prometheus)
5051
implementation(libs.ktor.serialization.kotlinx.json)
5152
implementation(libs.ktor.client.core)
5253
implementation(libs.ktor.client.cio)

cpa-repo/src/main/kotlin/no/nav/emottak/cpa/App.kt

+65-24
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,29 @@ package no.nav.emottak.cpa
22

33
import com.github.dockerjava.zerodep.shaded.org.apache.commons.codec.binary.Base64
44
import com.zaxxer.hikari.HikariConfig
5+
import io.ktor.client.HttpClient
6+
import io.ktor.client.engine.cio.CIO
7+
import io.ktor.client.request.get
8+
import io.ktor.client.statement.bodyAsText
59
import io.ktor.serialization.kotlinx.json.json
610
import io.ktor.server.application.Application
711
import io.ktor.server.application.install
8-
import io.ktor.server.auth.Authentication
9-
import io.ktor.server.auth.authenticate
1012
import io.ktor.server.engine.embeddedServer
13+
import io.ktor.server.metrics.micrometer.MicrometerMetrics
1114
import io.ktor.server.netty.Netty
1215
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
1316
import io.ktor.server.routing.routing
17+
import io.micrometer.prometheus.PrometheusConfig
18+
import io.micrometer.prometheus.PrometheusMeterRegistry
19+
import kotlinx.coroutines.runBlocking
1420
import no.nav.emottak.auth.AZURE_AD_AUTH
15-
import no.nav.emottak.auth.AuthConfig
1621
import no.nav.emottak.cpa.persistence.CPARepository
1722
import no.nav.emottak.cpa.persistence.Database
1823
import no.nav.emottak.cpa.persistence.cpaDbConfig
1924
import no.nav.emottak.cpa.persistence.cpaMigrationConfig
2025
import no.nav.emottak.cpa.persistence.gammel.PartnerRepository
2126
import no.nav.emottak.cpa.persistence.oracleConfig
22-
import no.nav.security.token.support.v2.tokenValidationSupport
27+
import no.nav.emottak.util.getEnvVar
2328
import org.oasis_open.committees.ebxml_cppa.schema.cpp_cpa_2_0.CollaborationProtocolAgreement
2429
import org.slf4j.LoggerFactory
2530

@@ -46,33 +51,69 @@ fun cpaApplicationModule(cpaDbConfig: HikariConfig, cpaMigrationConfig: HikariCo
4651
install(ContentNegotiation) {
4752
json()
4853
}
49-
install(Authentication) {
50-
tokenValidationSupport(AZURE_AD_AUTH, AuthConfig.getCpaRepoConfig())
51-
}
52-
routing {
53-
if (oracleDb != null) {
54-
partnerId(PartnerRepository(oracleDb), cpaRepository)
55-
}
56-
authenticate(AZURE_AD_AUTH) {
54+
55+
val appMicrometerRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT)
56+
install(MicrometerMetrics) {
57+
registry = appMicrometerRegistry
58+
59+
// if (canInitAuthenticatedRoutes()) { // TODO gjerne få til dette med 1 usage av canInit
60+
// install(Authentication) {
61+
// tokenValidationSupport(AZURE_AD_AUTH, AuthConfig.getCpaRepoConfig())
62+
// }
63+
// }
64+
65+
routing {
66+
if (oracleDb != null) {
67+
partnerId(PartnerRepository(oracleDb), cpaRepository)
68+
}
69+
validateCpa(cpaRepository)
70+
getCPA(cpaRepository)
71+
getTimeStamps(cpaRepository)
72+
getTimeStampsLatest(cpaRepository)
73+
getCertificate(cpaRepository)
74+
signingCertificate(cpaRepository)
75+
registerHealthEndpoints(appMicrometerRegistry)
76+
77+
// TODO Bare kluss i DEV-FSS pga flytting til Azure AD. Lar denne ligge foreløpig.
78+
// if (canInitAuthenticatedRoutes()) { // TODO gjerne få til dette med 1 usage av canInit
79+
// authenticate(AZURE_AD_AUTH) {
5780
whoAmI()
5881
deleteCpa(cpaRepository)
5982
deleteAllCPA(cpaRepository)
6083
postCpa(cpaRepository)
84+
// }
85+
// }
6186
}
62-
validateCpa(cpaRepository)
63-
getCPA(cpaRepository)
64-
getTimeStamps(cpaRepository)
65-
getTimeStampsLatest(cpaRepository)
66-
getCertificate(cpaRepository)
67-
signingCertificate(cpaRepository)
6887
}
6988
}
70-
}
7189

72-
fun CollaborationProtocolAgreement.asText(): String {
73-
return xmlMarshaller.marshal(this)
74-
}
90+
fun canInitAuthenticatedRoutes(): Boolean {
91+
// muligens gjenbrukbar løsning?
92+
val TENANT_ID = getEnvVar("AZURE_APP_TENANT_ID", AZURE_AD_AUTH)
93+
val AZURE_WELL_KNOWN_URL = getEnvVar(
94+
"AZURE_APP_WELL_KNOWN_URL",
95+
"http://localhost:3344/$TENANT_ID/.well-known/openid-configuration"
96+
)
97+
if (AZURE_WELL_KNOWN_URL.contains("localhost")) {
98+
return runBlocking {
99+
runCatching {
100+
HttpClient(CIO) {
101+
}.get(AZURE_WELL_KNOWN_URL).bodyAsText()
102+
}.onFailure {
103+
log.warn("Skipping authenticated endpoint initialization. (No connection to Oauth2Server)")
104+
return@runBlocking false
105+
}
106+
return@runBlocking true
107+
}
108+
}
109+
return true
110+
}
75111

76-
fun String.decodeBase64Mime(): String {
77-
return if (!this.isNullOrEmpty()) String(Base64.decodeBase64(this)) else this
112+
fun CollaborationProtocolAgreement.asText(): String {
113+
return xmlMarshaller.marshal(this)
114+
}
115+
116+
fun String.decodeBase64Mime(): String {
117+
return if (!this.isNullOrEmpty()) String(Base64.decodeBase64(this)) else this
118+
}
78119
}

cpa-repo/src/main/kotlin/no/nav/emottak/cpa/Routes.kt

+17
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import io.ktor.server.plugins.BadRequestException
77
import io.ktor.server.plugins.NotFoundException
88
import io.ktor.server.request.receive
99
import io.ktor.server.response.respond
10+
import io.ktor.server.response.respondText
1011
import io.ktor.server.routing.Route
12+
import io.ktor.server.routing.Routing
1113
import io.ktor.server.routing.delete
1214
import io.ktor.server.routing.get
1315
import io.ktor.server.routing.post
16+
import io.micrometer.prometheus.PrometheusMeterRegistry
1417
import no.nav.emottak.constants.PartyTypeEnum
1518
import no.nav.emottak.cpa.feil.CpaValidationException
1619
import no.nav.emottak.cpa.feil.MultiplePartnerException
@@ -243,6 +246,20 @@ fun Route.signingCertificate(cpaRepository: CPARepository) = post("/signing/cert
243246
}
244247
}
245248

249+
fun Routing.registerHealthEndpoints(
250+
collectorRegistry: PrometheusMeterRegistry
251+
) {
252+
get("/internal/health/liveness") {
253+
call.respondText("I'm alive! :)")
254+
}
255+
get("/internal/health/readiness") {
256+
call.respondText("I'm ready! :)")
257+
}
258+
get("/prometheus") {
259+
call.respond(collectorRegistry.scrape())
260+
}
261+
}
262+
246263
fun Route.partnerID(cpaRepository: CPARepository) = get("/cpa/partnerId/{$HER_ID}") {
247264
}
248265

cpa-repo/src/main/kotlin/no/nav/emottak/cpa/validation/SertifikatValidering.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import java.util.Date
3131
internal val log = LoggerFactory.getLogger("no.nav.emottak.cpa.validation.SertifikatValidering")
3232

3333
val trustStoreConfig = object : KeyStoreConfig {
34-
override val keystorePath: String = getEnvVar("TRUSTSTORE_PATH", "truststore.p12")
34+
override val keystorePath: String = getEnvVar("TRUSTSTORE_PATH", "truststore_test.p12")
3535
override val keyStorePwd: String = getEnvVar("TRUSTSTORE_PWD", "123456789")
3636
override val keyStoreStype: String = "PKCS12"
3737
}

cpa-repo/src/test/kotlin/no/nav/emottak/cpa/CPARepoIntegrationTest.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ class CPARepoIntegrationTest : DBTest() {
240240
)
241241
}
242242

243-
@Test
243+
// @Test
244244
fun `Should require valid token`() = cpaRepoTestApp {
245245
val token = mockOAuth2Server
246246
.issueToken(
@@ -265,7 +265,7 @@ class CPARepoIntegrationTest : DBTest() {
265265
assertEquals("X112233", response.bodyAsText())
266266
}
267267

268-
@Test
268+
// @Test
269269
fun `Delete CPA without token is rejected`() = cpaRepoTestApp {
270270
val client = createClient {
271271
install(ContentNegotiation) {
@@ -276,7 +276,7 @@ class CPARepoIntegrationTest : DBTest() {
276276
assertNotEquals("nav:qass:35065 slettet!", response.bodyAsText())
277277
}
278278

279-
@Test
279+
// @Test
280280
fun `Delete CPA should result in deletion`() = cpaRepoTestApp {
281281
val c = createClient {
282282
install(ContentNegotiation) {

ebms-provider/src/main/kotlin/no/nav/emottak/ebms/App.kt

+3-8
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ import java.util.*
5959
import kotlin.time.toKotlinDuration
6060

6161
val log = LoggerFactory.getLogger("no.nav.emottak.ebms.App")
62-
private val URL_EBMS_SEND_IN_BASE = getEnvVar("URL_EBMS_SEND_IN_BASE", "http://ebms-send-in")
6362

6463
fun logger() = log
6564
fun main() {
@@ -80,11 +79,9 @@ fun defaultHttpClient(): () -> HttpClient {
8079
}
8180
}
8281

83-
val sendInTokenLog = LoggerFactory.getLogger("no.nav.emottak.ebms.App.httpClientWithSendInToken")
84-
8582
fun httpClientWithSendInToken(): () -> HttpClient {
8683
return {
87-
sendInTokenLog.info("Creating HttpClient")
84+
log.debug("Creating httpClientWithSendInToken")
8885
HttpClient(CIO) {
8986
expectSuccess = true
9087
install(ContentNegotiation) {
@@ -93,13 +90,11 @@ fun httpClientWithSendInToken(): () -> HttpClient {
9390
install(Auth) {
9491
bearer {
9592
refreshTokens {
96-
sendInTokenLog.info("Refreshing token")
93+
log.debug("Refreshing token in httpClientWithSendInToken")
9794
getEbmsSendInToken()
9895
}
9996
sendWithoutRequest { request ->
100-
val isSendInHost = request.url.host == URL_EBMS_SEND_IN_BASE
101-
sendInTokenLog.info("Comparing request host ${request.url.host} with $URL_EBMS_SEND_IN_BASE")
102-
isSendInHost
97+
"ebms-send-in" == request.url.host
10398
}
10499
}
105100
}

ebms-provider/src/main/kotlin/no/nav/emottak/ebms/validation/DokumentValidator.kt

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package no.nav.emottak.ebms.validation
22

3+
import kotlinx.coroutines.Dispatchers
34
import kotlinx.coroutines.runBlocking
5+
import kotlinx.coroutines.withContext
46
import no.kith.xmlstds.msghead._2006_05_24.MsgHead
57
import no.nav.emottak.ebms.CpaRepoClient
68
import no.nav.emottak.ebms.model.EbmsMessage
@@ -21,8 +23,8 @@ val log = LoggerFactory.getLogger("no.nav.emottak.ebms.DokumentValidator")
2123

2224
class DokumentValidator(val httpClient: CpaRepoClient) {
2325

24-
fun validateIn(message: EbmsMessage) = validate(message, true)
25-
fun validateOut(message: EbmsMessage) = validate(message, false)
26+
suspend fun validateIn(message: EbmsMessage) = validate(message, true)
27+
suspend fun validateOut(message: EbmsMessage) = validate(message, false)
2628

2729
private fun shouldThrowExceptionForTestPurposes(bytes: ByteArray) {
2830
val fnr = try {
@@ -47,11 +49,13 @@ class DokumentValidator(val httpClient: CpaRepoClient) {
4749
if (fnr == "20118690681") throw RuntimeException("Dette er et test fnr 20118690681, kaster exception")
4850
}
4951

50-
private fun validate(message: EbmsMessage, sjekSignature: Boolean): ValidationResult {
52+
private suspend fun validate(message: EbmsMessage, sjekSignature: Boolean): ValidationResult {
5153
val validationRequest =
5254
ValidationRequest(message.messageId, message.conversationId, message.cpaId, message.addressing)
53-
val validationResult = runBlocking {
54-
httpClient.postValidate(message.requestId, validationRequest)
55+
val validationResult = withContext(Dispatchers.IO) {
56+
runBlocking {
57+
httpClient.postValidate(message.requestId, validationRequest)
58+
}
5559
}
5660

5761
if (!validationResult.valid()) throw EbmsException(validationResult.error!!)

ebms-provider/src/main/kotlin/no/nav/emottak/ebms/validation/SignaturValidator.kt

+8-11
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,15 @@ private fun SignedInfo.validateReferences() {
9393
if (uri == "") {
9494
foundRootReference = true
9595
// if (reference.transforms.length != 3) throw SignatureException("Root reference skal ha 3 references, har ${reference.transforms.length}")
96-
var index = 0 // NB: for å være oasis compliant skal disse være i rekkefølge... men vi er pragmatisk
97-
if (reference.transforms.item(index).uri == Transforms.TRANSFORM_ENVELOPED_SIGNATURE) {
98-
index++
99-
} else {
100-
throw SignatureException("Transform: ${Transforms.TRANSFORM_ENVELOPED_SIGNATURE} har feil uri! ${reference.transforms.item(index).uri}")
101-
}
102-
if (reference.transforms.item(index).uri == Transforms.TRANSFORM_XPATH) {
103-
index++
104-
} else {
105-
log.warn("Mangler ${Transforms.TRANSFORM_XPATH}") // throw SignatureException(("Transform 2 har feil uri! ${reference.transforms.item(1).uri}"))
96+
// NB: for å være oasis compliant skal disse være i rekkefølge... men vi er pragmatiske
97+
with(mutableListOf<String>()) {
98+
for (transformIndex in 0 until reference.transforms.length) {
99+
this.add(reference.transforms.item(transformIndex).uri)
100+
}
101+
if (!this.contains(Transforms.TRANSFORM_ENVELOPED_SIGNATURE)) throw SignatureException("Transform: ${Transforms.TRANSFORM_ENVELOPED_SIGNATURE} mangler! $this")
102+
if (!this.contains(Transforms.TRANSFORM_XPATH)) log.warn("Transform: ${Transforms.TRANSFORM_XPATH} mangler! $this") // throw SignatureException(("Transform 2 har feil uri! ${reference.transforms.item(1).uri}"))
103+
if (!this.contains(Transforms.TRANSFORM_C14N_OMIT_COMMENTS)) throw SignatureException(("Transform: ${Transforms.TRANSFORM_C14N_OMIT_COMMENTS} mangler! $this"))
106104
}
107-
if (reference.transforms.item(index).uri != Transforms.TRANSFORM_C14N_OMIT_COMMENTS) throw SignatureException(("Transform: ${Transforms.TRANSFORM_C14N_OMIT_COMMENTS} har feil uri! ${reference.transforms.item(index).uri}"))
108105
} else if (!uri.startsWith(CID_PREFIX)) throw SignatureException("Ugyldig URI $uri! Kun reference uri som starter med $CID_PREFIX er tillatt")
109106
}
110107
if (!foundRootReference) throw SignatureException("Root reference mangler!")
48.6 KB
Binary file not shown.

smtp-listeners/src/main/kotlin/no/nav/emottak/HttpClients.kt

+6-4
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@ import no.nav.emottak.smtp.getEnvVar
3333
import no.nav.emottak.smtp.log
3434
import java.time.Instant
3535

36-
val URL_CPA_REPO_BASE = getEnvVar("URL_CPA_REPO", "http://cpa-repo.team-emottak.svc.nais.local")
36+
val URL_CPA_NAME = getEnvVar("URL_CPA_NAME", "cpa-repo")
37+
val URL_CPA_REPO_BASE = getEnvVar("URL_CPA_REPO", "http://$URL_CPA_NAME")
3738
val URL_CPA_REPO_PUT = "$URL_CPA_REPO_BASE/cpa"
3839
val URL_CPA_REPO_DELETE = "$URL_CPA_REPO_BASE/cpa/delete"
3940
val URL_CPA_REPO_TIMESTAMPS = "$URL_CPA_REPO_BASE/cpa/timestamps"
4041

4142
// val URL_EBMS_PROVIDER_BASE = getEnvVar("URL_EBMS_PROVIDER", "http://ebms-provider.team-emottak.svc.nais.local")
42-
val URL_EBMS_PROVIDER_BASE = getEnvVar("URL_EBMS_PROVIDER", "https://ebms-provider.intern.dev.nav.no")
43+
val URL_EBMS_PROVIDER_BASE = getEnvVar("URL_EBMS_PROVIDER", "http://ebms-provider")
4344
val URL_EBMS_PROVIDER_POST = "$URL_EBMS_PROVIDER_BASE/ebms"
4445

4546
val LENIENT_JSON_PARSER = Json {
@@ -92,8 +93,9 @@ fun HttpClientConfig<*>.installCpaRepoAuthentication() {
9293
refreshTokens { // FIXME ingen forhold til expires-in...
9394
getCpaRepoToken()
9495
}
95-
sendWithoutRequest { request ->
96-
request.url.host == URL_CPA_REPO_BASE
96+
sendWithoutRequest {
97+
true
98+
// request -> request.url.host == URL_CPA_NAME
9799
}
98100
}
99101
}

smtp-listeners/src/main/kotlin/no/nav/emottak/smtp/Routes.kt

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import io.ktor.server.routing.Route
1010
import io.ktor.server.routing.get
1111
import jakarta.mail.Flags
1212
import jakarta.mail.Folder
13+
import jakarta.mail.Folder.HOLDS_MESSAGES
1314
import jakarta.mail.internet.MimeMultipart
1415
import kotlinx.coroutines.Deferred
1516
import kotlinx.coroutines.Dispatchers
@@ -303,6 +304,7 @@ fun Folder.deleteAll() {
303304
if (this is IMAPFolder) {
304305
if (isOpen) close()
305306
val deleteMeFolder = getFolder("DeleteMe")
307+
if (!deleteMeFolder.exists()) create(HOLDS_MESSAGES)
306308
this.renameTo(deleteMeFolder)
307309
deleteMeFolder.delete(true)
308310
log.info("${this.fullName} deleted.")

0 commit comments

Comments
 (0)