fix: verify dashboard sessions via config API
This commit is contained in:
+15
-14
@@ -29,24 +29,25 @@ class GatewayHttpProbe(
|
|||||||
bearerToken: String,
|
bearerToken: String,
|
||||||
sessionCookie: String
|
sessionCookie: String
|
||||||
): GatewayProbeResult {
|
): GatewayProbeResult {
|
||||||
// Hermes dashboard auth gates every protected route, including /health.
|
// Hermes Dashboard and Hermes API Server are distinct upstream surfaces.
|
||||||
// A successful password login therefore must send its session cookie to
|
// Dashboard /health and /v1/models can legitimately serve the SPA shell,
|
||||||
// the health probe as well as /v1/models; otherwise the 302-to-login
|
// so they are not a valid dashboard authentication probe. A password
|
||||||
// response is incorrectly presented as a generic offline failure.
|
// session is verified against the documented JSON dashboard config route.
|
||||||
val healthCookie = if (authMode == ConnectionAuthMode.PasswordLogin) sessionCookie else ""
|
if (authMode == ConnectionAuthMode.PasswordLogin) {
|
||||||
val health = getJson("$baseUrl/health", sessionCookie = healthCookie)
|
return when (val dashboard = getJson("$baseUrl/api/config", sessionCookie = sessionCookie)) {
|
||||||
|
HttpProbeResult.Success -> GatewayProbeResult.Healthy("Dashboard session authentication passed.")
|
||||||
|
else -> dashboard.toGatewayResult("Dashboard session check")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val health = getJson("$baseUrl/health")
|
||||||
if (health != HttpProbeResult.Success) return health.toGatewayResult("Health probe")
|
if (health != HttpProbeResult.Success) return health.toGatewayResult("Health probe")
|
||||||
if (authMode == ConnectionAuthMode.None) {
|
if (authMode == ConnectionAuthMode.None) {
|
||||||
return GatewayProbeResult.Healthy("Gateway health check passed.")
|
return GatewayProbeResult.Healthy("Gateway health check passed.")
|
||||||
}
|
}
|
||||||
val compatibility = when (authMode) {
|
return when (val models = getJson("$baseUrl/v1/models", bearerToken = bearerToken)) {
|
||||||
ConnectionAuthMode.None -> error("Anonymous probes return after the health check.")
|
HttpProbeResult.Success -> GatewayProbeResult.Healthy("Gateway health and bearer authentication checks passed.")
|
||||||
ConnectionAuthMode.BearerToken -> getJson("$baseUrl/v1/models", bearerToken = bearerToken)
|
else -> models.toGatewayResult("Authenticated API check")
|
||||||
ConnectionAuthMode.PasswordLogin -> getJson("$baseUrl/v1/models", sessionCookie = sessionCookie)
|
|
||||||
}
|
|
||||||
return when (compatibility) {
|
|
||||||
HttpProbeResult.Success -> GatewayProbeResult.Healthy("Gateway health and authentication checks passed.")
|
|
||||||
else -> compatibility.toGatewayResult("Authenticated compatibility check")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-5
@@ -56,7 +56,7 @@ class GatewayHttpProbeTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun passwordSessionProbeUsesCookieOnlyForAuthenticatedCompatibilityCheck() = runBlocking {
|
fun passwordSessionProbeUsesCookieOnlyForDashboardConfigCheck() = runBlocking {
|
||||||
val requests = mutableListOf<Triple<String, String?, String?>>()
|
val requests = mutableListOf<Triple<String, String?, String?>>()
|
||||||
val probe = GatewayHttpProbe(client { chain ->
|
val probe = GatewayHttpProbe(client { chain ->
|
||||||
requests += Triple(
|
requests += Triple(
|
||||||
@@ -71,10 +71,7 @@ class GatewayHttpProbeTest {
|
|||||||
|
|
||||||
assertTrue(result is GatewayProbeResult.Healthy)
|
assertTrue(result is GatewayProbeResult.Healthy)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
listOf(
|
listOf(Triple("/api/config", null, SESSION_COOKIE)),
|
||||||
Triple("/health", null, SESSION_COOKIE),
|
|
||||||
Triple("/v1/models", null, SESSION_COOKIE)
|
|
||||||
),
|
|
||||||
requests
|
requests
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user