-
Notifications
You must be signed in to change notification settings - Fork 2
/
AuditLogger.kt
100 lines (85 loc) · 3.73 KB
/
AuditLogger.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package no.nav.familie.ef.sak
import no.nav.familie.ef.sak.felles.integration.dto.Tilgang
import no.nav.familie.ef.sak.infrastruktur.sikkerhet.SikkerhetContext
import no.nav.familie.log.mdc.MDCConstants
import org.slf4j.LoggerFactory
import org.slf4j.MDC
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes
import javax.servlet.http.HttpServletRequest
/**
* [custom1], [custom2], [custom3] brukes for å logge ekstra felter, eks fagsak, behandling,
* disse logges til cs3,cs5,cs6 då cs1,cs2 og cs4 er til internt bruk
* Kan brukes med eks CustomKeyValue(key=fagsak, value=fagsakId)
*/
data class Sporingsdata(
val event: AuditLoggerEvent,
val personIdent: String,
val tilgang: Tilgang,
val custom1: CustomKeyValue? = null,
val custom2: CustomKeyValue? = null,
val custom3: CustomKeyValue? = null,
)
enum class AuditLoggerEvent(val type: String) {
CREATE("create"),
UPDATE("update"),
DELETE("delete"),
ACCESS("access"),
}
data class CustomKeyValue(val key: String, val value: String)
@Component
class AuditLogger(@Value("\${NAIS_APP_NAME}") private val applicationName: String) {
private val logger = LoggerFactory.getLogger(javaClass)
private val audit = LoggerFactory.getLogger("auditLogger")
private val regexFlereSpaces = "\\s+".toRegex()
fun log(data: Sporingsdata) {
val request = getRequest() ?: throw IllegalArgumentException("Ikke brukt i context av en HTTP request")
if (!SikkerhetContext.erMaskinTilMaskinToken()) {
audit.info(createAuditLogString(data, request))
} else {
logger.debug("Maskin til maskin token i request")
}
}
private fun getRequest(): HttpServletRequest? {
return RequestContextHolder.getRequestAttributes()
?.takeIf { it is ServletRequestAttributes }
?.let { it as ServletRequestAttributes }
?.request
}
private fun createAuditLogString(data: Sporingsdata, request: HttpServletRequest): String {
val timestamp = System.currentTimeMillis()
val name = "Saksbehandling"
return "CEF:0|$applicationName|auditLog|1.0|audit:${data.event.type}|$name|INFO|end=$timestamp " +
"suid=${SikkerhetContext.hentSaksbehandler()} " +
"duid=${data.personIdent} " +
"sproc=${getCallId()} " +
"requestMethod=${request.method} " +
"request=${request.requestURI} " +
"flexString1Label=Decision flexString1=${formatHarTilgang(data.tilgang)} " +
formatDenyPolicy(data.tilgang) +
createCustomString(data)
}
private fun formatHarTilgang(tilgang: Tilgang): String = if (tilgang.harTilgang) "Permit" else "Deny"
private fun formatDenyPolicy(tilgang: Tilgang): String {
val begrunnelse = tilgang.begrunnelse
return if (!tilgang.harTilgang && begrunnelse != null) {
val denyPolicy = begrunnelse.replace(regexFlereSpaces, " ").split(" ").joinToString("_")
"flexString2Label=deny_policy flexString2=$denyPolicy "
} else {
""
}
}
private fun createCustomString(data: Sporingsdata): String {
return listOfNotNull(
data.custom1?.let { "cs3Label=${it.key} cs3=${it.value}" },
data.custom2?.let { "cs5Label=${it.key} cs5=${it.value}" },
data.custom3?.let { "cs6Label=${it.key} cs6=${it.value}" },
)
.joinToString(" ")
}
private fun getCallId(): String {
return MDC.get(MDCConstants.MDC_CALL_ID) ?: throw IllegalStateException("Mangler callId")
}
}