Skip to content

Commit 31e81ff

Browse files
authored
Autentisere med azure (#118)
DAG-152 Autentisere med azure + oppgradering av java runtime ++
1 parent 7b7fc61 commit 31e81ff

26 files changed

+507
-295
lines changed

.github/workflows/dp-inntekt-api-deploy.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- name: Set up Java
1616
uses: actions/setup-java@v1
1717
with:
18-
java-version: '13.x'
18+
java-version: '17.x'
1919

2020
- name: Setup gradle dependency cache
2121
uses: actions/cache@v2

.github/workflows/dp-inntekt-grpc-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Set up Java
1717
uses: actions/setup-java@v1
1818
with:
19-
java-version: '13.x'
19+
java-version: '17.x'
2020

2121
- name: Cache gradle dependencies
2222
uses: actions/cache@v1

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM navikt/java:13
1+
FROM navikt/java:17
22

33
EXPOSE 50051
44

build.gradle.kts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ allprojects {
3030
}
3131

3232
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
33-
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
33+
kotlinOptions.jvmTarget = JavaVersion.VERSION_17.toString()
3434
}
3535

3636
java {
37-
sourceCompatibility = JavaVersion.VERSION_1_8
38-
targetCompatibility = JavaVersion.VERSION_1_8
37+
sourceCompatibility = JavaVersion.VERSION_17
38+
targetCompatibility = JavaVersion.VERSION_17
3939
}
4040

4141
tasks.withType<Wrapper> {
@@ -69,7 +69,7 @@ allprojects {
6969
}
7070

7171
repositories {
72-
jcenter()
72+
mavenCentral()
7373
maven("https://jitpack.io")
7474
}
7575
}

buildSrc/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ plugins {
33
}
44

55
repositories {
6-
jcenter()
6+
mavenCentral()
77
}

dp-inntekt-api/build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ plugins {
1010

1111
buildscript {
1212
repositories {
13-
jcenter()
13+
mavenCentral()
1414
}
1515
}
1616

@@ -98,6 +98,8 @@ dependencies {
9898
// https://youtrack.jetbrains.com/issue/KT-46090
9999
exclude("org.jetbrains.kotlin", "kotlin-test-junit")
100100
}
101+
102+
testImplementation("no.nav.security:mock-oauth2-server:0.4.3")
101103
testImplementation(Ktor.library("client-mock"))
102104
testImplementation(Junit5.api)
103105
testImplementation(Junit5.params)

dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/Application.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import io.prometheus.client.hotspot.DefaultExports
88
import kotlinx.coroutines.launch
99
import kotlinx.coroutines.runBlocking
1010
import mu.KotlinLogging
11+
import no.nav.dagpenger.inntekt.Config.inntektApiConfig
1112
import no.nav.dagpenger.inntekt.db.PostgresInntektStore
1213
import no.nav.dagpenger.inntekt.db.dataSourceFrom
1314
import no.nav.dagpenger.inntekt.db.migrate
@@ -26,10 +27,11 @@ import java.util.concurrent.TimeUnit
2627
import kotlin.concurrent.fixedRateTimer
2728

2829
private val LOGGER = KotlinLogging.logger {}
29-
private val config = Configuration()
30+
private val configuration = Config.config
3031

3132
fun main() {
3233
runBlocking {
34+
val config = configuration.inntektApiConfig
3335
migrate(config)
3436
DefaultExports.initialize()
3537

@@ -94,6 +96,7 @@ fun main() {
9496
// Provides a HTTP API for getting inntekt
9597
embeddedServer(Netty, port = config.application.httpPort) {
9698
inntektApi(
99+
configuration,
97100
inntektskomponentHttpClient,
98101
postgresInntektStore,
99102
cachedInntektsGetter,
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package no.nav.dagpenger.inntekt
2+
3+
import com.auth0.jwk.JwkProvider
4+
import com.auth0.jwk.JwkProviderBuilder
5+
import com.natpryce.konfig.Configuration
6+
import com.natpryce.konfig.Key
7+
import com.natpryce.konfig.stringType
8+
import io.ktor.auth.jwt.JWTAuthenticationProvider
9+
import io.ktor.auth.jwt.JWTCredential
10+
import io.ktor.auth.jwt.JWTPrincipal
11+
import mu.KotlinLogging
12+
import java.net.URL
13+
import java.util.concurrent.TimeUnit
14+
15+
private val LOGGER = KotlinLogging.logger {}
16+
17+
internal fun JWTAuthenticationProvider.Configuration.azureAdJWT(config: Configuration) {
18+
val jwksUri = config[Key("AZURE_OPENID_CONFIG_JWKS_URI", stringType)]
19+
val issuer = config[Key("AZURE_OPENID_CONFIG_ISSUER", stringType)]
20+
val clientId = config[Key("AZURE_APP_CLIENT_ID", stringType)]
21+
this.realm = "dp-inntekt-api"
22+
23+
this.verifier(jwkProvider(jwksUri), issuer)
24+
validate { credentials: JWTCredential ->
25+
try {
26+
requireNotNull(credentials.payload.audience) {
27+
"Auth: Missing audience in token"
28+
}
29+
require(credentials.payload.audience.contains(clientId)) {
30+
"Auth: Valid audience not found in claims"
31+
}
32+
JWTPrincipal(credentials.payload)
33+
} catch (e: Throwable) {
34+
LOGGER.error("Unauthorized", e)
35+
null
36+
}
37+
}
38+
}
39+
40+
private fun jwkProvider(url: String): JwkProvider {
41+
return JwkProviderBuilder(URL(url))
42+
.cached(10, 24, TimeUnit.HOURS) // cache up to 10 JWKs for 24 hours
43+
.rateLimited(
44+
10,
45+
1,
46+
TimeUnit.MINUTES
47+
) // if not cached, only allow max 10 different keys per minute to be fetched from external provider
48+
.build()
49+
}

dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/Configuration.kt

Lines changed: 0 additions & 158 deletions
This file was deleted.

dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/InntektApi.kt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package no.nav.dagpenger.inntekt
22

33
import com.auth0.jwk.JwkProvider
4+
import com.natpryce.konfig.Configuration
45
import com.ryanharter.ktor.moshi.moshi
56
import com.squareup.moshi.JsonDataException
67
import com.squareup.moshi.JsonEncodingException
78
import io.ktor.application.Application
89
import io.ktor.application.call
910
import io.ktor.application.install
1011
import io.ktor.auth.Authentication
12+
import io.ktor.auth.authenticate
1113
import io.ktor.auth.jwt.JWTPrincipal
1214
import io.ktor.auth.jwt.jwt
1315
import io.ktor.features.CallId
@@ -30,6 +32,7 @@ import io.micrometer.prometheus.PrometheusConfig
3032
import io.micrometer.prometheus.PrometheusMeterRegistry
3133
import io.prometheus.client.CollectorRegistry
3234
import mu.KotlinLogging
35+
import no.nav.dagpenger.inntekt.Config.application
3336
import no.nav.dagpenger.inntekt.db.IllegalInntektIdException
3437
import no.nav.dagpenger.inntekt.db.InntektNotFoundException
3538
import no.nav.dagpenger.inntekt.db.InntektStore
@@ -51,9 +54,9 @@ import java.util.concurrent.atomic.AtomicLong
5154

5255
private val LOGGER = KotlinLogging.logger {}
5356
private val sikkerLogg = KotlinLogging.logger("tjenestekall")
54-
private val config = Configuration()
5557

5658
fun Application.inntektApi(
59+
config: Configuration = Config.config,
5760
inntektskomponentHttpClient: InntektskomponentClient,
5861
inntektStore: InntektStore,
5962
behandlingsInntektsGetter: BehandlingsInntektsGetter,
@@ -71,7 +74,7 @@ fun Application.inntektApi(
7174
}
7275

7376
install(Authentication) {
74-
apiKeyAuth {
77+
apiKeyAuth("apikey") {
7578
apiKeyName = "X-API-KEY"
7679
validate { apikeyCredential: ApiKeyCredential ->
7780
when {
@@ -96,6 +99,10 @@ fun Application.inntektApi(
9699
return@validate JWTPrincipal(credentials.payload)
97100
}
98101
}
102+
103+
jwt("azure") {
104+
azureAdJWT(config)
105+
}
99106
}
100107

101108
install(StatusPages) {
@@ -209,12 +216,21 @@ fun Application.inntektApi(
209216
routing {
210217
route("/v1") {
211218
route("/inntekt") {
212-
inntekt(behandlingsInntektsGetter)
219+
authenticate("apikey") {
220+
inntekt(behandlingsInntektsGetter)
221+
}
213222
uklassifisertInntekt(inntektskomponentHttpClient, inntektStore, personOppslag)
214223
}
215224
opptjeningsperiodeApi(inntektStore)
216225
enhetsregisteret(enhetsregisterClient)
217226
}
227+
route("v2") {
228+
route("/inntekt") {
229+
authenticate("azure") {
230+
inntekt(behandlingsInntektsGetter)
231+
}
232+
}
233+
}
218234
naischecks(healthChecks)
219235
}
220236
}

0 commit comments

Comments
 (0)