chore: import upstream snapshot with attribution
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
"""Auth utilities for HTTP servers.
|
||||
|
||||
This module is intentionally lightweight (no torch import) so it can be used in unit tests.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import secrets
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AuthDecision:
|
||||
allowed: bool
|
||||
error_status_code: int = 401 # Only meaningful when allowed=False
|
||||
|
||||
|
||||
class AuthLevel(str, Enum):
|
||||
"""Per-endpoint auth level (attached to endpoint function via `@auth_level`)."""
|
||||
|
||||
NORMAL = "normal"
|
||||
ADMIN_OPTIONAL = "admin_optional"
|
||||
ADMIN_FORCE = "admin_force"
|
||||
|
||||
|
||||
def auth_level(level: AuthLevel):
|
||||
"""Mark endpoint with auth level (stored in endpoint metadata)."""
|
||||
|
||||
def decorator(func):
|
||||
func._auth_level = level
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def _get_auth_level_from_app_and_scope(app: Any, scope: dict) -> AuthLevel:
|
||||
"""Best-effort resolve auth level by matching the request to a route."""
|
||||
# Import lazily to keep this module unit-test friendly (FastAPI/Starlette are not
|
||||
# required unless you actually use the middleware / route matching).
|
||||
from starlette.routing import Match
|
||||
|
||||
# Prefer app.router.routes when available; fall back to app.routes.
|
||||
routes = getattr(getattr(app, "router", None), "routes", None) or getattr(
|
||||
app, "routes", []
|
||||
)
|
||||
|
||||
for route in routes:
|
||||
try:
|
||||
match, child_scope = route.matches(scope)
|
||||
except Exception:
|
||||
continue
|
||||
if match == Match.FULL:
|
||||
endpoint = child_scope.get("endpoint") or getattr(route, "endpoint", None)
|
||||
level = getattr(endpoint, "_auth_level", None)
|
||||
return level if isinstance(level, AuthLevel) else AuthLevel.NORMAL
|
||||
|
||||
return AuthLevel.NORMAL
|
||||
|
||||
|
||||
def app_has_admin_force_endpoints(app: Any) -> bool:
|
||||
"""Return True if any route endpoint is marked as ADMIN_FORCE."""
|
||||
routes = getattr(getattr(app, "router", None), "routes", None) or getattr(
|
||||
app, "routes", []
|
||||
)
|
||||
for route in routes:
|
||||
endpoint = getattr(route, "endpoint", None)
|
||||
if getattr(endpoint, "_auth_level", None) == AuthLevel.ADMIN_FORCE:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def decide_request_auth(
|
||||
*,
|
||||
method: str,
|
||||
path: str,
|
||||
authorization_header: Optional[str],
|
||||
api_key: Optional[str],
|
||||
admin_api_key: Optional[str],
|
||||
auth_level: AuthLevel,
|
||||
) -> AuthDecision:
|
||||
"""Pure auth decision function (easy to unit test).
|
||||
|
||||
Auth levels:
|
||||
- NORMAL: legacy behavior (api_key protects all endpoints when configured)
|
||||
- ADMIN_OPTIONAL: can be accessed without any key (if no keys configured),
|
||||
or with api_key/admin_api_key depending on server config.
|
||||
- ADMIN_FORCE: requires admin_api_key; if admin_api_key is NOT configured,
|
||||
it must be rejected (403) even if api_key is provided.
|
||||
|
||||
NOTE :
|
||||
- Health/metrics endpoints are always allowed (even when api_key/admin_api_key is set),
|
||||
to support k8s/liveness/readiness and Prometheus scraping without embedding secrets.
|
||||
- We match them by prefix to cover common variants like /health_generate.
|
||||
"""
|
||||
if method == "OPTIONS":
|
||||
return AuthDecision(allowed=True)
|
||||
|
||||
if path.startswith("/health") or path.startswith("/metrics"):
|
||||
return AuthDecision(allowed=True)
|
||||
|
||||
def _check_bearer_token(
|
||||
authorization_header: Optional[str], expected_token: str
|
||||
) -> bool:
|
||||
"""Check bearer token with constant-time comparison."""
|
||||
if not authorization_header:
|
||||
return False
|
||||
parts = authorization_header.split(" ", 1)
|
||||
if len(parts) != 2 or parts[0].lower() != "bearer":
|
||||
return False
|
||||
return secrets.compare_digest(parts[1], expected_token)
|
||||
|
||||
# Force-auth endpoints: only admin_api_key can unlock them; if admin_api_key is unset,
|
||||
# reject them unconditionally (explicitly "not allowed").
|
||||
if auth_level == AuthLevel.ADMIN_FORCE:
|
||||
if not admin_api_key:
|
||||
return AuthDecision(allowed=False, error_status_code=403)
|
||||
if not _check_bearer_token(authorization_header, admin_api_key):
|
||||
return AuthDecision(allowed=False)
|
||||
return AuthDecision(allowed=True)
|
||||
|
||||
# Optional-auth endpoints:
|
||||
# - no keys configured: allow
|
||||
# - only api_key: require api_key
|
||||
# - only admin_api_key: require admin_api_key
|
||||
# - both: require admin_api_key (api_key is NOT accepted)
|
||||
if auth_level == AuthLevel.ADMIN_OPTIONAL:
|
||||
if admin_api_key:
|
||||
return AuthDecision(
|
||||
allowed=_check_bearer_token(authorization_header, admin_api_key)
|
||||
)
|
||||
elif api_key:
|
||||
return AuthDecision(
|
||||
allowed=_check_bearer_token(authorization_header, api_key)
|
||||
)
|
||||
else:
|
||||
return AuthDecision(allowed=True)
|
||||
|
||||
# Normal endpoints:
|
||||
# - if api_key is configured, require api_key (even if admin_api_key is also configured)
|
||||
# - otherwise allow (including the "admin_api_key only" case)
|
||||
if api_key:
|
||||
return AuthDecision(allowed=_check_bearer_token(authorization_header, api_key))
|
||||
|
||||
return AuthDecision(allowed=True)
|
||||
|
||||
|
||||
def add_api_key_middleware(
|
||||
app,
|
||||
*,
|
||||
api_key: Optional[str],
|
||||
admin_api_key: Optional[str],
|
||||
):
|
||||
"""Add middleware for three endpoint auth levels: normal/admin_optional/admin_force."""
|
||||
# Import lazily so `decide_request_auth()` can be unit-tested without FastAPI installed.
|
||||
from fastapi.responses import ORJSONResponse
|
||||
from starlette.requests import Request
|
||||
|
||||
class _ApiKeyASGIMiddleware:
|
||||
"""ASGI-native middleware to preserve client disconnect events."""
|
||||
|
||||
def __init__(self, app, *, api_key, admin_api_key, fastapi_app):
|
||||
self.app = app
|
||||
self.api_key = api_key
|
||||
self.admin_api_key = admin_api_key
|
||||
self.fastapi_app = fastapi_app
|
||||
|
||||
async def __call__(self, scope, receive, send):
|
||||
if scope["type"] != "http":
|
||||
await self.app(scope, receive, send)
|
||||
return
|
||||
|
||||
request = Request(scope, receive=receive)
|
||||
path = request.url.path
|
||||
authz = request.headers.get("Authorization")
|
||||
level = _get_auth_level_from_app_and_scope(self.fastapi_app, scope)
|
||||
decision = decide_request_auth(
|
||||
method=request.method,
|
||||
path=path,
|
||||
authorization_header=authz,
|
||||
api_key=self.api_key,
|
||||
admin_api_key=self.admin_api_key,
|
||||
auth_level=level,
|
||||
)
|
||||
|
||||
if not decision.allowed:
|
||||
response = ORJSONResponse(
|
||||
content={
|
||||
"error": (
|
||||
"Unauthorized"
|
||||
if decision.error_status_code == 401
|
||||
else "Forbidden"
|
||||
)
|
||||
},
|
||||
status_code=decision.error_status_code,
|
||||
)
|
||||
await response(scope, receive, send)
|
||||
return
|
||||
|
||||
await self.app(scope, receive, send)
|
||||
|
||||
app.add_middleware(
|
||||
_ApiKeyASGIMiddleware,
|
||||
api_key=api_key,
|
||||
admin_api_key=admin_api_key,
|
||||
fastapi_app=app,
|
||||
)
|
||||
Reference in New Issue
Block a user