diff --git a/backend/app/core/auth.py b/backend/app/core/auth.py index 941070a..c59caff 100644 --- a/backend/app/core/auth.py +++ b/backend/app/core/auth.py @@ -64,11 +64,11 @@ async def exchange_code_for_user(code: str) -> Optional[dict]: "code": code, } - async with httpx.AsyncClient(timeout=15, verify=False) as client: + async with httpx.AsyncClient(timeout=15) as client: try: resp = await client.post(token_url, data=data) if resp.status_code != 200: - logger.error(f"Casdoor token 换取失败: {resp.status_code} {resp.text}") + logger.error("Casdoor token 换取失败: status=%s", resp.status_code) return None token_data = resp.json() @@ -77,19 +77,16 @@ async def exchange_code_for_user(code: str) -> Optional[dict]: logger.error("Casdoor 返回中没有 id_token") return None - # 解码 id_token (JWT) payload,不验证签名(HTTPS 已保证传输安全) - # 生产环境建议验证 Casdoor 证书 cert = _load_casdoor_certificate() - try: - payload = jwt.decode( - id_token, - key=cert or None, - options={"verify_signature": bool(cert)}, - audience=settings.CASDOOR_CLIENT_ID, - ) - except JWTError: - # 不验证签名的方式解码 - payload = jwt.get_unverified_claims(id_token) + if not cert: + logger.error("Casdoor token 验证证书未配置") + return None + + payload = jwt.decode( + id_token, + key=cert, + audience=settings.CASDOOR_CLIENT_ID, + ) return payload diff --git a/backend/tests/test_deployment_security.py b/backend/tests/test_deployment_security.py new file mode 100644 index 0000000..17ce8d8 --- /dev/null +++ b/backend/tests/test_deployment_security.py @@ -0,0 +1,18 @@ +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] + + +def test_compose_does_not_embed_password_or_net_admin_capability(): + compose = (ROOT / "docker-compose.yml").read_text(encoding="utf-8") + + assert "POSTGRES_PASSWORD=pingwatch123" not in compose + assert "NET_ADMIN" not in compose + assert "127.0.0.1:8001:8000" in compose + + +def test_oauth_client_does_not_disable_tls_verification(): + auth_source = (ROOT / "backend" / "app" / "core" / "auth.py").read_text(encoding="utf-8") + + assert "verify=False" not in auth_source diff --git a/docker-compose.yml b/docker-compose.yml index fc72bde..901f050 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,10 +6,9 @@ services: env_file: - ./backend/.env environment: - - DATABASE_URL=postgresql+asyncpg://pingwatch:pingwatch123@db:5432/pingwatch - TZ=Asia/Shanghai ports: - - "8001:8000" + - "127.0.0.1:8001:8000" depends_on: db: condition: service_healthy @@ -18,8 +17,7 @@ services: networks: - pingwatch-net cap_add: - - NET_RAW # 允许 ICMP ping - - NET_ADMIN # 允许原始套接字 + - NET_RAW frontend: build: ./frontend @@ -40,9 +38,9 @@ services: restart: unless-stopped environment: - TZ=Asia/Shanghai - - POSTGRES_DB=pingwatch - - POSTGRES_USER=pingwatch - - POSTGRES_PASSWORD=pingwatch123 + - POSTGRES_DB=${POSTGRES_DB:-pingwatch} + - POSTGRES_USER=${POSTGRES_USER:-pingwatch} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in backend/.env} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: