test_setup_info.py
1 """Tests for /setup (public) and /info (authenticated) response shapes. 2 3 In particular: the admin-only `auth_secret_weak` security flag must 4 NOT leak via the public /setup endpoint — that would let an 5 unauthenticated attacker probe for weak-secret misconfigurations. 6 """ 7 from __future__ import annotations 8 9 import pytest 10 from fastapi.testclient import TestClient 11 12 from restai.config import RESTAI_DEFAULT_PASSWORD 13 from restai.main import app 14 15 16 ADMIN = ("admin", RESTAI_DEFAULT_PASSWORD) 17 18 19 @pytest.fixture(scope="module") 20 def client(): 21 with TestClient(app) as c: 22 yield c 23 24 25 def test_setup_is_public_and_omits_security_flags(client): 26 r = client.get("/setup") 27 assert r.status_code == 200 28 body = r.json() 29 # Must NOT carry the admin-only weak-secret signal. 30 assert "auth_secret_weak" not in body, ( 31 "auth_secret_weak leaked via unauthenticated /setup" 32 ) 33 # Sanity: the pre-login UI knobs are still here. 34 for k in ("app_name", "sso", "sso_provider_names", "mcp"): 35 assert k in body, f"expected {k} in /setup response" 36 37 38 def test_info_requires_auth(client): 39 r = client.get("/info") 40 assert r.status_code == 401 41 42 43 def test_info_exposes_auth_secret_weak_to_admin(client): 44 r = client.get("/info", auth=ADMIN) 45 assert r.status_code == 200 46 body = r.json() 47 # Field is always present for authenticated callers; value is 48 # environment-dependent. 49 assert "auth_secret_weak" in body 50 assert isinstance(body["auth_secret_weak"], bool) 51 52 53 def test_info_hides_auth_secret_weak_from_non_admin(client): 54 """Non-admin users get False regardless of actual state — the 55 signal is reconnaissance-relevant even for low-trust users.""" 56 import random 57 username = f"info_viewer_{random.randint(0, 999999)}" 58 client.post("/users", json={"username": username, "password": "x"}, auth=ADMIN) 59 try: 60 r = client.get("/info", auth=(username, "x")) 61 assert r.status_code == 200 62 body = r.json() 63 assert body.get("auth_secret_weak") is False 64 finally: 65 client.delete(f"/users/{username}", auth=ADMIN)