From 094d38d912b64e035b4b3fb67da96c7bb6fa3774 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Wed, 30 Oct 2024 09:59:36 +0100 Subject: [PATCH 1/3] Lagt til timout i byggsteg i alle workflows, justert noen dependency-navn --- .github/workflows/api-start-stopp.yaml | 3 ++- .github/workflows/bekreftelse-api.yaml | 3 ++- .../bekreftelse-min-side-varsler.yaml | 3 ++- .github/workflows/bekreftelse-tjeneste.yaml | 3 ++- .github/workflows/bekreftelse-utgang.yaml | 3 ++- .github/workflows/hendelselogg-backup.yaml | 3 ++- .github/workflows/hendelseprosessor.yaml | 3 ++- .github/workflows/kafka-key-generator.yaml | 3 ++- .../utgang-formidlingsgruppe-deploy.yaml | 3 ++- .github/workflows/utgang-pdl-deploy.yaml | 3 ++- .../api-start-stopp-perioder/build.gradle.kts | 2 +- apps/bekreftelse-api/build.gradle.kts | 2 +- .../build.gradle.kts | 4 ++-- .../build.gradle.kts | 4 ++-- domain/main-avro-schema/build.gradle.kts | 4 ++-- gradle/libs.versions.toml | 21 +++++++++++-------- 16 files changed, 40 insertions(+), 27 deletions(-) diff --git a/.github/workflows/api-start-stopp.yaml b/.github/workflows/api-start-stopp.yaml index 3454c86a..6331e162 100644 --- a/.github/workflows/api-start-stopp.yaml +++ b/.github/workflows/api-start-stopp.yaml @@ -21,11 +21,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/.github/workflows/bekreftelse-api.yaml b/.github/workflows/bekreftelse-api.yaml index 4766bc14..a0c8482b 100644 --- a/.github/workflows/bekreftelse-api.yaml +++ b/.github/workflows/bekreftelse-api.yaml @@ -22,11 +22,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/.github/workflows/bekreftelse-min-side-varsler.yaml b/.github/workflows/bekreftelse-min-side-varsler.yaml index afeb0be9..e85d20fd 100644 --- a/.github/workflows/bekreftelse-min-side-varsler.yaml +++ b/.github/workflows/bekreftelse-min-side-varsler.yaml @@ -21,11 +21,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/.github/workflows/bekreftelse-tjeneste.yaml b/.github/workflows/bekreftelse-tjeneste.yaml index 089925cb..5bc32e6a 100644 --- a/.github/workflows/bekreftelse-tjeneste.yaml +++ b/.github/workflows/bekreftelse-tjeneste.yaml @@ -22,11 +22,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/.github/workflows/bekreftelse-utgang.yaml b/.github/workflows/bekreftelse-utgang.yaml index 9f337e17..4e6dc957 100644 --- a/.github/workflows/bekreftelse-utgang.yaml +++ b/.github/workflows/bekreftelse-utgang.yaml @@ -22,11 +22,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/.github/workflows/hendelselogg-backup.yaml b/.github/workflows/hendelselogg-backup.yaml index 5333b7e0..3c636c3b 100644 --- a/.github/workflows/hendelselogg-backup.yaml +++ b/.github/workflows/hendelselogg-backup.yaml @@ -21,11 +21,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/.github/workflows/hendelseprosessor.yaml b/.github/workflows/hendelseprosessor.yaml index 41266a34..6029a552 100644 --- a/.github/workflows/hendelseprosessor.yaml +++ b/.github/workflows/hendelseprosessor.yaml @@ -21,11 +21,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/.github/workflows/kafka-key-generator.yaml b/.github/workflows/kafka-key-generator.yaml index ea795c72..0945f666 100644 --- a/.github/workflows/kafka-key-generator.yaml +++ b/.github/workflows/kafka-key-generator.yaml @@ -21,11 +21,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/.github/workflows/utgang-formidlingsgruppe-deploy.yaml b/.github/workflows/utgang-formidlingsgruppe-deploy.yaml index 2fefcb6e..644f7733 100644 --- a/.github/workflows/utgang-formidlingsgruppe-deploy.yaml +++ b/.github/workflows/utgang-formidlingsgruppe-deploy.yaml @@ -21,11 +21,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/.github/workflows/utgang-pdl-deploy.yaml b/.github/workflows/utgang-pdl-deploy.yaml index 22603e1f..423f00cb 100644 --- a/.github/workflows/utgang-pdl-deploy.yaml +++ b/.github/workflows/utgang-pdl-deploy.yaml @@ -21,11 +21,12 @@ env: jobs: build: name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read id-token: write packages: write - runs-on: ubuntu-latest outputs: image: ${{ steps.docker-build-push.outputs.image }} steps: diff --git a/apps/api-start-stopp-perioder/build.gradle.kts b/apps/api-start-stopp-perioder/build.gradle.kts index 1cdcd08a..e8482dba 100644 --- a/apps/api-start-stopp-perioder/build.gradle.kts +++ b/apps/api-start-stopp-perioder/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { implementation(libs.nav.common.tokenClient) implementation(libs.nav.common.auditLog) implementation(libs.nav.common.log) - implementation(libs.poao.tilgangClient) + implementation(libs.nav.poao.tilgangClient) implementation(libs.logbackClassic) implementation(libs.logstashLogbackEncoder) implementation(libs.kafka.clients) diff --git a/apps/bekreftelse-api/build.gradle.kts b/apps/bekreftelse-api/build.gradle.kts index 5167a589..7d476d1c 100644 --- a/apps/bekreftelse-api/build.gradle.kts +++ b/apps/bekreftelse-api/build.gradle.kts @@ -42,7 +42,7 @@ dependencies { implementation(libs.nav.security.tokenValidationKtorV2) // Authorization - implementation(libs.poao.tilgangClient) + implementation(libs.nav.poao.tilgangClient) // Documentation implementation(libs.ktor.server.openapi) diff --git a/domain/bekreftelse-paavegneav-avro-schema/build.gradle.kts b/domain/bekreftelse-paavegneav-avro-schema/build.gradle.kts index 097500ca..06689276 100644 --- a/domain/bekreftelse-paavegneav-avro-schema/build.gradle.kts +++ b/domain/bekreftelse-paavegneav-avro-schema/build.gradle.kts @@ -10,8 +10,8 @@ val schema by configurations.creating { } dependencies { - schema(libs.paw.schema.bekreftelse.paavegneav) - implementation(libs.paw.schema.bekreftelse.paavegneav) + schema(libs.nav.paw.schema.bekreftelse.paavegneav) + implementation(libs.nav.paw.schema.bekreftelse.paavegneav) api(libs.avro.core) } diff --git a/domain/bekreftelsesmelding-avro-schema/build.gradle.kts b/domain/bekreftelsesmelding-avro-schema/build.gradle.kts index 3b5cf307..0b0241b9 100644 --- a/domain/bekreftelsesmelding-avro-schema/build.gradle.kts +++ b/domain/bekreftelsesmelding-avro-schema/build.gradle.kts @@ -10,8 +10,8 @@ val schema by configurations.creating { } dependencies { - schema(libs.paw.schema.bekreftelsesmelding) - implementation(libs.paw.schema.bekreftelsesmelding) + schema(libs.nav.paw.schema.bekreftelsesmelding) + implementation(libs.nav.paw.schema.bekreftelsesmelding) api(libs.avro.core) } diff --git a/domain/main-avro-schema/build.gradle.kts b/domain/main-avro-schema/build.gradle.kts index 5ec4173c..b7f4e508 100644 --- a/domain/main-avro-schema/build.gradle.kts +++ b/domain/main-avro-schema/build.gradle.kts @@ -10,8 +10,8 @@ val schema by configurations.creating { } dependencies { - schema(libs.paw.schema.main) - api(libs.paw.schema.main) + schema(libs.nav.paw.schema.main) + api(libs.nav.paw.schema.main) api(libs.avro.core) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7c481d64..565551c6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,8 @@ [versions] noNavSecurityVersion = "5.0.5" +noNavSecurityMockOauth2ServerVersion = "2.1.5" noNavCommonVersion = "3.2024.05.23_05.46-2b29fa343e8e" +navPoaoTilgangClientVersion = "2024.04.29_13.59-a0ddddd36ac9" arbeidssokerregisteretVersion = "1.9348086045.48-1" bekreftelseSchemaVersion = "24.10.28.13-1" arrowVersion = "1.2.4" @@ -66,7 +68,6 @@ opentelemetry-ktor = { group = "io.opentelemetry.instrumentation", name = "opent opentelemetry-annotations = { group = "io.opentelemetry.instrumentation", name = "opentelemetry-instrumentation-annotations", version.ref = "otelInstrumentationVersion" } micrometerCore = { group = "io.micrometer", name = "micrometer-core", version.ref = "micrometerVersion" } micrometer-registryPrometheus = { group = "io.micrometer", name = "micrometer-registry-prometheus", version.ref = "micrometerVersion" } -paw-schema-main = { group = "no.nav.paw.arbeidssokerregisteret.api", name = "main-avro-schema", version.ref = "arbeidssokerregisteretVersion" } kafka-clients = { group = "org.apache.kafka", name = "kafka-clients", version.ref = "orgApacheKafkaVersion" } kafka-streams-core = { group = "org.apache.kafka", name = "kafka-streams", version.ref = "orgApacheKafkaVersion" } kafka-streams-test = { group = "org.apache.kafka", name = "kafka-streams-test-utils", version.ref = "orgApacheKafkaVersion" } @@ -76,11 +77,6 @@ avro-kafkaStreamsSerde = { group = "io.confluent", name = "kafka-streams-avro-se jackson-datatypeJsr310 = { group = "com.fasterxml.jackson.datatype", name = "jackson-datatype-jsr310", version.ref = "comFasterxmlJacksonVersion" } jackson-kotlin = { group = "com.fasterxml.jackson.module", name = "jackson-module-kotlin", version.ref = "comFasterxmlJacksonVersion" } jackson-core = { group = "com.fasterxml.jackson.core", name = "jackson-core", version.ref = "comFasterxmlJacksonVersion" } -nav-common-tokenClient = { group = "no.nav.common", name = "token-client", version.ref = "noNavCommonVersion" } -nav-common-log = { group = "no.nav.common", name = "log", version.ref = "noNavCommonVersion" } -nav-common-auditLog = { group = "no.nav.common", name = "audit-log", version.ref = "noNavCommonVersion" } -nav-security-tokenValidationKtorV2 = { group = "no.nav.security", name = "token-validation-ktor-v2", version.ref = "noNavSecurityVersion" } -nav-security-tokenClientCore = { group = "no.nav.security", name = "token-client-core", version.ref = "noNavSecurityVersion" } graphql-client = { group = "com.expediagroup", name = "graphql-kotlin-client", version.ref = "graphqlClientVersion" } graphql-ktor-client = { group = "com.expediagroup", name = "graphql-kotlin-ktor-client", version.ref = "graphqlClientVersion" } hoplite-core = { group = "com.sksamuel.hoplite", name = "hoplite-core", version.ref = "comSksamuelHopliteVersion" } @@ -102,9 +98,16 @@ database-postgres-driver = { group = "org.postgresql", name = "postgresql", vers database-flyway-core = { group = "org.flywaydb", name = "flyway-core", version.ref = "flywayVersion" } database-flyway-postgres = { group = "org.flywaydb", name = "flyway-database-postgresql", version.ref = "flywayVersion" } database-hikari-connectionPool = { group = "com.zaxxer", name = "HikariCP", version.ref = "hikariVersion" } -poao-tilgangClient = { group = "no.nav.poao-tilgang", name = "client", version = "2024.04.29_13.59-a0ddddd36ac9" } -paw-schema-bekreftelse-paavegneav = { group = "no.nav.paw.arbeidssokerregisteret.api", name = "bekreftelse-paavegneav-schema", version.ref = "bekreftelseSchemaVersion" } -paw-schema-bekreftelsesmelding = { group = "no.nav.paw.arbeidssokerregisteret.api", name = "bekreftelsesmelding-schema", version.ref = "bekreftelseSchemaVersion" } +nav-common-tokenClient = { group = "no.nav.common", name = "token-client", version.ref = "noNavCommonVersion" } +nav-common-log = { group = "no.nav.common", name = "log", version.ref = "noNavCommonVersion" } +nav-common-auditLog = { group = "no.nav.common", name = "audit-log", version.ref = "noNavCommonVersion" } +nav-security-tokenClientCore = { group = "no.nav.security", name = "token-client-core", version.ref = "noNavSecurityVersion" } +nav-security-tokenValidationKtorV2 = { group = "no.nav.security", name = "token-validation-ktor-v2", version.ref = "noNavSecurityVersion" } +nav-security-mockOauth2Server = { group = "no.nav.security", name = "mock-oauth2-server", version.ref = "noNavSecurityMockOauth2ServerVersion" } +nav-poao-tilgangClient = { group = "no.nav.poao-tilgang", name = "client", version.ref = "navPoaoTilgangClientVersion" } +nav-paw-schema-main = { group = "no.nav.paw.arbeidssokerregisteret.api", name = "main-avro-schema", version.ref = "arbeidssokerregisteretVersion" } +nav-paw-schema-bekreftelse-paavegneav = { group = "no.nav.paw.arbeidssokerregisteret.api", name = "bekreftelse-paavegneav-schema", version.ref = "bekreftelseSchemaVersion" } +nav-paw-schema-bekreftelsesmelding = { group = "no.nav.paw.arbeidssokerregisteret.api", name = "bekreftelsesmelding-schema", version.ref = "bekreftelseSchemaVersion" } [bundles] ktorServerWithNettyAndMicrometer = ["ktor-server-core", "ktor-server-coreJvm", "ktor-server-netty", "ktor-server-metricsMicrometer"] From 33d6f7af8040edea6e49867cb434612b9c5a45b6 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Wed, 30 Oct 2024 10:14:47 +0100 Subject: [PATCH 2/3] Lagt til felles sikkerhetsmodul --- lib/security/README.md | 3 + lib/security/build.gradle.kts | 24 ++++ .../exception/BearerTokenManglerException.kt | 6 + .../exception/IngenTilgangException.kt | 6 + .../exception/UgyldigBearerTokenException.kt | 6 + .../exception/UgyldigBrukerException.kt | 6 + .../security/authentication/model/Bruker.kt | 11 ++ .../authentication/model/Identitetsnummer.kt | 10 ++ .../authentication/token/AccessToken.kt | 95 ++++++++++++++ .../context/AuthorizationContext.kt | 6 + .../authorization/context/RequestContext.kt | 48 +++++++ .../authorization/context/SecurityContext.kt | 53 ++++++++ .../interceptor/AuthorizationInterceptor.kt | 25 ++++ .../authorization/model/AccessDecision.kt | 7 + .../authorization/model/AccessOperation.kt | 3 + .../authorization/model/AccessResult.kt | 6 + .../authorization/policy/AccessPolicy.kt | 8 ++ .../policy/AccessPolicyEvaluator.kt | 21 +++ .../authorization/RouteAuthorizationTest.kt | 61 +++++++++ .../authorization/policy/TestPolicies.kt | 19 +++ .../security/test/TestApplicationContext.kt | 120 ++++++++++++++++++ .../nav/paw/security/test/TokenTestUtils.kt | 80 ++++++++++++ settings.gradle.kts | 1 + 23 files changed, 625 insertions(+) create mode 100644 lib/security/README.md create mode 100644 lib/security/build.gradle.kts create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/BearerTokenManglerException.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/IngenTilgangException.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/UgyldigBearerTokenException.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/UgyldigBrukerException.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authentication/model/Bruker.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authentication/model/Identitetsnummer.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authentication/token/AccessToken.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/AuthorizationContext.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/RequestContext.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/SecurityContext.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authorization/interceptor/AuthorizationInterceptor.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessDecision.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessOperation.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessResult.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authorization/policy/AccessPolicy.kt create mode 100644 lib/security/src/main/kotlin/no/nav/paw/security/authorization/policy/AccessPolicyEvaluator.kt create mode 100644 lib/security/src/test/kotlin/no/nav/paw/security/authorization/RouteAuthorizationTest.kt create mode 100644 lib/security/src/test/kotlin/no/nav/paw/security/authorization/policy/TestPolicies.kt create mode 100644 lib/security/src/test/kotlin/no/nav/paw/security/test/TestApplicationContext.kt create mode 100644 lib/security/src/test/kotlin/no/nav/paw/security/test/TokenTestUtils.kt diff --git a/lib/security/README.md b/lib/security/README.md new file mode 100644 index 00000000..6e62c421 --- /dev/null +++ b/lib/security/README.md @@ -0,0 +1,3 @@ +# Sikkerhetsmodul + +Felles sikkerhetsmodul for autentisering og autorisering. diff --git a/lib/security/build.gradle.kts b/lib/security/build.gradle.kts new file mode 100644 index 00000000..02f9a88b --- /dev/null +++ b/lib/security/build.gradle.kts @@ -0,0 +1,24 @@ +plugins { + kotlin("jvm") +} + +dependencies { + implementation(project(":lib:error-handling")) + implementation(libs.ktor.server.auth) + implementation(libs.logbackClassic) + implementation(libs.nav.security.tokenValidationKtorV2) + + //Test + testImplementation(project(":lib:pdl-client")) + testImplementation(libs.nav.poao.tilgangClient) + testImplementation(libs.nav.security.mockOauth2Server) + testImplementation(libs.bundles.testLibsWithUnitTesting) + testImplementation(libs.ktor.server.testJvm) + testImplementation(libs.ktor.client.contentNegotiation) + testImplementation(libs.ktor.serialization.jackson) + testImplementation(libs.jackson.datatypeJsr310) +} + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/BearerTokenManglerException.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/BearerTokenManglerException.kt new file mode 100644 index 00000000..f69672e9 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/BearerTokenManglerException.kt @@ -0,0 +1,6 @@ +package no.nav.paw.security.authentication.exception + +import no.nav.paw.error.exception.AuthenticationException + +class BearerTokenManglerException(message: String) : + AuthenticationException("PAW_BEARER_TOKEN_MANGLER", message) \ No newline at end of file diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/IngenTilgangException.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/IngenTilgangException.kt new file mode 100644 index 00000000..973c8fe0 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/IngenTilgangException.kt @@ -0,0 +1,6 @@ +package no.nav.paw.security.authentication.exception + +import no.nav.paw.error.exception.AuthorizationException + +class IngenTilgangException(message: String) : + AuthorizationException("PAW_INGEN_TILGANG", message) \ No newline at end of file diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/UgyldigBearerTokenException.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/UgyldigBearerTokenException.kt new file mode 100644 index 00000000..5f64f323 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/UgyldigBearerTokenException.kt @@ -0,0 +1,6 @@ +package no.nav.paw.security.authentication.exception + +import no.nav.paw.error.exception.AuthorizationException + +class UgyldigBearerTokenException(message: String) : + AuthorizationException("PAW_UGYLDIG_BEARER_TOKEN", message) \ No newline at end of file diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/UgyldigBrukerException.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/UgyldigBrukerException.kt new file mode 100644 index 00000000..119f7ab9 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/exception/UgyldigBrukerException.kt @@ -0,0 +1,6 @@ +package no.nav.paw.security.authentication.exception + +import no.nav.paw.error.exception.AuthorizationException + +class UgyldigBrukerException(message: String) : + AuthorizationException("PAW_UGYLDIG_BRUKER", message) \ No newline at end of file diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authentication/model/Bruker.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/model/Bruker.kt new file mode 100644 index 00000000..e7313539 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/model/Bruker.kt @@ -0,0 +1,11 @@ +package no.nav.paw.security.authentication.model + +import java.util.* + +sealed class Bruker( + open val ident: ID +) + +data class Sluttbruker(override val ident: Identitetsnummer) : Bruker(ident) +data class NavAnsatt(val oid: UUID, override val ident: String) : Bruker(ident) +data class M2MToken(val oid: UUID) : Bruker("N/A") diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authentication/model/Identitetsnummer.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/model/Identitetsnummer.kt new file mode 100644 index 00000000..f371c5b7 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/model/Identitetsnummer.kt @@ -0,0 +1,10 @@ +package no.nav.paw.security.authentication.model + +@JvmInline +value class Identitetsnummer(val verdi: String) { + override fun toString(): String { + return "*".repeat(verdi.length) + } +} + +fun String.asIdentitetsnummer(): Identitetsnummer = Identitetsnummer(this) diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authentication/token/AccessToken.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/token/AccessToken.kt new file mode 100644 index 00000000..113a8dc0 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authentication/token/AccessToken.kt @@ -0,0 +1,95 @@ +package no.nav.paw.security.authentication.token + +import no.nav.paw.security.authentication.exception.UgyldigBearerTokenException +import no.nav.paw.security.authentication.model.Identitetsnummer +import no.nav.security.token.support.core.context.TokenValidationContext +import no.nav.security.token.support.core.jwt.JwtToken +import java.util.* + +data class AccessToken( + val jwt: String, + val issuer: Issuer, + val claims: Claims +) { + fun isM2MToken(): Boolean { + return claims.getOrNull(Roles)?.contains("access_as_application") ?: false + } +} + +sealed class Issuer(val name: String) + +data object IdPorten : Issuer("idporten") +data object TokenX : Issuer("tokenx") +data object AzureAd : Issuer("azure") + +class Claims(private val claims: Map, Any>) { + @Suppress("UNCHECKED_CAST") + fun getOrNull(claim: Claim): T? = claims[claim] as T? + + @Suppress("UNCHECKED_CAST") + fun getOrThrow(claim: Claim): T = claims[claim] as T? + ?: throw UgyldigBearerTokenException("Bearer Token mangler påkrevd claim ${claim.name}") + + fun isEmpty(): Boolean = claims.isEmpty() + + fun contains(claim: Claim<*>): Boolean = claims.containsKey(claim) +} + +abstract class Claim( + open val name: String, + open val resolve: (Any) -> A +) + +sealed class SingleClaim( + override val name: String, + override val resolve: (Any) -> A +) : Claim(name, resolve) + +sealed class ListClaim( + override val name: String, + override val resolve: (Any) -> List +) : Claim>(name, resolve) + +data object PID : SingleClaim("pid", { Identitetsnummer(it.toString()) }) +data object OID : SingleClaim("oid", { UUID.fromString(it.toString()) }) +data object Name : SingleClaim("name", { it.toString() }) +data object NavIdent : SingleClaim("NAVident", { it.toString() }) +data object Roles : ListClaim("roles", { value -> (value as List<*>).map { it.toString() } }) + +sealed class ResolveToken(val issuer: Issuer, val claims: List>) + +data object IdPortenToken : ResolveToken(IdPorten, listOf(PID)) +data object TokenXToken : ResolveToken(TokenX, listOf(PID)) +data object AzureAdToken : ResolveToken(AzureAd, listOf(OID, Name, NavIdent, Roles)) + +private val validTokens: List = listOf(IdPortenToken, TokenXToken, AzureAdToken) + +fun TokenValidationContext.resolveTokens(): List { + return validTokens + .mapNotNull { resolveToken -> + getJwtToken(resolveToken.issuer.name)?.let { resolveToken to it } + } + .map { (resolveToken, jwtToken) -> + val claims = jwtToken.resolveClaims(resolveToken) + AccessToken(jwtToken.encodedToken, resolveToken.issuer, claims) + } +} + +private fun JwtToken.resolveClaims(resolveToken: ResolveToken): Claims { + val claims = resolveToken.claims + .mapNotNull { claim -> + when (claim) { + is ListClaim<*> -> { + val value = jwtTokenClaims.getAsList(claim.name) + value?.let { claim to claim.resolve(value) } + } + + else -> { + val value = jwtTokenClaims.getStringClaim(claim.name) + value?.let { claim to claim.resolve(value) } + } + } + } + .toMap() + return Claims(claims) +} diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/AuthorizationContext.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/AuthorizationContext.kt new file mode 100644 index 00000000..cd8b1668 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/AuthorizationContext.kt @@ -0,0 +1,6 @@ +package no.nav.paw.security.authorization.context + +data class AuthorizationContext( + val requestContext: RequestContext, + val securityContext: SecurityContext +) diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/RequestContext.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/RequestContext.kt new file mode 100644 index 00000000..2a537822 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/RequestContext.kt @@ -0,0 +1,48 @@ +package no.nav.paw.security.authorization.context + +import io.ktor.http.HttpHeaders +import io.ktor.server.application.ApplicationCall +import io.ktor.server.application.call +import io.ktor.server.auth.principal +import io.ktor.server.request.ApplicationRequest +import io.ktor.util.pipeline.PipelineContext +import no.nav.security.token.support.v2.TokenValidationContextPrincipal + +sealed class NavHeader(val name: String) + +data object TraceParent : NavHeader("traceparent") +data object NavCallId : NavHeader("Nav-Call-Id") +data object NavConsumerId : NavHeader("Nav-Consumer-Id") +data object NavIdent : NavHeader("Nav-Ident") + +data class RequestHeaders( + val authorization: String?, + val navCallId: String?, + val traceParent: String?, + val navConsumerId: String?, + val navIdent: String?, +) + +data class RequestContext( + val request: ApplicationRequest, + val headers: RequestHeaders, + val principal: TokenValidationContextPrincipal? +) + +fun PipelineContext.resolveRequestContext(): RequestContext { + return RequestContext( + request = call.request, + headers = resolveRequestHeaders(), + principal = call.principal() + ) +} + +fun PipelineContext.resolveRequestHeaders(): RequestHeaders { + return RequestHeaders( + authorization = call.request.headers[HttpHeaders.Authorization], + traceParent = call.request.headers[TraceParent.name], + navCallId = call.request.headers[NavCallId.name], + navConsumerId = call.request.headers[NavConsumerId.name], + navIdent = call.request.headers[NavIdent.name], + ) +} \ No newline at end of file diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/SecurityContext.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/SecurityContext.kt new file mode 100644 index 00000000..087b5efd --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/context/SecurityContext.kt @@ -0,0 +1,53 @@ +package no.nav.paw.security.authorization.context + +import no.nav.paw.security.authentication.exception.BearerTokenManglerException +import no.nav.paw.security.authentication.exception.UgyldigBearerTokenException +import no.nav.paw.security.authentication.model.Bruker +import no.nav.paw.security.authentication.model.M2MToken +import no.nav.paw.security.authentication.model.NavAnsatt +import no.nav.paw.security.authentication.model.Sluttbruker +import no.nav.paw.security.authentication.token.AccessToken +import no.nav.paw.security.authentication.token.AzureAd +import no.nav.paw.security.authentication.token.IdPorten +import no.nav.paw.security.authentication.token.NavIdent +import no.nav.paw.security.authentication.token.OID +import no.nav.paw.security.authentication.token.PID +import no.nav.paw.security.authentication.token.TokenX +import no.nav.paw.security.authentication.token.resolveTokens + +data class SecurityContext( + val bruker: Bruker<*>, + val accessToken: AccessToken +) + +fun RequestContext.resolveSecurityContext(): SecurityContext { + val tokenContext = principal?.context ?: throw BearerTokenManglerException("Bearer Token mangler") + + val accessToken = tokenContext.resolveTokens().firstOrNull() // Kan støtte flere tokens + ?: throw UgyldigBearerTokenException("Ingen gyldige Bearer Tokens funnet") + + if (accessToken.claims.isEmpty()) { + throw UgyldigBearerTokenException("Bearer Token mangler påkrevd innhold") + } + + val bruker = when (accessToken.issuer) { + is IdPorten -> Sluttbruker(accessToken.claims.getOrThrow(PID)) + is TokenX -> Sluttbruker(accessToken.claims.getOrThrow(PID)) + is AzureAd -> { + if (accessToken.isM2MToken()) { + if (headers.navIdent.isNullOrBlank()) { + M2MToken(accessToken.claims.getOrThrow(OID)) + } else { + NavAnsatt(accessToken.claims.getOrThrow(OID), headers.navIdent) + } + } else { + NavAnsatt(accessToken.claims.getOrThrow(OID), accessToken.claims.getOrThrow(NavIdent)) + } + } + } + + return SecurityContext( + bruker = bruker, + accessToken = accessToken + ) +} diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authorization/interceptor/AuthorizationInterceptor.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/interceptor/AuthorizationInterceptor.kt new file mode 100644 index 00000000..af023103 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/interceptor/AuthorizationInterceptor.kt @@ -0,0 +1,25 @@ +package no.nav.paw.security.authorization.interceptor + +import io.ktor.server.application.ApplicationCall +import io.ktor.util.pipeline.PipelineContext +import no.nav.paw.security.authorization.context.AuthorizationContext +import no.nav.paw.security.authorization.context.resolveRequestContext +import no.nav.paw.security.authorization.context.resolveSecurityContext +import no.nav.paw.security.authorization.policy.AccessPolicy +import no.nav.paw.security.authorization.policy.AccessPolicyEvaluator +import org.slf4j.LoggerFactory + +private val logger = LoggerFactory.getLogger("no.nav.paw.logger.security.authorization") + +suspend fun PipelineContext.authorize( + policies: List = emptyList(), + body: suspend PipelineContext.(AuthorizationContext) -> Unit +): PipelineContext { + logger.debug("Kjører autorisasjon") + val requestContext = resolveRequestContext() + val securityContext = requestContext.resolveSecurityContext() + val authorizationContext = AuthorizationContext(requestContext, securityContext) + AccessPolicyEvaluator(policies).checkAccess(authorizationContext) + body(authorizationContext) + return this +} \ No newline at end of file diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessDecision.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessDecision.kt new file mode 100644 index 00000000..b45b3bc9 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessDecision.kt @@ -0,0 +1,7 @@ +package no.nav.paw.security.authorization.model + +enum class AccessDecision { + PERMIT, + DENY, + DEFER +} \ No newline at end of file diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessOperation.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessOperation.kt new file mode 100644 index 00000000..f86f50d1 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessOperation.kt @@ -0,0 +1,3 @@ +package no.nav.paw.security.authorization.model + +enum class AccessOperation { READ, WRITE } \ No newline at end of file diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessResult.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessResult.kt new file mode 100644 index 00000000..58774a10 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/model/AccessResult.kt @@ -0,0 +1,6 @@ +package no.nav.paw.security.authorization.model + +data class AccessResult( + val decision: AccessDecision, + val details: String +) \ No newline at end of file diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authorization/policy/AccessPolicy.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/policy/AccessPolicy.kt new file mode 100644 index 00000000..e1b31008 --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/policy/AccessPolicy.kt @@ -0,0 +1,8 @@ +package no.nav.paw.security.authorization.policy + +import no.nav.paw.security.authorization.context.AuthorizationContext +import no.nav.paw.security.authorization.model.AccessResult + +interface AccessPolicy { + fun hasAccess(context: AuthorizationContext): AccessResult +} diff --git a/lib/security/src/main/kotlin/no/nav/paw/security/authorization/policy/AccessPolicyEvaluator.kt b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/policy/AccessPolicyEvaluator.kt new file mode 100644 index 00000000..17d25e1c --- /dev/null +++ b/lib/security/src/main/kotlin/no/nav/paw/security/authorization/policy/AccessPolicyEvaluator.kt @@ -0,0 +1,21 @@ +package no.nav.paw.security.authorization.policy + +import no.nav.paw.security.authentication.exception.IngenTilgangException +import no.nav.paw.security.authorization.context.AuthorizationContext +import no.nav.paw.security.authorization.model.AccessDecision +import org.slf4j.LoggerFactory + +class AccessPolicyEvaluator(private val policies: List) { + + private val logger = LoggerFactory.getLogger("no.nav.paw.logger.security.authorization") + + fun checkAccess(context: AuthorizationContext) { + logger.debug("Sjekker {} tilgangsregler", policies.size) + val results = policies.map { it.hasAccess(context) } + val deny = results.filter { it.decision == AccessDecision.DENY } + if (deny.isNotEmpty()) { + logger.debug("Evaluering av tilgangsregler resulterte i {} DENY decisions [{}]", deny.size, deny) + throw IngenTilgangException("Ingen tilgang") + } + } +} \ No newline at end of file diff --git a/lib/security/src/test/kotlin/no/nav/paw/security/authorization/RouteAuthorizationTest.kt b/lib/security/src/test/kotlin/no/nav/paw/security/authorization/RouteAuthorizationTest.kt new file mode 100644 index 00000000..8930c7ae --- /dev/null +++ b/lib/security/src/test/kotlin/no/nav/paw/security/authorization/RouteAuthorizationTest.kt @@ -0,0 +1,61 @@ +package no.nav.paw.security.authorization + +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.shouldBe +import io.ktor.client.request.bearerAuth +import io.ktor.client.request.get +import io.ktor.http.HttpStatusCode +import io.ktor.server.testing.testApplication +import no.nav.paw.security.authorization.policy.TestDenyPolicy +import no.nav.paw.security.authorization.policy.TestPermitPolicy +import no.nav.paw.security.test.TestApplicationContext +import no.nav.paw.security.test.issueTokenXToken + +class RouteAuthorizationTest : FreeSpec({ + + with(TestApplicationContext()) { + + beforeSpec { + mockOAuth2Server.start() + } + + afterSpec { + mockOAuth2Server.shutdown() + } + + "Skal få 401 Unauthorized uten Bearer Token header" { + testApplication { + application { + configureApplication() + } + + val testClient = configureTestClient() + + val response = testClient.get("/api/dummy") + + response.status shouldBe HttpStatusCode.Unauthorized + } + } + + "Skal få 403 Forbidden ved en DENY policy" { + testApplication { + application { + configureApplication( + listOf( + TestPermitPolicy(), + TestDenyPolicy() + ) + ) + } + + val testClient = configureTestClient() + + val response = testClient.get("/api/dummy") { + bearerAuth(mockOAuth2Server.issueTokenXToken(pid = "01017012345")) + } + + response.status shouldBe HttpStatusCode.Forbidden + } + } + } +}) \ No newline at end of file diff --git a/lib/security/src/test/kotlin/no/nav/paw/security/authorization/policy/TestPolicies.kt b/lib/security/src/test/kotlin/no/nav/paw/security/authorization/policy/TestPolicies.kt new file mode 100644 index 00000000..2b232f65 --- /dev/null +++ b/lib/security/src/test/kotlin/no/nav/paw/security/authorization/policy/TestPolicies.kt @@ -0,0 +1,19 @@ +package no.nav.paw.security.authorization.policy + +import no.nav.paw.security.authorization.context.AuthorizationContext +import no.nav.paw.security.authorization.model.AccessDecision +import no.nav.paw.security.authorization.model.AccessResult + +class TestPermitPolicy : AccessPolicy { + + override fun hasAccess(context: AuthorizationContext): AccessResult { + return AccessResult(AccessDecision.PERMIT, "FULL STEAM AHEAD!") + } +} + +class TestDenyPolicy : AccessPolicy { + + override fun hasAccess(context: AuthorizationContext): AccessResult { + return AccessResult(AccessDecision.DENY, "YOU SHALL NOT PASS!") + } +} \ No newline at end of file diff --git a/lib/security/src/test/kotlin/no/nav/paw/security/test/TestApplicationContext.kt b/lib/security/src/test/kotlin/no/nav/paw/security/test/TestApplicationContext.kt new file mode 100644 index 00000000..ccc66401 --- /dev/null +++ b/lib/security/src/test/kotlin/no/nav/paw/security/test/TestApplicationContext.kt @@ -0,0 +1,120 @@ +package no.nav.paw.security.test + +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.SerializationFeature +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +import com.fasterxml.jackson.module.kotlin.registerKotlinModule +import io.ktor.client.HttpClient +import io.ktor.serialization.jackson.jackson +import io.ktor.server.application.Application +import io.ktor.server.application.call +import io.ktor.server.application.install +import io.ktor.server.auth.authenticate +import io.ktor.server.auth.authentication +import io.ktor.server.plugins.statuspages.StatusPages +import io.ktor.server.response.respond +import io.ktor.server.routing.IgnoreTrailingSlash +import io.ktor.server.routing.get +import io.ktor.server.routing.post +import io.ktor.server.routing.routing +import io.ktor.server.testing.ApplicationTestBuilder +import no.nav.paw.error.handler.handleException +import no.nav.paw.security.authorization.interceptor.authorize +import no.nav.paw.security.authorization.policy.AccessPolicy +import no.nav.security.mock.oauth2.MockOAuth2Server +import no.nav.security.token.support.v2.IssuerConfig +import no.nav.security.token.support.v2.RequiredClaims +import no.nav.security.token.support.v2.TokenSupportConfig +import no.nav.security.token.support.v2.tokenValidationSupport +import io.ktor.client.plugins.contentnegotiation.ContentNegotiation as ClientContentNegotiation +import io.ktor.server.plugins.contentnegotiation.ContentNegotiation as ServerContentNegotiation + +class TestApplicationContext { + + val mockOAuth2Server = MockOAuth2Server() + + fun ApplicationTestBuilder.configureTestClient(): HttpClient { + return createClient { + install(ClientContentNegotiation) { + jackson { + disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + registerModule(JavaTimeModule()) + registerKotlinModule() + } + } + } + } + + fun Application.configureApplication(policies: List = emptyList()) { + configureSerialization() + configureRequestHandling() + configureAuthentication() + configureRouting(policies) + } + + fun Application.configureRouting(policies: List = emptyList()) { + routing { + authenticate("tokenx") { + get("/api/dummy") { + authorize(policies) { + call.respond(TestResponse("All Quiet on the Western Front")) + } + } + + post("/api/dummy") { + authorize(policies) { + call.respond(TestResponse("All Quiet on the Western Front")) + } + } + } + } + } + + fun Application.configureSerialization() { + install(ServerContentNegotiation) { + jackson { + disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + registerModule(JavaTimeModule()) + registerKotlinModule() + } + } + } + + fun Application.configureRequestHandling() { + install(IgnoreTrailingSlash) + install(StatusPages) { + exception { call, cause -> + call.handleException(cause) + } + } + } + + + fun Application.configureAuthentication() { + val authProviders = mockOAuth2Server.getAuthProviders() + + authentication { + authProviders.forEach { authProvider -> + tokenValidationSupport( + name = authProvider.name, + config = TokenSupportConfig( + IssuerConfig( + name = authProvider.name, + discoveryUrl = authProvider.discoveryUrl, + acceptedAudience = authProvider.acceptedAudience + ) + ), + requiredClaims = RequiredClaims( + authProvider.name, + authProvider.claimMap, + authProvider.combineWithOr + ) + ) + } + } + } +} + +data class TestResponse(val message: String) diff --git a/lib/security/src/test/kotlin/no/nav/paw/security/test/TokenTestUtils.kt b/lib/security/src/test/kotlin/no/nav/paw/security/test/TokenTestUtils.kt new file mode 100644 index 00000000..25456410 --- /dev/null +++ b/lib/security/src/test/kotlin/no/nav/paw/security/test/TokenTestUtils.kt @@ -0,0 +1,80 @@ +package no.nav.paw.security.test + +import no.nav.security.mock.oauth2.MockOAuth2Server +import java.util.* + +fun MockOAuth2Server.issueIDPortenToken( + acr: String = "idporten-loa-high", + pid: String = "01017012345" +): String { + return issueToken( + claims = mapOf( + "acr" to acr, + "pid" to pid + ) + ).serialize() +} + +fun MockOAuth2Server.issueTokenXToken( + acr: String = "idporten-loa-high", + pid: String = "01017012345" +): String { + return issueToken( + claims = mapOf( + "acr" to acr, + "pid" to pid + ) + ).serialize() +} + +fun MockOAuth2Server.issueAzureADToken( + oid: UUID = UUID.randomUUID(), + name: String = "Kari Nordmann", + navIdent: String = "NAV12345" +): String { + return issueToken( + claims = mapOf( + "oid" to oid.toString(), + "name" to name, + "NAVident" to navIdent + ) + ).serialize() +} + +fun MockOAuth2Server.issueAzureM2MToken( + oid: UUID = UUID.randomUUID(), + roles: List = listOf("access_as_application"), +): String { + return issueToken( + claims = mapOf( + "oid" to oid.toString(), + "roles" to roles + ) + ).serialize() +} + +fun MockOAuth2Server.getAuthProviders(): List { + val issuerId = "default" + val wellKnownUrl = wellKnownUrl(issuerId).toString() + return listOf( + "idporten" to arrayOf("acr=idporten-loa-high"), + "tokenx" to arrayOf("acr=idporten-loa-high"), + "azure" to arrayOf("NAVident") + ).map { + AuthProvider( + name = it.first, + discoveryUrl = wellKnownUrl, + acceptedAudience = listOf(issuerId), + claimMap = it.second, + combineWithOr = true + ) + } +} + +data class AuthProvider( + val name: String, + val discoveryUrl: String, + val acceptedAudience: List, + val claimMap: Array, + val combineWithOr: Boolean +) diff --git a/settings.gradle.kts b/settings.gradle.kts index ae093c26..f3ebc404 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,6 +13,7 @@ rootProject.name = "paw-arbeidssoekerregisteret-monorepo-intern" include( "lib:hoplite-config", "lib:error-handling", + "lib:security", "lib:kafka", "lib:kafka-streams", "lib:kafka-key-generator-client", From a0aaf0df0120db50de399d3c41a50395dd237f01 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Wed, 30 Oct 2024 10:41:52 +0100 Subject: [PATCH 3/3] Endret intervaller for bekreftelse i dev --- .../no/nav/paw/arbeidssokerregisteret/ProducerMock.kt | 7 ++++++- apps/bekreftelse-tjeneste/nais/nais-dev.yaml | 8 ++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ProducerMock.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ProducerMock.kt index 11baa646..ae7a4d22 100644 --- a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ProducerMock.kt +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ProducerMock.kt @@ -6,7 +6,11 @@ import org.apache.kafka.clients.producer.Callback import org.apache.kafka.clients.producer.Producer import org.apache.kafka.clients.producer.ProducerRecord import org.apache.kafka.clients.producer.RecordMetadata -import org.apache.kafka.common.* +import org.apache.kafka.common.Metric +import org.apache.kafka.common.MetricName +import org.apache.kafka.common.PartitionInfo +import org.apache.kafka.common.TopicPartition +import org.apache.kafka.common.Uuid import java.time.Duration import java.time.Instant import java.util.concurrent.CompletableFuture @@ -26,6 +30,7 @@ class ProducerMock : Producer { override fun beginTransaction() {} + @Deprecated(message = "Use sendOffsetsToTransaction(Map, ConsumerGroupMetadata") override fun sendOffsetsToTransaction( offsets: MutableMap?, consumerGroupId: String? diff --git a/apps/bekreftelse-tjeneste/nais/nais-dev.yaml b/apps/bekreftelse-tjeneste/nais/nais-dev.yaml index 6a502dc1..3193f589 100644 --- a/apps/bekreftelse-tjeneste/nais/nais-dev.yaml +++ b/apps/bekreftelse-tjeneste/nais/nais-dev.yaml @@ -20,15 +20,15 @@ spec: - name: KAFKA_PAW_BEKREFTELSE_PAA_VEGNE_AV_TOPIC value: "paw.arbeidssoker-bekreftelse-paavegneav-beta-v1" - name: KAFKA_PUNCTUATOR_INTERVAL - value: "PT1M" + value: "PT1H" - name: BEKREFTELSE_MIGRERINGSTIDSPUNKT value: "2024-09-29T22:00:00Z" - name: BEKREFTELSE_INTERVAL - value: "PT28M" + value: "P1D" - name: BEKREFTELSE_GRACEPERIODE - value: "PT14M" + value: "PT12H" - name: BEKREFTELSE_TILGJENGELIG_OFFSET - value: "PT6M" + value: "PT6H" azure: application: enabled: true