Best-effort serve for bad stored config + admin self-lockout guards
Serving never refuses to start because of stored realm config: the registry build sanitizes best-effort and warns — misfiled origin entries are reclassified (a cross-domain origins entry is served as a related origin) or dropped, collisions resolve first-come-wins, over-cap related lists truncate, unsalvageable realms are skipped. Fixing the stored config stays the admin interface's job, and it stays reachable on any working realm. Only a config with no servable realm at all is fatal. Admin realm writes stay strict and gain self-lockout guards: an update that would leave the admin's current host unable to run ceremonies for the realm they are on is refused (unless an auth host takes over ceremonies), and deleting the realm currently in use is refused.
This commit is contained in:
@@ -2048,6 +2048,69 @@ class TestRealms:
|
||||
r = await client.delete("/auth/api/admin/realms/example.com", headers=headers)
|
||||
assert r.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_realm_refuses_self_lockout(
|
||||
self, client: httpx.AsyncClient, session_token: str
|
||||
):
|
||||
"""An allow-list excluding the admin's current host is refused."""
|
||||
headers = {**auth_headers(session_token), "Host": "localhost:4401"}
|
||||
|
||||
# Allow-list without the current host and no auth host → lockout
|
||||
r = await client.patch(
|
||||
"/auth/api/admin/realms/localhost",
|
||||
json={
|
||||
"rp_name": "",
|
||||
"auth_host": "",
|
||||
"origins": ["https://auth.localhost"],
|
||||
},
|
||||
headers=headers,
|
||||
)
|
||||
assert r.status_code == 400
|
||||
assert "lock you out" in r.text
|
||||
|
||||
# Allow-list including the current host is fine
|
||||
r = await client.patch(
|
||||
"/auth/api/admin/realms/localhost",
|
||||
json={
|
||||
"rp_name": "",
|
||||
"auth_host": "",
|
||||
"origins": ["https://localhost:4401"],
|
||||
},
|
||||
headers=headers,
|
||||
)
|
||||
assert r.status_code == 200, r.text
|
||||
|
||||
# An allow-list without the current host is also fine when an auth
|
||||
# host is set: ceremonies move there (and it is always allowed).
|
||||
# Done last: with an auth host set, the API here routes differently.
|
||||
r = await client.patch(
|
||||
"/auth/api/admin/realms/localhost",
|
||||
json={
|
||||
"rp_name": "",
|
||||
"auth_host": "auth.localhost",
|
||||
"origins": ["https://auth.localhost"],
|
||||
},
|
||||
headers=headers,
|
||||
)
|
||||
assert r.status_code == 200, r.text
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_current_realm_refused(
|
||||
self, client: httpx.AsyncClient, session_token: str
|
||||
):
|
||||
headers = {**auth_headers(session_token), "Host": "localhost:4401"}
|
||||
r = await client.post(
|
||||
"/auth/api/admin/realms/", json={"rp_id": "example.com"}, headers=headers
|
||||
)
|
||||
assert r.status_code == 200
|
||||
# Deleting the realm in use is refused even if it has no credentials
|
||||
r = await client.delete("/auth/api/admin/realms/localhost", headers=headers)
|
||||
assert r.status_code == 400
|
||||
assert "currently using" in r.text
|
||||
# Deleting another realm while authenticated here is fine
|
||||
r = await client.delete("/auth/api/admin/realms/example.com", headers=headers)
|
||||
assert r.status_code == 200, r.text
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_effective_auth_host_fallback(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user