o
    پiy                     @  s   d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	m
Z
 eddG d	d
 d
ZG dd deeZd%ddZd&ddZd'ddZd(d!d"Zd)d#d$ZdS )*z~Auth utilities for HTTP servers.

This module is intentionally lightweight (no torch import) so it can be used in unit tests.
    )annotationsN)	dataclass)Enum)AnyOptionalT)frozenc                   @  s"   e Zd ZU ded< dZded< dS )AuthDecisionboolallowed  interror_status_codeN)__name__
__module____qualname____annotations__r    r   r   I/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/utils/auth.pyr      s   
 r   c                   @  s   e Zd ZdZdZdZdZdS )	AuthLevelzJPer-endpoint auth level (attached to endpoint function via `@auth_level`).normaladmin_optionaladmin_forceN)r   r   r   __doc__NORMALADMIN_OPTIONALADMIN_FORCEr   r   r   r   r      s
    r   levelc                   s    fdd}|S )z<Mark endpoint with auth level (stored in endpoint metadata).c                   s
    | _ | S N)_auth_level)funcr   r   r   	decorator   s   zauth_level.<locals>.decoratorr   )r   r!   r   r    r   
auth_level   s   r"   appr   scopedictreturnc           	   	   C  s   ddl m} tt| ddddpt| dg }|D ]9}z	||\}}W n	 ty,   Y qw ||jkrQ|dp<t|dd}t|dd}t|trL|  S tj	  S qtj	S )zBBest-effort resolve auth level by matching the request to a route.r   )MatchrouterNroutesendpointr   )
starlette.routingr'   getattrmatches	ExceptionFULLget
isinstancer   r   )	r#   r$   r'   r)   routematchchild_scoper*   r   r   r   r   "_get_auth_level_from_app_and_scope&   s    
r5   r	   c                 C  sR   t t | ddddpt | dg }|D ]}t |dd}t |ddtjkr& dS qdS )z;Return True if any route endpoint is marked as ADMIN_FORCE.r(   Nr)   r*   r   TF)r,   r   r   )r#   r)   r2   r*   r   r   r   app_has_admin_force_endpoints>   s   r6   methodstrpathauthorization_headerOptional[str]api_keyadmin_api_keyc                 C  s   | dkr	t ddS |ds|drt ddS ddd}|tjkr9|s*t dddS |||s4t ddS t ddS |tjkrW|rHt |||dS |rRt |||dS t ddS |rat |||dS t ddS )a  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.
    OPTIONST)r
   z/healthz/metricsr:   r;   expected_tokenr8   r&   r	   c                 S  sD   | sdS |  dd}t|dks|d  dkrdS t|d |S )z1Check bearer token with constant-time comparison.F       r   bearer)splitlenlowersecretscompare_digest)r:   r?   partsr   r   r   _check_bearer_tokeng   s   z0decide_request_auth.<locals>._check_bearer_tokenFi  )r
   r   N)r:   r;   r?   r8   r&   r	   )r   
startswithr   r   r   )r7   r9   r:   r<   r=   r"   rJ   r   r   r   decide_request_authJ   s0   









rL   c                  sB   ddl m  ddlm G  fddd}| j|||| d dS )zQAdd middleware for three endpoint auth levels: normal/admin_optional/admin_force.r   )ORJSONResponse)Requestc                      s&   e Zd ZdZdd Z fddZdS )z5add_api_key_middleware.<locals>._ApiKeyASGIMiddlewarez<ASGI-native middleware to preserve client disconnect events.c                S  s   || _ || _|| _|| _d S r   )r#   r<   r=   fastapi_app)selfr#   r<   r=   rO   r   r   r   __init__   s   
z>add_api_key_middleware.<locals>._ApiKeyASGIMiddleware.__init__c           
        s   |d dkr|  |||I d H  d S ||d}|jj}|jd}t| j|}t|j||| j	| j
|d}|jsT d|jdkrBdnd	i|jd
}	|	|||I d H  d S |  |||I d H  d S )Ntypehttp)receiveAuthorization)r7   r9   r:   r<   r=   r"   errorr   Unauthorized	Forbidden)contentstatus_code)r#   urlr9   headersr0   r5   rO   rL   r7   r<   r=   r
   r   )
rP   r$   rT   sendrequestr9   authzr   decisionresponserM   rN   r   r   __call__   s8   	

z>add_api_key_middleware.<locals>._ApiKeyASGIMiddleware.__call__N)r   r   r   r   rQ   rc   r   rb   r   r   _ApiKeyASGIMiddleware   s    rd   )r<   r=   rO   N)fastapi.responsesrM   starlette.requestsrN   add_middleware)r#   r<   r=   rd   r   rb   r   add_api_key_middleware   s   +
rh   )r   r   )r#   r   r$   r%   r&   r   )r#   r   r&   r	   )r7   r8   r9   r8   r:   r;   r<   r;   r=   r;   r"   r   r&   r   )r<   r;   r=   r;   )r   
__future__r   rG   dataclassesr   enumr   typingr   r   r   r8   r   r"   r5   r6   rL   rh   r   r   r   r   <module>   s    




K