Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kotoutumiskoulutus): add audit logging #593

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,45 @@
package fi.oph.kitu.kotoutumiskoulutus

import com.fasterxml.jackson.databind.ObjectMapper
import fi.oph.kitu.AUDIT_LOGGER_NAME
import fi.oph.kitu.logging.add
import fi.oph.kitu.logging.tryAddUser
import org.slf4j.LoggerFactory
import org.springframework.data.relational.core.mapping.event.AfterDeleteCallback
import org.springframework.data.relational.core.mapping.event.AfterSaveCallback
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Component
import org.springframework.stereotype.Repository

@Repository
interface KielitestiSuoritusRepository : CrudRepository<KielitestiSuoritus, Int>

@Component
class AuditLoggerEntityListener(
private val jacksonObjectMapper: ObjectMapper,
) : AfterSaveCallback<KielitestiSuoritus>,
AfterDeleteCallback<KielitestiSuoritus> {
private val auditLogger = LoggerFactory.getLogger(AUDIT_LOGGER_NAME)

override fun onAfterSave(aggregate: KielitestiSuoritus): KielitestiSuoritus {
auditLogger
.atInfo()
.tryAddUser()
.add(
"entity" to jacksonObjectMapper.writeValueAsString(aggregate),
"operation" to "save",
).log("Saved kielitesti suoritus")
return aggregate
}

override fun onAfterDelete(aggregate: KielitestiSuoritus): KielitestiSuoritus {
auditLogger
.atInfo()
.tryAddUser()
.add(
"entity" to jacksonObjectMapper.writeValueAsString(aggregate),
"operation" to "delete",
).log("Deleted kielitesti suoritus")
return aggregate
}
}
11 changes: 11 additions & 0 deletions server/src/main/kotlin/fi/oph/kitu/logging/LoggerExtensions.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fi.oph.kitu.logging

import fi.oph.kitu.PeerService
import fi.oph.kitu.auth.CasUserDetails
import io.opentelemetry.semconv.HttpAttributes
import io.opentelemetry.semconv.UrlAttributes
import io.opentelemetry.semconv.UserAgentAttributes
Expand All @@ -11,6 +12,7 @@ import org.slf4j.spi.LoggingEventBuilder
import org.springframework.dao.DuplicateKeyException
import org.springframework.http.HttpHeaders
import org.springframework.http.ResponseEntity
import org.springframework.security.core.context.SecurityContextHolder
import java.net.http.HttpResponse

fun LoggingEventBuilder.addServletRequest(request: HttpServletRequest): LoggingEventBuilder =
Expand Down Expand Up @@ -120,3 +122,12 @@ fun <T> LoggingEventBuilder.withEvent(
log()
}
}

fun LoggingEventBuilder.tryAddUser(): LoggingEventBuilder {
val userDetails = SecurityContextHolder.getContext().authentication?.principal as? CasUserDetails
if (userDetails == null) {
return this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vai olisko parempi lokittaa "user": null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tää on ihan hyvä kysymys. OpenTelemetry ei tue null-arvoja attribuuteille, se oli ehkä mielessä tässä, vaikka ei sitä käytetäkään (vielä).

}
add("user" to userDetails)
return this
}
1 change: 1 addition & 0 deletions server/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ kitu.yki.password=${YKI_API_PASSWORD}
spring.mustache.suffix=.mustache

logging.structured.format.console=ecs
logging.structured.format.file=ecs

# Uncomment this to debug authentication/authorization issues.
# Ref: https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-logging
Expand Down
5 changes: 3 additions & 2 deletions server/src/main/resources/logback-spring.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

<appender name="AUDIT_LOCAL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/audit.log</file>
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<encoder class="org.springframework.boot.logging.logback.StructuredLogEncoder">
<format>${FILE_LOG_STRUCTURED_FORMAT}</format>
<charset>${FILE_LOG_CHARSET}</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/audit.%d{yyyy-MM-dd}.log</fileNamePattern>
Expand Down
1 change: 1 addition & 0 deletions server/src/test/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ kitu.yki.username=
kitu.yki.password=

logging.structured.format.console=ecs
logging.structured.format.file=ecs
Loading