Files

160 lines
5.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import argparse
import os
import sys
from typing import Iterable, Set
import httpx
def _check_status(
response: httpx.Response,
expected: Iterable[int],
success_message: str,
fail_message: str,
failures: list[str],
) -> bool:
expected_set: Set[int] = set(expected)
if response.status_code in expected_set:
print(f"[PASS] {success_message} (status={response.status_code})")
return True
print(f"[FAIL] {fail_message} (status={response.status_code}, body={response.text})")
failures.append(fail_message)
return False
def main() -> int:
parser = argparse.ArgumentParser(description="Auth and permission smoke checks for InSAR backend.")
parser.add_argument("--base-url", default=os.getenv("AUTH_SMOKE_BASE_URL", "http://127.0.0.1:8000"))
parser.add_argument("--admin-user", default=os.getenv("INIT_ADMIN_USERNAME", "admin"))
parser.add_argument("--admin-password", default=os.getenv("INIT_ADMIN_PASSWORD", "ChangeMe123!"))
parser.add_argument("--viewer-user", default=os.getenv("AUTH_SMOKE_VIEWER_USERNAME", ""))
parser.add_argument("--viewer-password", default=os.getenv("AUTH_SMOKE_VIEWER_PASSWORD", ""))
args = parser.parse_args()
failures: list[str] = []
timeout = httpx.Timeout(10.0)
try:
with httpx.Client(base_url=args.base_url.rstrip("/"), timeout=timeout) as client:
print(f"[*] Target: {args.base_url.rstrip('/')}")
unauth_me = client.get("/api/auth/me")
_check_status(
unauth_me,
{401},
"未登录访问 /api/auth/me 返回 401",
"未登录访问 /api/auth/me 未返回 401",
failures,
)
login_admin = client.post(
"/api/auth/login",
json={"username": args.admin_user, "password": args.admin_password},
)
if not _check_status(
login_admin,
{200},
"管理员登录成功",
"管理员登录失败",
failures,
):
print("[INFO] 管理员登录失败,后续检查跳过。")
return 1
me_admin = client.get("/api/auth/me")
if _check_status(
me_admin,
{200},
"管理员会话可访问 /api/auth/me",
"管理员会话无法访问 /api/auth/me",
failures,
):
role = (me_admin.json() or {}).get("role")
if role != "admin":
print(f"[FAIL] 管理员角色异常,实际 role={role}")
failures.append("管理员角色异常")
else:
print("[PASS] 管理员角色校验通过")
audit_logs = client.get("/api/auth/audit-logs", params={"limit": 20})
if _check_status(
audit_logs,
{200},
"管理员可查询审计日志 /api/auth/audit-logs",
"管理员无法查询审计日志 /api/auth/audit-logs",
failures,
):
payload = audit_logs.json()
if isinstance(payload, list):
print(f"[PASS] 审计日志接口返回列表(条数={len(payload)}")
else:
print("[FAIL] 审计日志接口返回格式不是列表")
failures.append("审计日志接口返回格式异常")
run_now_admin = client.post("/api/monitor/run-now")
_check_status(
run_now_admin,
{200, 202, 400, 409},
"管理员可触发写操作接口(未被鉴权拒绝)",
"管理员触发写操作接口异常(可能被鉴权拒绝)",
failures,
)
client.post("/api/auth/logout")
if args.viewer_user and args.viewer_password:
login_viewer = client.post(
"/api/auth/login",
json={"username": args.viewer_user, "password": args.viewer_password},
)
if _check_status(
login_viewer,
{200},
"只读用户登录成功",
"只读用户登录失败",
failures,
):
me_viewer = client.get("/api/auth/me")
if _check_status(
me_viewer,
{200},
"只读用户会话可访问 /api/auth/me",
"只读用户会话无法访问 /api/auth/me",
failures,
):
role = (me_viewer.json() or {}).get("role")
if role != "viewer":
print(f"[FAIL] 只读用户角色异常,实际 role={role}")
failures.append("只读用户角色异常")
else:
print("[PASS] 只读用户角色校验通过")
run_now_viewer = client.post("/api/monitor/run-now")
_check_status(
run_now_viewer,
{403},
"只读用户写操作被拒绝(403",
"只读用户写操作未被拒绝",
failures,
)
client.post("/api/auth/logout")
else:
print("[INFO] 未提供只读用户凭据,跳过 viewer 鉴权回归。")
except httpx.RequestError as exc:
print(f"[FAIL] 无法连接后端: {exc}")
return 1
if failures:
print("\n[RESULT] 鉴权冒烟检查失败。")
for item in failures:
print(f"- {item}")
return 1
print("\n[RESULT] 鉴权冒烟检查通过。")
return 0
if __name__ == "__main__":
sys.exit(main())