From 2edf0617c4b319585a1f68d1c635ed9b4245a22d Mon Sep 17 00:00:00 2001 From: dzikoysk Date: Mon, 29 Jan 2024 22:37:33 +0100 Subject: [PATCH] GH-2026 Display unauthorized host in authentication error log entry (Resolve #2026) --- .../reposilite/auth/AuthenticationFacade.kt | 2 +- .../com/reposilite/auth/api/Credentials.kt | 1 + .../infrastructure/ConsoleWebSocketHandler.kt | 19 +++++++++++++------ .../maven/RepositoryLoopbackClient.kt | 4 ++-- .../web/application/JavalinConfiguration.kt | 8 +++++--- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/reposilite-backend/src/main/kotlin/com/reposilite/auth/AuthenticationFacade.kt b/reposilite-backend/src/main/kotlin/com/reposilite/auth/AuthenticationFacade.kt index 4b4ec3e64..242460c4a 100644 --- a/reposilite-backend/src/main/kotlin/com/reposilite/auth/AuthenticationFacade.kt +++ b/reposilite-backend/src/main/kotlin/com/reposilite/auth/AuthenticationFacade.kt @@ -52,7 +52,7 @@ class AuthenticationFacade( .map { authenticator -> authenticator .authenticate(credentials) - .onError { logger.debug("${credentials.name} failed to authenticate with ${authenticator.realm()} realm due to $it") } + .onError { logger.debug("${credentials.name}@${credentials.host} failed to authenticate with ${authenticator.realm()} realm due to $it") } } .firstOrNull { it.isOk } ?.peek { authenticationCache.put(credentials, it) } diff --git a/reposilite-backend/src/main/kotlin/com/reposilite/auth/api/Credentials.kt b/reposilite-backend/src/main/kotlin/com/reposilite/auth/api/Credentials.kt index c55d15059..dd21bd618 100644 --- a/reposilite-backend/src/main/kotlin/com/reposilite/auth/api/Credentials.kt +++ b/reposilite-backend/src/main/kotlin/com/reposilite/auth/api/Credentials.kt @@ -17,6 +17,7 @@ package com.reposilite.auth.api data class Credentials( + val host: String, val name: String, val secret: String ) diff --git a/reposilite-backend/src/main/kotlin/com/reposilite/console/infrastructure/ConsoleWebSocketHandler.kt b/reposilite-backend/src/main/kotlin/com/reposilite/console/infrastructure/ConsoleWebSocketHandler.kt index 440887b48..07f2857db 100644 --- a/reposilite-backend/src/main/kotlin/com/reposilite/console/infrastructure/ConsoleWebSocketHandler.kt +++ b/reposilite-backend/src/main/kotlin/com/reposilite/console/infrastructure/ConsoleWebSocketHandler.kt @@ -106,19 +106,26 @@ internal class CliEndpoint( val authMessage = connection.message() if (!authMessage.startsWith(AUTHORIZATION_PREFIX)) { - return unauthorizedError("Unauthorized CLI access request from ${address(connection)} (missing credentials)") + return unauthorizedError("Unauthorized CLI access request from ${connection.getHost()} (missing credentials)") } return extractFromString(authMessage.replaceFirst(AUTHORIZATION_PREFIX, "")) - .flatMap { (name, secret) -> authenticationFacade.authenticateByCredentials(Credentials(name, secret)) } + .map { (name, secret) -> + Credentials( + host = connection.getHost(), + name = name, + secret = secret + ) + } + .flatMap { authenticationFacade.authenticateByCredentials(it) } .filter( { accessTokenFacade.hasPermission(it.identifier, MANAGER) }, - { unauthorized("Unauthorized CLI access request from ${address(connection)}") } + { unauthorized("Unauthorized CLI access request from ${connection.getHost()}") } ) - .map { "${it.name}@${address(connection)}" } + .map { "${it.name}@${connection.getHost()}" } } - private fun address(context: WsContext): String = - context.header(forwardedIp.get()) ?: context.session.remoteAddress.toString() + private fun WsContext.getHost(): String = + header(forwardedIp.get()) ?: session.remoteAddress.toString() } diff --git a/reposilite-backend/src/main/kotlin/com/reposilite/maven/RepositoryLoopbackClient.kt b/reposilite-backend/src/main/kotlin/com/reposilite/maven/RepositoryLoopbackClient.kt index 3675bc81d..affd04a0f 100644 --- a/reposilite-backend/src/main/kotlin/com/reposilite/maven/RepositoryLoopbackClient.kt +++ b/reposilite-backend/src/main/kotlin/com/reposilite/maven/RepositoryLoopbackClient.kt @@ -60,8 +60,8 @@ internal class RepositoryLoopbackClient( private fun RemoteCredentials?.toAccessToken(): AccessTokenIdentifier? = Option.of(this) .toResult(UNAUTHORIZED.toErrorResponse("Missing credentials")) - .filter({ it.method == LOOPBACK_LINK }, { UNAUTHORIZED.toErrorResponse("") }) - .flatMap { authenticationFacade.authenticateByCredentials(Credentials(it.login, it.password)) } + .filter({ it.method == LOOPBACK_LINK }, { UNAUTHORIZED.toErrorResponse() }) + .flatMap { authenticationFacade.authenticateByCredentials(Credentials(host = "loopback", name = it.login, secret = it.password)) } .fold( { it.identifier }, { null } diff --git a/reposilite-backend/src/main/kotlin/com/reposilite/web/application/JavalinConfiguration.kt b/reposilite-backend/src/main/kotlin/com/reposilite/web/application/JavalinConfiguration.kt index d8fdc8412..9b58ed48c 100644 --- a/reposilite-backend/src/main/kotlin/com/reposilite/web/application/JavalinConfiguration.kt +++ b/reposilite-backend/src/main/kotlin/com/reposilite/web/application/JavalinConfiguration.kt @@ -47,12 +47,14 @@ import io.javalin.http.Context import io.javalin.http.ExceptionHandler import io.javalin.http.Handler import io.javalin.http.Header +import io.javalin.http.Header.AUTHORIZATION import io.javalin.http.HttpStatus import io.javalin.json.JavalinJackson import io.javalin.openapi.plugin.OpenApiPlugin import io.javalin.openapi.plugin.OpenApiPluginConfiguration import io.javalin.plugin.bundled.SslRedirectPlugin import io.javalin.util.ConcurrencyUtil +import io.javalin.util.javalinLazy import kotlin.time.Duration.Companion.minutes import org.eclipse.jetty.server.Server import org.eclipse.jetty.server.ServerConnector @@ -140,9 +142,9 @@ internal object JavalinConfiguration { logger = reposilite.logger, ctx = this, accessTokenFacade = accessTokenFacade, - authenticationResult = lazy { - extractFromHeader(header(Header.AUTHORIZATION)) - .map { (name, secret) -> Credentials(name, secret) } + authenticationResult = javalinLazy { + extractFromHeader(header(AUTHORIZATION)) + .map { (name, secret) -> Credentials(host = host() ?: req().remoteAddr, name = name, secret = secret) } .flatMap { authenticationFacade.authenticateByCredentials(it) } } )