Unverified Commit bf668b5b authored by Yan Pashkovsky's avatar Yan Pashkovsky Committed by GitHub
Browse files

[Feature] Support multiple api keys in server (#18548)


Signed-off-by: default avatarYan Pashkovsky <yanp.bugz@gmail.com>
parent da3e0bd6
...@@ -126,6 +126,7 @@ curl http://localhost:8000/v1/models ...@@ -126,6 +126,7 @@ curl http://localhost:8000/v1/models
``` ```
You can pass in the argument `--api-key` or environment variable `VLLM_API_KEY` to enable the server to check for API key in the header. You can pass in the argument `--api-key` or environment variable `VLLM_API_KEY` to enable the server to check for API key in the header.
You can pass multiple keys after `--api-key`, and the server will accept any of the keys passed, this can be useful for key rotation.
### OpenAI Completions API with vLLM ### OpenAI Completions API with vLLM
......
...@@ -1239,9 +1239,9 @@ class AuthenticationMiddleware: ...@@ -1239,9 +1239,9 @@ class AuthenticationMiddleware:
2. The request path doesn't start with /v1 (e.g. /health). 2. The request path doesn't start with /v1 (e.g. /health).
""" """
def __init__(self, app: ASGIApp, api_token: str) -> None: def __init__(self, app: ASGIApp, tokens: list[str]) -> None:
self.app = app self.app = app
self.api_token = api_token self.api_tokens = {f"Bearer {token}" for token in tokens}
def __call__(self, scope: Scope, receive: Receive, def __call__(self, scope: Scope, receive: Receive,
send: Send) -> Awaitable[None]: send: Send) -> Awaitable[None]:
...@@ -1255,7 +1255,7 @@ class AuthenticationMiddleware: ...@@ -1255,7 +1255,7 @@ class AuthenticationMiddleware:
headers = Headers(scope=scope) headers = Headers(scope=scope)
# Type narrow to satisfy mypy. # Type narrow to satisfy mypy.
if url_path.startswith("/v1") and headers.get( if url_path.startswith("/v1") and headers.get(
"Authorization") != f"Bearer {self.api_token}": "Authorization") not in self.api_tokens:
response = JSONResponse(content={"error": "Unauthorized"}, response = JSONResponse(content={"error": "Unauthorized"},
status_code=401) status_code=401)
return response(scope, receive, send) return response(scope, receive, send)
...@@ -1512,8 +1512,8 @@ def build_app(args: Namespace) -> FastAPI: ...@@ -1512,8 +1512,8 @@ def build_app(args: Namespace) -> FastAPI:
status_code=HTTPStatus.BAD_REQUEST) status_code=HTTPStatus.BAD_REQUEST)
# Ensure --api-key option from CLI takes precedence over VLLM_API_KEY # Ensure --api-key option from CLI takes precedence over VLLM_API_KEY
if token := args.api_key or envs.VLLM_API_KEY: if tokens := [key for key in (args.api_key or [envs.VLLM_API_KEY]) if key]:
app.add_middleware(AuthenticationMiddleware, api_token=token) app.add_middleware(AuthenticationMiddleware, tokens=tokens)
if args.enable_request_id_headers: if args.enable_request_id_headers:
app.add_middleware(XRequestIdMiddleware) app.add_middleware(XRequestIdMiddleware)
......
...@@ -85,9 +85,9 @@ class FrontendArgs: ...@@ -85,9 +85,9 @@ class FrontendArgs:
"""Allowed methods.""" """Allowed methods."""
allowed_headers: list[str] = field(default_factory=lambda: ["*"]) allowed_headers: list[str] = field(default_factory=lambda: ["*"])
"""Allowed headers.""" """Allowed headers."""
api_key: Optional[str] = None api_key: Optional[list[str]] = None
"""If provided, the server will require this key to be presented in the """If provided, the server will require one of these keys to be presented in
header.""" the header."""
lora_modules: Optional[list[LoRAModulePath]] = None lora_modules: Optional[list[LoRAModulePath]] = None
"""LoRA modules configurations in either 'name=path' format or JSON format """LoRA modules configurations in either 'name=path' format or JSON format
or JSON list format. Example (old format): `'name=path'` Example (new or JSON list format. Example (old format): `'name=path'` Example (new
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment