
    hH                     l   d dl Z d dlZd dlZd dlmZmZmZmZ d dlm	Z	m
Z
mZ d dlmZmZ d dlmZ d dl d dlmZ 	 d0de
d	ee   d
ee   fdZ	 d0deee      de
d	ee   d
eeee   f   fdZded
efdZdeded
efdZdededed
efdZdedededee   d
ef
dZdededee   ded
ef
dZde
dedefdZdefdZde
d
efd Z de
d
efd!Z!d"ed
efd#Z"d$e#fd%Z$d&e%d
ee&ee#f      fd'Z'd&e%d
ee&ee#f      fd(Z(ded
efd)Z)d* Z*	 d1ded+ee   d
ee   fd,Z+deded
ee,eee   f      fd-Z-d.ed
efd/Z.y)2    N)AnyListOptionalTuple)HTTPExceptionRequeststatus)Routerprovider_list)verbose_proxy_logger)*)#CONFIGURABLE_CLIENTSIDE_AUTH_PARAMSrequestuse_x_forwarded_forreturnc                     d }|du rd| j                   v r| j                   d   }|S | j                  | j                  j                  }|S d}|S )NTzx-forwarded-for )headersclienthost)r   r   	client_ips      Y/var/www/Befach/backend/env/lib/python3.12/site-packages/litellm/proxy/auth/auth_utils.py_get_request_ip_addressr      sd     Id"'8GOO'KOO$56	  
	#NN''	  	    allowed_ipsc                 :    | yt        ||      }|| vrd|fS d|fS )z)
    Returns if ip is allowed or not
    )TN)r   r   FT)r   )r   r   r   r   s       r   _check_valid_ipr      s>      (-@I
 #i?r   request_bodyc                 \    d}| j                  d      }|yd|v sd|v sd|v sd|v ryd| v ry	y)
zh
    if 'api_base' in request body. Check if complete credentials given. Prevent malicious attacks.
    NmodelF	sagemakerbedrock	vertex_aivertex_ai_betaapi_keyT)get)r   given_models     r   check_complete_credentialsr(   3   sW     "&K""7+K 	{"#+%{* L r   request_body_value	regex_strc                 <    t        j                  ||       s|| k(  ryy)zP
    Check if request_body_value matches the regex_str or is equal to param
    TF)rematchr)   r*   s     r   check_regex_or_str_matchr/   L   s!     
xx	-.)?Q2Qr   param#configurable_clientside_auth_paramsc                     |y|D ]B  }t        |t              r| |k(  r yt        |t              s+| dk(  s1t        ||d         sB y y)zd
    Check if param is a str or dict and if request_body_value is in the list of allowed values
    FTapi_baser.   )
isinstancestrDictr/   )r0   r)   r1   items       r   _is_param_allowedr8   U   sY     +23dC Ud]d#
"'?#5z*(  4 r   r    
llm_routerc                    |y|j                  |       }|@| j                  dd      d   t        v r%|j                  | j                  dd      d         }|y||j                  yt	        |||j                        S )z
    Check if model is allowed to use configurable client-side params
    - get matching model
    - check if 'clientside_configurable_parameters' is set for model
    -
    F)model_group/   r   )r0   r)   r1   )get_model_group_infosplitr   r1   r8   )r    r0   r)   r9   
model_infos        r   5_allow_model_level_clientside_configurable_parametersrA   m   s     00U0CJ;;sAq!]2#88!KKQ/2 9 J ZKKS-,6,Z,Z r   general_settingsc                     ddg}|D ]M  }|| v st        |       r|j                  d      du r yt        ||| |   |      du r yt        d| d       y)	u  
    Check if the request body is safe.

    A malicious user can set the ﻿api_base to their own domain and invoke POST /chat/completions to intercept and steal the OpenAI API key.
    Relevant issue: https://huntr.com/bounties/4001e1a2-7b7a-4776-a3ae-e6692ec3d997
    r3   base_url)r   allow_client_side_credentialsT)r    r0   r)   r9   zRejected Request: z is not allowed in request body. Enable with `general_settings::allow_client_side_credentials` on proxy config.yaml. Relevant Issue: https://huntr.com/bounties/4001e1a2-7b7a-4776-a3ae-e6692ec3d997)r(   r&   rA   
ValueError)r   rB   r9   r    banned_paramsr0   s         r   is_request_body_saferH      s      ,M\!.)  ##$CDLE'3E':)	  $UG ,b b ' 2 r   request_dataroutec           	      &  K   ddl m}m}m} t	        |        d{    t        ||||j                  dd             t        |j                  dd      |j                  d	d
      |       \  }}|st        t        j                  d| d      d|v rx|d   }|dur0t        j                  dt        j                  j                          ||vr:t        j                  d| d|        t        t        j                  d| d      yy7 w)ax  
    1. Checks if request size is under max_request_size_mb (if set)
    2. Check if request body is safe (example user has not set api_base in request body)
    3. Check if IP address is allowed (if set)
    4. Check if request route is an allowed route on the proxy (if set)

    Returns:
    - True

    Raises:
    - HTTPException if request fails initial auth checks
    r   )rB   r9   premium_user)r   Nr    r   )r   rB   r9   r    r   r   F)r   r   r   zAccess forbidden: IP address z not allowed.)status_codedetailallowed_routesTz=Trying to set allowed_routes. This is an Enterprise feature. zRoute z not in allowed_routes=zAccess forbidden: Route z not allowed)litellm.proxy.proxy_serverrB   r9   rL   check_if_request_size_is_saferH   r&   r   r   r	   HTTP_403_FORBIDDENr   errorCommonProxyErrorsnot_premium_uservalue)	r   rI   rJ   rB   r9   rL   is_valid_ippassed_in_ip_allowed_routess	            r   pre_db_read_auth_checksrZ      sB    " VU (
888 !)R
	 !0$((=,001FN!K 112<.N
 	
 ++*+;<t# &&OPaPrPrPxPxOyz ' &&66GH  "551%E 	 ( ,5 9s   DDC3Dcurrent_routec                     ddl m}m} 	 |dury|y|j                  dg       }| |v ryy# t        $ r+}t        j                  dt        |              Y d}~yd}~ww xY w)a  
    Helper to check if the user defined public_routes on config.yaml

    Parameters:
    - current_route: str - the route the user is trying to call

    Returns:
    - bool - True if the route is defined in public_routes
    - bool - False if the route is not defined in public_routes


    In order to use this the litellm config.yaml should have the following in general_settings:

    ```yaml
    general_settings:
        master_key: sk-1234
        public_routes: ["LiteLLMRoutes.public_routes", "/spend/calculate"]
    ```
    r   rB   rL   TFNpublic_routesz"route_in_additonal_public_routes: )rP   rB   rL   r&   	Exceptionr   rS   r5   )r[   rB   rL   routes_definedes        r    route_in_additonal_public_routesrb      sn    , Jt##)--orBN* ""%GAx#PQs   * * * 	A!AAc                    	 t        | d      rr| j                  j                  j                  | j                  j                        r9| j                  j                  t        | j                  j                        dz
  d S | j                  j                  S # t        $ rX}t        j                  dt        |       d| j                  j                          | j                  j                  cY d}~S d}~ww xY w)z
    Helper to get the route from the request

    remove base url from path if set e.g. `/genai/chat/completions` -> `/chat/completions
    rD   r=   Nzerror on get_request_route: z!, defaulting to request.url.path=)
hasattrurlpath
startswithrD   lenr_   r   debugr5   )r   ra   s     r   get_request_routerj     s     7J'GKK,<,<,G,G!!-
 ;;##C(8(8(=(=$>$B$DEE;;###  ""*3q6(2ST[T_T_TdTdSef	
 {{	 s%   A=B  B 	C7AC2,C72C7c                   K   ddl m}m} |j                  dd      }|/|dur1t	        j
                  dt        j                  j                          y| j                  j                  d      }|rct        |      }t        |      }t	        j                  d	|        ||kD  r.t        d
| d| dt        j                  j                  dd      y| j!                          d{   }t#        |      }t        |      }	t	        j                  d|	        |	|kD  r.t        d
|	 d| dt        j                  j                  dd      y7 gw)a  
    Enterprise Only:
        - Checks if the request size is within the limit

    Args:
        request (Request): The incoming request.

    Returns:
        bool: True if the request size is within the limit

    Raises:
        ProxyException: If the request size is too large

    r   r]   max_request_size_mbNTzPusing max_request_size_mb - not checking -  this is an enterprise only feature. content-lengthbytes_valuez"content_length request size in MB=z+Request size is too large. Request size is  MB. Max size is  MB  messagetypecoder0   z request body request size in MB=)rP   rB   rL   r&   r   warningrT   rU   rV   r   intbytes_to_mbri   ProxyExceptionProxyErrorTypesbad_request_errorbodyrh   )
r   rB   rL   rl   content_lengthheader_sizeheader_size_mbr}   	body_sizerequest_size_mbs
             r   rQ   rQ   1  s     J*../DdK&t# ((bct  dF  dF  dL  dL  cM  N  !,,-=>n-K([AN &&4^4DE  33$I.IYYjk~j  @C  D(::@@*	 .  !'DD	I)i@O &&2?2CD !44$I/IZZkl  lA  AD  E(::@@*	   (s   C&E(E)A(Eresponsec                   K   ddl m}m} |j                  dd      }||dur1t	        j
                  dt        j                  j                          yt        t        j                  |             }t	        j                  d|        ||kD  r.t        d	| d
| dt        j                  j                  dd      yw)a   
    Enterprise Only:
        - Checks if the response size is within the limit

    Args:
        response (Any): The response to check.

    Returns:
        bool: True if the response size is within the limit

    Raises:
        ProxyException: If the response size is too large

    r   r]   max_response_size_mbNTzQusing max_response_size_mb - not checking -  this is an enterprise only feature. rn   zresponse size in MB=z-Response size is too large. Response size is rp   rq   rr   rm   rs   )rP   rB   rL   r&   r   rw   rT   rU   rV   ry   sys	getsizeofri   rz   r{   r|   )r   rB   rL   r   response_size_mbs        r   check_response_size_is_safer   q  s       J+//0FM't# ((cdu  eG  eG  eM  eM  dN  O &3==3JK""%9:J9K#LM22 GHXGYYjk  kA  AD  E$66<<&	  s   B=B?ro   c                     | dz  S )z'
    Helper to convert bytes to MB
    i    rn   s    r   ry   ry     s     +&&r   user_api_key_dictc                     | j                   rd| j                   v r| j                   d   S y | j                  r9i }| j                  j                         D ]  \  }}d|v s|d   |d   ||<    |S y )Nmodel_rpm_limit	rpm_limit)metadatamodel_max_budgetitems)r   r   r    budgets       r   get_key_model_rpm_limitr     s     !! 1 : ::$--.?@@  
	+	+*,.??EEGME6f$)<)H)/)<& H r   c                     | j                   rd| j                   v r| j                   d   S y | j                  rd| j                  v r| j                  d   S y )Nmodel_tpm_limit	tpm_limit)r   r   )r   s    r   get_key_model_tpm_limitr     sa     !! 1 : ::$--.?@@
 	 
	+	++<<<$55kBBr   c                 $    dg}|D ]  }|| v s y y)Nz	vertex-aiTFr   )rJ   %PROVIDER_SPECIFIC_PASS_THROUGH_ROUTESprefixs      r   is_pass_through_provider_router     s(    -)
 8U? 8 r   c                      t        j                  dd      } t        j                  dd      }t        j                  dd      }| duxs
 |duxs |du}|S )z
    Check if the user has set up single sign-on (SSO) by verifying the presence of Microsoft client ID, Google client ID or generic client ID and UI username environment variables.
    Returns a boolean indicating whether SSO has been set up.
    MICROSOFT_CLIENT_IDNGOOGLE_CLIENT_IDGENERIC_CLIENT_ID)osgetenv)microsoft_client_idgoogle_client_idgeneric_client_id	sso_setups       r   _has_user_setup_ssor     sk    
 ))$94@yy!3T:		"5t< 
D	( 	+D(	+T)  r   request_headersc                 >   ddl m} |~d}|j                  |      }|rit        |t              rY|j                         D ]F  \  }}|j                         |j                         k(  s(|}|j                         s;t	        |      c S  d| v r| d   | d   }t	        |      S | j                  d      }	t        |	t              r|	j                  d      }
|
t	        |
      S | j                  d      }t        |t              r|j                  d      }|t	        |      S y )Nr   )rB   user_header_nameuserlitellm_metadatar   user_id)	rP   rB   r&   r4   r5   r   lowerstripdict)r   r   rB   user_id_header_config_keycustom_header_name_to_checkheader_nameheader_valueuser_id_from_headeruser_from_body_user_fieldr   user_from_litellm_metadatametadata_dictuser_id_from_metadata_fields                r   !get_end_user_id_from_request_bodyr     s6   
 <
 "$6!&6&:&:;T&U#&:6QSV+W-<-B-B-D)\$$&*E*K*K*MM*6'*002"#677	 .E ,v"6"B$0$8!,-- $''(:;"D)%5%9%9&%A"%1122 !$$Z0M-&&3&7&7	&B#&2233r   c                 R   | j                  d      xs | j                  d      }|P|j                  d      }t        |      dk(  r|d   j                         }n|D cg c]  }|j                          }}|)t	        j
                  d|      }|r|j                  d      }|S c c}w )Nr    target_model_names,r=   r   z/openai/deployments/([^/]+))r&   r?   rh   r   r,   r-   group)rI   rJ   r    model_namesmr-   s         r   get_model_from_requestr   	  s     W%O)9)9:N)OEkk#&{q N((*E(341QWWY4E4 }7?KKNEL 5s   B$r%   c                     d| dd   S )Nzsk-...r   )r%   s    r   abbreviate_api_keyr      s    GBCL>""r   )F)N)/r   r,   r   typingr   r   r   r   fastapir   r   r	   litellmr
   r   litellm._loggingr   litellm.proxy._typeslitellm.types.routerr   boolr5   r   r   r   r(   r/   r8   rA   rH   rZ   rb   rj   rQ   r   rx   ry   UserAPIKeyAuthr6   r   r   r   r   r   Unionr   r   r   r   r   <module>r      s   	 	 
 - - 2 2 ) 1 " D =B+3D>c]" +0$s)$ "$ 4#	.T d 2    *M 
	003AI&AQ	B$$*.$<DV<L$UX$	$N;;; ;|&C &R w  3  *= =T =@% % %P'S '%d38n 
%
d38n

# 
$ 
& ;?)))1$)c])X"eCcN#$.# # #r   