fix(auth): change InternalAuthFilter to use @Singleton and add HTTP tests for secret validation
Build & Test (NowChessSystems) TeamCity build failed
Build & Test (NowChessSystems) TeamCity build failed
This commit is contained in:
+5
-2
@@ -186,8 +186,11 @@ class InstanceHeartbeatService:
|
|||||||
)
|
)
|
||||||
|
|
||||||
val json = mapper.writeValueAsString(metadata)
|
val json = mapper.writeValueAsString(metadata)
|
||||||
reactiveRedis.value(classOf[String]).setex(key, 5L, json)
|
reactiveRedis
|
||||||
.subscribe().`with`(
|
.value(classOf[String])
|
||||||
|
.setex(key, 5L, json)
|
||||||
|
.subscribe()
|
||||||
|
.`with`(
|
||||||
_ => (),
|
_ => (),
|
||||||
(ex: Throwable) => log.warnf(ex, "Failed to refresh Redis heartbeat"),
|
(ex: Throwable) => log.warnf(ex, "Failed to refresh Redis heartbeat"),
|
||||||
)
|
)
|
||||||
|
|||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
package de.nowchess.chess.resource
|
||||||
|
|
||||||
|
import de.nowchess.chess.grpc.{IoGrpcClientWrapper, RuleSetGrpcAdapter}
|
||||||
|
import de.nowchess.chess.redis.GameRedisSubscriberManager
|
||||||
|
import io.quarkus.test.InjectMock
|
||||||
|
import io.quarkus.test.junit.{QuarkusTest, TestProfile}
|
||||||
|
import io.quarkus.test.junit.QuarkusTestProfile
|
||||||
|
import io.restassured.RestAssured
|
||||||
|
import jakarta.ws.rs.core.MediaType
|
||||||
|
import org.junit.jupiter.api.{DisplayName, Test}
|
||||||
|
|
||||||
|
import java.util.Map as JMap
|
||||||
|
|
||||||
|
// scalafix:off
|
||||||
|
class InternalAuthEnabledProfile extends QuarkusTestProfile:
|
||||||
|
override def getConfigOverrides(): JMap[String, String] =
|
||||||
|
JMap.of(
|
||||||
|
"nowchess.internal.auth.enabled", "true",
|
||||||
|
"nowchess.internal.secret", "test-secret-123",
|
||||||
|
)
|
||||||
|
|
||||||
|
@QuarkusTest
|
||||||
|
@TestProfile(classOf[InternalAuthEnabledProfile])
|
||||||
|
@DisplayName("InternalAuthFilter HTTP")
|
||||||
|
class InternalAuthFilterHttpTest:
|
||||||
|
|
||||||
|
@InjectMock
|
||||||
|
var ioWrapper: IoGrpcClientWrapper = scala.compiletime.uninitialized
|
||||||
|
|
||||||
|
@InjectMock
|
||||||
|
var ruleAdapter: RuleSetGrpcAdapter = scala.compiletime.uninitialized
|
||||||
|
|
||||||
|
@InjectMock
|
||||||
|
var subscriberManager: GameRedisSubscriberManager = scala.compiletime.uninitialized
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /api/board/game without secret returns 401")
|
||||||
|
def rejectNoSecret(): Unit =
|
||||||
|
RestAssured.`given`()
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body("{}")
|
||||||
|
.when()
|
||||||
|
.post("/api/board/game")
|
||||||
|
.then()
|
||||||
|
.statusCode(401)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /api/board/game with wrong secret returns 401")
|
||||||
|
def rejectWrongSecret(): Unit =
|
||||||
|
RestAssured.`given`()
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.header("X-Internal-Secret", "wrong-secret")
|
||||||
|
.body("{}")
|
||||||
|
.when()
|
||||||
|
.post("/api/board/game")
|
||||||
|
.then()
|
||||||
|
.statusCode(401)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /api/board/game/{id} without secret returns 404 not 401")
|
||||||
|
def nonInternalEndpointNotBlocked(): Unit =
|
||||||
|
RestAssured.`given`()
|
||||||
|
.when()
|
||||||
|
.get("/api/board/game/nonexistent")
|
||||||
|
.then()
|
||||||
|
.statusCode(404)
|
||||||
|
// scalafix:on
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package de.nowchess.security
|
package de.nowchess.security
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
import jakarta.inject.Singleton
|
||||||
import jakarta.ws.rs.container.{ContainerRequestContext, ContainerRequestFilter}
|
import jakarta.ws.rs.container.{ContainerRequestContext, ContainerRequestFilter}
|
||||||
import jakarta.ws.rs.core.Response
|
import jakarta.ws.rs.core.Response
|
||||||
import jakarta.ws.rs.ext.Provider
|
import jakarta.ws.rs.ext.Provider
|
||||||
@@ -9,7 +9,7 @@ import scala.compiletime.uninitialized
|
|||||||
|
|
||||||
@Provider
|
@Provider
|
||||||
@InternalOnly
|
@InternalOnly
|
||||||
@ApplicationScoped
|
@Singleton
|
||||||
class InternalAuthFilter extends ContainerRequestFilter:
|
class InternalAuthFilter extends ContainerRequestFilter:
|
||||||
|
|
||||||
@ConfigProperty(name = "nowchess.internal.secret", defaultValue = "")
|
@ConfigProperty(name = "nowchess.internal.secret", defaultValue = "")
|
||||||
|
|||||||
Reference in New Issue
Block a user