Ë
    tPêj<V  ã                   ó  — U d Z ddlZddlZddlZddlZddlZddlmZmZ ddl	m
Z
 ddlmZmZmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZmZ ddlmZ 	 ddlmZ ddlmZ ddl m!Z! ddl"m#Z# dZ$dZ&ee'd<   dZ(ee'd<   dZ)ee'd<   dZ*ee'd<   dZ+ee'd<   dZ,ee'd<   dZ-ee'd<   d Z.ee'd!<   d"Z/ee'd#<   d$Z0ee'd%<   d&Z1ee'd'<   d"Z2ee'd(<   d)Z3ee'd*<   d+Z4ee'd,<   d-Z5ee'd.<   d/Z6ee'd0<   d1Z7ee'd2<   d3Z8ee'd4<   d5efd6„Z9 G d7„ d8«      Z:y# e%$ r dZ$Y Œ˜w xY w)9a  
SAML 2.0 SSO for the LiteLLM proxy admin UI.

Supports both SP-initiated and IdP-initiated login via the HTTP-POST binding,
using the OneLogin python3-saml toolkit for signature, audience and time
validation. The IdP is configured from its metadata (``SAML_IDP_METADATA_URL``
or inline ``SAML_IDP_METADATA_XML``); a successful login is mapped to a
``CustomOpenID`` and handed to the shared post-login path used by every other
SSO provider.

python3-saml pulls in the native ``xmlsec``/``libxml2`` libraries, so it is an
optional dependency. When it is not installed the SAML routes return a clear
error instead of breaking proxy startup.
é    N)ÚFinalÚcast)Ú	parse_qsl)ÚHTTPExceptionÚRequestÚstatus)ÚRedirectResponse)ÚValidationError)Úverbose_proxy_logger)Ú	DualCache)ÚCustomOpenIDÚget_litellm_user_role)Úget_custom_url)ÚOneLogin_Saml2_Auth)Ú OneLogin_Saml2_IdPMetadataParser)ÚOneLogin_Saml2_Settings)ÚOneLogin_Saml2_XMLTFzsso/saml/loginÚSAML_LOGIN_ROUTEzsso/saml/callbackÚSAML_CALLBACK_ROUTEzsso/saml/metadataÚSAML_METADATA_ROUTEÚlitellm_saml_authnÚ_SAML_AUTHN_STATE_COOKIEÚsaml_idp_settingsÚ_SAML_IDP_SETTINGS_CACHE_PREFIXÚsaml_authn_requestÚ _SAML_AUTHN_REQUEST_CACHE_PREFIXÚsaml_consumed_assertionÚ%_SAML_CONSUMED_ASSERTION_CACHE_PREFIXiX  Ú_SAML_AUTHN_REQUEST_TTL_SECONDSi  Ú_SAML_IDP_METADATA_TTL_SECONDSé
   Ú$_SAML_METADATA_FETCH_TIMEOUT_SECONDSi  P Ú_SAML_MAX_POST_BYTESÚ&_SAML_REPLAY_GUARD_DEFAULT_TTL_SECONDSi€Q Ú"_SAML_REPLAY_GUARD_MAX_TTL_SECONDS)z!urn:oid:0.9.2342.19200300.100.1.3zBhttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddressÚemailÚemailAddressÚmailÚEmailÚ_EMAIL_ATTRIBUTE_CANDIDATES)zurn:oid:2.5.4.42z?http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givennameÚ	givenNameÚ
first_nameÚ	firstNameÚ _FIRST_NAME_ATTRIBUTE_CANDIDATES)zurn:oid:2.5.4.4z=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surnameÚsnÚsurnameÚ	last_nameÚlastNameÚ_LAST_NAME_ATTRIBUTE_CANDIDATES)ÚroleÚrolesÚlitellm_roleÚ_ROLE_ATTRIBUTE_CANDIDATES)ÚteamsÚteam_idsÚgroupsÚ_TEAM_IDS_ATTRIBUTE_CANDIDATESÚreturnc                  ó8   — t        t        j                  d¬«      S )NzöSAML SSO requires the optional 'python3-saml' dependency, which is not installed. Re-install litellm with the saml extra: 'pip install litellm[saml]'. The saml extra bundles the native xmlsec/libxml2 libraries, so no system packages are required.©Ústatus_codeÚdetail)r   r   ÚHTTP_501_NOT_IMPLEMENTED© ó    út/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/management_endpoints/sso/saml_sso.pyÚ_saml_unavailable_errorrE   a   s   € ÜÜ×3Ñ3ðLôð rC   c            
       óR  — e Zd ZdZed(dededz  dedz  fd„«       Zedefd„«       Zedededefd„«       Z	ed	e
defd
„«       Zed	e
defd„«       Zed	e
defd„«       Zed	e
defd„«       Zed	e
defd„«       Zededeeef   fd„«       Zed	e
deeef   deeef   fd„«       Zed(d	e
deeef   dz  deeef   fd„«       Ze	 d(d	e
dedeeef   dz  ddfd„«       Ze	 d(d	e
dededz  defd„«       Zed	e
dedefd„«       Zed	e
deeef   fd„«       Zed	e
dedeeef   defd„«       Zedddefd„«       Zedddedz  fd„«       Zedddededz  ddfd „«       Z edddefd!„«       Z!ed"eee"e   f   d#ed$e#ed%f   dedz  fd&„«       Z$ed"eee"e   f   d#ed$e#ed%f   de"e   fd'„«       Z%y))ÚSAMLAuthHandlerz6SP- and IdP-initiated SAML 2.0 login for the admin UI.NÚnameÚdefaultr<   c                 ó.   — t        j                  | |«      S ©N)ÚosÚgetenv)rH   rI   s     rD   Ú_envzSAMLAuthHandler._envp   s   € ä�y‰y˜˜wÓ'Ð'rC   c                  ól   — t        t        j                  d«      xs t        j                  d«      «      S )NÚSAML_IDP_METADATA_URLÚSAML_IDP_METADATA_XML)ÚboolrG   rN   rB   rC   rD   Úis_saml_configuredz"SAMLAuthHandler.is_saml_configuredt   s*   € ä”O×(Ñ(Ð)@ÓAÒrÄ_×EYÑEYÐZqÓErÓsÐsrC   c                 ót   — t         j                  | «      }|€|S |j                  «       j                  «       dv S )N)ÚtrueÚ1ÚyesÚon)rG   rN   ÚstripÚlower)rH   rI   Úraws      rD   Ú	_bool_envzSAMLAuthHandler._bool_envx   s7   € ä$×)Ñ)¨$Ó/ˆØˆ;ØˆNØ�y‰y‹{× Ñ Ó"Ð&@Ð@Ð@rC   Úrequestc                 óp   — t        t        | j                  «      ¬«      }|j                  d«      r|S |dz   S )N)Úrequest_base_urlú/)r   ÚstrÚbase_urlÚendswith)r]   Úbases     rD   Ú	_base_urlzSAMLAuthHandler._base_url   s1   € ä$´c¸'×:JÑ:JÓ6KÔLˆØ—}‘} SÔ)ˆtÐ9¨t°c©zÐ9rC   c                 óJ   — t         j                  | «      j                  d«      S )NÚhttps)rG   re   Ú
startswith©r]   s    rD   Ú	_is_httpszSAMLAuthHandler._is_https„   s   € ä×(Ñ(¨Ó1×<Ñ<¸WÓEÐErC   c                 ó:   — t         j                  | «      t        z   S rK   )rG   re   r   ri   s    rD   Ú_acs_urlzSAMLAuthHandler._acs_urlˆ   ó   € ä×(Ñ(¨Ó1Ô4GÑGÐGrC   c                 ó:   — t         j                  | «      t        z   S rK   )rG   re   r   ri   s    rD   Ú_metadata_urlzSAMLAuthHandler._metadata_urlŒ   rm   rC   c                 óZ   — t         j                  d«      xs t         j                  | «      S )NÚSAML_SP_ENTITY_ID)rG   rN   ro   ri   s    rD   Ú_sp_entity_idzSAMLAuthHandler._sp_entity_id�   s%   € ä×#Ñ#Ð$7Ó8Òb¼O×<YÑ<YÐZaÓ<bÐbrC   Úcachec              ƒ   ó:  K  — t         j                  d«      }t         j                  d«      }|xs |}|€t        t        j                  d¬«      ‚t
        › dt        j                  |j                  «       «      j                  «       › �}| j                  |¬«      }t        |t        «      rt        t        t        t        f   |«      S |�Ht!        j"                  t$        j&                  |t         j)                  dd«      t*        ¬	«      ƒ d {  –—† }n#t%        j,                  t        t        |«      «      }t        t        t        t        f   |«      }|j/                  d
«      st        t        j0                  d¬«      ‚| j3                  ||t4        ¬«       |S 7 Œ‹­w)NrP   rQ   zOSAML SSO is not configured. Set SAML_IDP_METADATA_URL or SAML_IDP_METADATA_XML.r>   ú:©ÚkeyÚSAML_IDP_METADATA_VALIDATE_CERTT)Úvalidate_certÚtimeoutÚidpzKCould not parse an IdP entityID/SSO URL/certificate from the SAML metadata.©rw   ÚvalueÚttl)rG   rN   r   r   rA   r   ÚhashlibÚsha256ÚencodeÚ	hexdigestÚ	get_cacheÚ
isinstanceÚdictr   ra   ÚobjectÚasyncioÚ	to_threadr   Úparse_remoter\   r"   ÚparseÚgetÚHTTP_502_BAD_GATEWAYÚ	set_cacher    )rs   Úmetadata_urlÚmetadata_xmlÚsourceÚ	cache_keyÚcachedÚparsedÚidp_settingss           rD   Ú_load_idp_settingsz"SAMLAuthHandler._load_idp_settings”   s]  è ø€ ä-×2Ñ2Ð3JÓKˆÜ-×2Ñ2Ð3JÓKˆØ$Ò4¨ˆØˆ>ÜÜ"×;Ñ;Øhôð ô
 >Ð>¸aÄÇÁÈvÏ}É}ËÓ@_×@iÑ@iÓ@kÐ?lÐmˆ	ØŸ™¨I˜Ó6ˆÜ�fœdÔ#ÜœœS¤&˜[Ñ)¨6Ó2Ð2àÐ#Ü"×,Ñ,Ü0×=Ñ=ØÜ-×7Ñ7Ð8YÐ[_Ó`Ü<ô	÷ ‰Fô 6×;Ñ;¼DÄÀlÓ<SÓTˆFä"¤4¬¬V¨Ñ#4°fÓ=ˆØ×Ñ Ô&ÜÜ"×7Ñ7Ødôð ð 	�‰˜I¨\Ô?]ˆÔ^ØÐð!ús   ‚DFÄFÄBFr”   c           
      ól  — t         j                  dd«      dt         j                  | «      t         j                  | «      ddœt         j	                  dd«      dœt         j                  d	d«      t         j                  d
d«      t         j                  dd«      ddddœdœ}t        j                  ||«      S )NÚSAML_STRICTTFz.urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST)ÚurlÚbindingÚSAML_SP_NAME_ID_FORMATz6urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress)ÚentityIdÚassertionConsumerServiceÚNameIDFormatÚSAML_WANT_ASSERTIONS_SIGNEDÚSAML_WANT_MESSAGES_SIGNEDÚSAML_AUTHN_REQUESTS_SIGNED)ÚwantAssertionsSignedÚwantMessagesSignedÚauthnRequestsSignedÚ
wantNameIdÚrequestedAuthnContextÚ*rejectUnsolicitedResponsesWithInResponseTo)ÚstrictÚdebugÚspÚsecurity)rG   r\   rr   rl   rN   r   Úmerge_settings)r]   r”   Úsp_settingss      rD   Ú_build_settingszSAMLAuthHandler._build_settings·   s¸   € ô &×/Ñ/°¸tÓDØä+×9Ñ9¸'ÓBä*×3Ñ3°GÓ<ØOñ-ô !0× 4Ñ 4Ø,ØLó!ñ
ô )8×(AÑ(AÐB_ÐaeÓ(fÜ&5×&?Ñ&?Ð@[Ð]bÓ&cÜ'6×'@Ñ'@ÐA]Ð_dÓ'eØ"Ø).Ø>Cññ1
ˆô. 0×>Ñ>¸{ÈLÓYÐYrC   Ú	post_datac                 óÚ   — t         j                  | «      }|j                  d«      \  }}}|j                  dd«      d   }|dk(  rdnd|dt        z   t        | j                  «      |xs i dœS )	Nz://r`   é   r   rg   rX   Úoff)rg   Ú	http_hostÚscript_nameÚget_datar®   )rG   re   Ú	partitionÚsplitr   r…   Úquery_params)r]   r®   rd   ÚschemeÚ_Ú	host_partÚhosts          rD   Ú_prepare_request_dataz%SAMLAuthHandler._prepare_request_dataÒ   ss   € ä%×/Ñ/°Ó8ˆØ#Ÿ~™~¨eÓ4Ñˆ��9Ø—o‘o c¨1Ó-¨aÑ0ˆà# wÒ.‘T°EØØÔ!4Ñ4Ü˜W×1Ñ1Ó2Ø"š bñ
ð 	
rC   r   c              ƒ   ó:  K  — t         s
t        «       ‚t        j                  |«      ƒ d {  –—† }t        j	                  | |«      }t        j                  | |«      }	 t        ||¬«      S 7 Œ># t        $ r#}t        t        j                  d|› �¬«      ‚d }~ww xY w­w)N)Úold_settingszInvalid SAML configuration: r>   )ÚSAML_AVAILABLErE   rG   r•   r­   r¼   r   Ú	Exceptionr   r   ÚHTTP_500_INTERNAL_SERVER_ERROR)r]   rs   r®   r”   ÚsettingsÚrequest_dataÚes          rD   Ú_build_authzSAMLAuthHandler._build_authß   s”   è ø€ õ Ü)Ó+Ð+Ü$3×$FÑ$FÀuÓ$M×MˆÜ)×9Ñ9¸'À<ÓPˆÜ-×CÑCÀGÈYÓWˆð	Ü& |À(ÔKÐKð	 Nùô
 ò 	ÜÜ"×AÑAØ5°a°SÐ9ôð ûð	üs3   ‚)B«A*¬0BÁA, Á)BÁ,	BÁ5BÂBÂBÚrelay_statec              ƒ   ó   K  — t         j                  | |«      ƒ d {  –—† }t        t        |j	                  |¬«      «      }t        |d¬«      }t        t        d z  |j                  «       «      }|�Y|j                  t        › d|› �dt        ¬«       t         j                  | «      }|j                  t        |t        d||rdnd	¬
«       |S 7 Œ¯­w)N)Ú	return_toi/  )r˜   r?   ru   rV   r|   TÚnoneÚlax)rw   r}   Úmax_ageÚhttponlyÚsecureÚsamesite)rG   rÅ   r   ra   Úloginr	   Úget_last_request_idr�   r   r   rj   Ú
set_cookier   )r]   rs   rÆ   ÚauthÚredirect_urlÚresponseÚ
request_idrÍ   s           rD   Úbuild_login_redirectz$SAMLAuthHandler.build_login_redirectò   sÍ   è ø€ ô ,×7Ñ7¸ÀÓG×GˆÜ"¤3¨¯
©
¸[¨
Ó(IÓJˆÜ*¨|ÈÔMˆÜ ¤ t¡¨T×-EÑ-EÓ-GÓHˆ
ØÐ!Ø�O‰OÜ7Ð8¸¸*¸ÐFØÜ3ð ô ô
 ,×5Ñ5°gÓ>ˆFØ×ÑÜ,Ø Ü7ØØÙ#)™¨uð  ô ð ˆð' Hús   ‚CœC�B0Cc              ƒ   ó˜  K  — t         s
t        «       ‚t        j                  |«      ƒ d {  –—† }t        j	                  | |«      }t        |d¬«      }t        t        |j                  «       «      }t        t        t           |j                  |«      «      }|r-t        t        j                  ddj                  |«      › �¬«      ‚|S 7 Œœ­w)NT)Úsp_validation_onlyzInvalid SP metadata: ú, r>   )r¿   rE   rG   r•   r­   r   r   ra   Úget_sp_metadataÚlistÚvalidate_metadatar   r   rÁ   Újoin)r]   rs   r”   rÂ   Úsaml_settingsÚmetadataÚerrorss          rD   Úbuild_sp_metadataz!SAMLAuthHandler.build_sp_metadata  s®   è ø€ åÜ)Ó+Ð+Ü$3×$FÑ$FÀuÓ$M×MˆÜ)×9Ñ9¸'À<ÓPˆÜ6°xÐTXÔYˆÜœs M×$AÑ$AÓ$CÓDˆÜœT¤#™Y¨×(GÑ(GÈÓ(QÓRˆÙÜÜ"×AÑAØ.¨t¯y©y¸Ó/@Ð.AÐBôð ð ˆð Nús   ‚)C
«C¬BC
c              ƒ   ó¸  K  — | j                   j                  d«      }|�=|j                  «       r-t        |«      t        kD  rt        t        j                  d¬«      ‚t        «       }| j                  «       2 3 d{  –—† }||z  }t        |«      t        kD  sŒ!t        t        j                  d¬«      ‚7 Œ76 t        t        |j                  dd«      «      «      S ­w)zõRead the ACS POST form under a hard size cap before any base64/XML decoding.

        Bounds both Content-Length-declared and chunked requests so an unauthenticated
        caller cannot force unbounded buffering while decoding the SAMLResponse.zcontent-lengthNz/SAML response exceeds the maximum allowed size.r>   zutf-8Úreplace)Úheadersr‹   ÚisdigitÚintr#   r   r   ÚHTTP_413_CONTENT_TOO_LARGEÚ	bytearrayÚstreamÚlenr…   r   Údecode)r]   ÚdeclaredÚbodyÚchunks       rD   Úread_acs_post_dataz"SAMLAuthHandler.read_acs_post_data  sÇ   è ø€ ð "Ÿ/™/×-Ñ-Ð.>Ó?ˆØÐ H×$4Ñ$4Ô$6¼3¸x»=ÔK_Ò;_ÜÜ"×=Ñ=ØHôð ô
 ‹{ˆØ"Ÿ>™>Ó+÷ 	ð 	�%Ø�E‰MˆDÜ�4‹yÔ/Ó/Ü#Ü &× AÑ AØLôð ð	øÐ+ô ”I˜dŸk™k¨'°9Ó=Ó>Ó?Ð?ùs0   ‚A5CÁ7B5Á;B3Á<B5Á?CÂCÂ3B5Â5%Cc              ƒ   ól  K  — t         j                  | ||¬«      ƒ d {  –—† }| j                  j                  t        «      }	 |j                  |¬«       t        t        t           |j                  «       «      }|s|j                  «       sA|j                  «       }t        t        j                  d|xs dj!                  |«      › �¬«      ‚t         j#                  |||«      ƒ d {  –—†  t         j%                  |«      S 7 Œâ# t        $ r#}t        t        j                  d|› �¬«      ‚d }~ww xY w7 ŒJ­w)N)r®   )rÕ   z!Could not process SAML response: r>   zSAML authentication failed: rÙ   )rG   rÅ   Úcookiesr‹   r   Úprocess_responserÀ   r   r   ÚHTTP_401_UNAUTHORIZEDr   rÛ   ra   Ú
get_errorsÚis_authenticatedÚget_last_error_reasonrÝ   Ú_enforce_response_bindingÚ_result_from_auth)r]   rs   r®   rÒ   Úbrowser_request_idrÄ   rà   Úreasons           rD   Ú
handle_acszSAMLAuthHandler.handle_acs3  s  è ø€ ä+×7Ñ7¸ÀÐR[Ð7Ó\×\ˆØ$+§O¡O×$7Ñ$7Ô8PÓ$QÐð	Ø×!Ñ!Ð-?Ð!Ô@ô œT¤#™Y¨¯©Ó(9Ó:ˆÙ˜×.Ñ.Ô0Ø ×6Ñ6Ó8ˆFÜÜ"×8Ñ8Ø5°fÒ6QÀÇ	Á	È&Ó@QÐ5RÐSôð ô
 ×7Ñ7¸¸eÐEWÓX×XÐXÜ×0Ñ0°Ó6Ð6ð' ]ùô ò 	ÜÜ"×8Ñ8Ø:¸1¸#Ð>ôð ûð	úð 	Yús@   ‚D4žDŸ#D4ÁD ÁBD4Ã'D2Ã(D4Ä	D/ÄD*Ä*D/Ä/D4rÒ   c                 óÊ   — | j                  «       }t        |t        «      st        S |t        t	        j                  «       «      z
  }t        t        |t        «      t        «      S rK   )Ú"get_last_assertion_not_on_or_afterr„   ræ   r$   ÚtimeÚminÚmaxr%   )rÒ   Únot_on_or_afterÚ	remainings      rD   Ú_replay_guard_ttlz!SAMLAuthHandler._replay_guard_ttlJ  sP   € à!%×!HÑ!HÓ!JˆÜ˜/¬3Ô/Ü9Ð9Ø*¬S´·±³Ó-=Ñ=ˆ	ÜÜ�	ÔAÓBÜ.ó
ð 	
rC   c                 óF  — t        t        dz  | j                  «       «      }|r|S t        t        dz  | j	                  «       «      }|syt        j                  |«      }t        j                  |d«      D ]*  }t        t        dz  |j                  d«      «      }|sŒ(|c S  y)a	  The request id this response answers, read from the Response element or, when the
        IdP only stamps it on the bearer SubjectConfirmationData, from there. A non-None value
        marks the response as solicited (SP-initiated) and so requiring browser binding.Nz-//saml:SubjectConfirmationData[@InResponseTo]ÚInResponseTo)	r   ra   Ú get_last_response_in_response_toÚbytesÚget_last_response_xmlr   Úto_etreeÚqueryr‹   )rÒ   r}   ÚxmlÚrootÚnodeÚirts         rD   Ú_response_in_response_toz(SAMLAuthHandler._response_in_response_toU  s—   € ô
 œC $™J¨×(MÑ(MÓ(OÓPˆÙØˆLÜœ% $™,¨×(BÑ(BÓ(DÓEˆÙØÜ(×1Ñ1°#Ó6ˆÜ&×,Ñ,¨TÐ3bÓcò 	ˆDÜ”s˜T‘z 4§8¡8¨NÓ#;Ó<ˆCÚØ’
ð	ð rC   rù   c              ƒ   ó4  K  — t         j                  | «      }|�kt        › d|› �}|j                  |¬«      €t	        t
        j                  d¬«      ‚|�t        j                  ||«      s�t	        t
        j                  d¬«      ‚|�t	        t
        j                  d¬«      ‚t         j                  dd«      st	        t
        j                  d¬«      ‚|j                  €t	        t
        j                  d	¬«      ‚t        t        d z  | j                  «       «      }|€t	        t
        j                  d
¬«      ‚t        › d|› �}|j                  |dt         j!                  | «      ¬«      ƒ d {  –—† }|�!|dkD  rt	        t
        j                  d¬«      ‚y y 7 Œ(­w)Nru   rv   zBSAML response references an unknown or already-used login request.r>   z;SAML response is not bound to this browser's login request.ÚSAML_ALLOW_UNSOLICITEDFz8Unsolicited (IdP-initiated) SAML responses are disabled.z|Unsolicited (IdP-initiated) SAML responses require a shared Redis cache so the replay guard is enforced across every worker.z4SAML assertion is missing the required ID attribute.r°   r|   z7SAML assertion has already been used (replay detected).)rG   r  r   rƒ   r   r   ró   ÚsecretsÚcompare_digestr\   Úredis_cacher   ra   Úget_last_assertion_idr   Úasync_increment_cacher  )rÒ   rs   rù   Úin_response_toÚ	authn_keyÚassertion_idÚconsumed_keyÚconsumed_counts           rD   r÷   z)SAMLAuthHandler._enforce_response_bindingg  s³  è ø€ ô !0× HÑ HÈÓ NˆàÐ%Ü"BÐ!CÀ1À^ÐDTÐUˆIØ�‰ 9ˆÓ-Ð5Ü#Ü &× <Ñ <Ø_ôð ð "Ð)´×1GÑ1GÐHZÐ\jÔ1kÜ#Ü &× <Ñ <ØXôð ð  Ð+ÜÜ"×8Ñ8ØTôð ô !×*Ñ*Ð+CÀUÔKÜÜ"×8Ñ8ØQôð ð ×ÑÐ&ÜÜ"×8Ñ8ðKôð ô #¤3¨¡:¨t×/IÑ/IÓ/KÓLˆØÐÜÜ"×8Ñ8ØMôð ô "GÐ GÀqÈÈÐWˆØ&+×&AÑ&AØ A¬?×+LÑ+LÈTÓ+Rð 'Bó '
÷ !
ˆð Ð%¨.¸1Ò*<ÜÜ"×8Ñ8ØPôð ð +=Ð%ð!
ús   ‚E+FÅ-FÅ.)Fc                 óì  — t        t        t        t        t           f   | j	                  «       «      }t        t        d z  | j                  «       «      }t        j                  |dt        «      }|€|�d|v r|}|€0t        j                  d«      �t        t        j                  d¬«      ‚t        j                  |dd«      xs |xs |}|€t        t        j                  d¬«      ‚t        j                  |d	t        «      }t        j                  |d
t        «      }t        j                  |dt        «      }t        j!                  |dt"        «      }dj%                  d„ ||fD «       «      xs |}	t'        j(                  d||t        |j+                  «       «      «       	 t-        |||||	d d||rt/        |«      ¬«	      S d ¬«	      S # t0        $ r#}
t        t        j                  d|
› �¬«      ‚d }
~
ww xY w)NÚSAML_ATTRIBUTE_EMAILú@ÚALLOWED_EMAIL_DOMAINSzmSAML assertion did not contain an email address, but ALLOWED_EMAIL_DOMAINS restricts sign-in by email domain.r>   ÚSAML_ATTRIBUTE_USER_IDrB   zBSAML assertion did not contain a usable subject (NameID) or email.ÚSAML_ATTRIBUTE_FIRST_NAMEÚSAML_ATTRIBUTE_LAST_NAMEÚSAML_ATTRIBUTE_ROLEÚSAML_ATTRIBUTE_TEAM_IDSú c              3   ó&   K  — | ]	  }|sŒ|–— Œ y ­wrK   rB   )Ú.0Úparts     rD   ú	<genexpr>z4SAMLAuthHandler._result_from_auth.<locals>.<genexpr>Â  s   è ø€ Ò&X°ÒSW¤tÑ&Xùs   ‚Šz/SAML login: subject=%s, email=%s, attributes=%sÚsaml)	Úidr&   r,   r1   Údisplay_nameÚpictureÚproviderr9   Ú	user_rolez6SAML assertion contained an invalid subject or email: )r   r…   ra   rÛ   Úget_attributesÚ
get_nameidrG   Ú_attribute_valuer*   rN   r   r   ró   r.   r3   r7   Ú_attribute_valuesr;   rÝ   r   ÚinfoÚkeysr   r   r
   )rÒ   Ú
attributesÚname_idr&   Úuser_idr,   r1   Ú
role_valuer9   r,  rÄ   s              rD   rø   z!SAMLAuthHandler._result_from_authž  s   € ä ¤¤c¬4´©9 nÑ!5°t×7JÑ7JÓ7LÓMˆ
Üœc D™j¨$¯/©/Ó*;Ó<ˆä×0Ñ0°Ð=SÔUpÓqˆØˆ=˜WÐ0°S¸G±^ØˆEàˆ=œ_×1Ñ1Ð2IÓJÐVÜÜ"×8Ñ8ð9ôð ô )×9Ñ9¸*ÐF^Ð`bÓcÒwÐgnÒwÐrwˆØˆ?ÜÜ"×8Ñ8Ø[ôð ô
 ,×<Ñ<ØÐ3Ô5Uó
ˆ
ô +×;Ñ;ØÐ2Ô4Só
ˆ	ô %×5Ñ5°jÐBWÔYsÓtˆ
Ü)×;Ñ;ØÐ1Ô3Qó
ˆð "Ÿh™hÑ&X¸ÀYÐ8OÔ&XÓXÒaÐ\aˆä×!Ñ!Ø=¸wÈÌtÐT^×TcÑTcÓTeÓOfô	
ð	ÜØØØ%Ø#Ø)ØØØ!Ù?IÔ/°
Ó;ô
ð 
ð PTô
ð 
øô ò 	ÜÜ"×8Ñ8ØOÐPQÈsÐSôð ûð	ús   Æ!G Ç G Ç	G3ÇG.Ç.G3r6  Úenv_overrideÚ
candidates.c                 óB   — t         j                  | ||«      }|r|d   S d S )Nr   )rG   r3  )r6  r:  r;  Úvaluess       rD   r2  z SAMLAuthHandler._attribute_valueÚ  s*   € ô (×9Ñ9¸*ÀlÐT^Ó_ˆÙ"ˆv�a‰yÐ,¨Ð,rC   c                 ó¬   — t         j                  |«      }|r|g|¢­n|}|D ]*  }| j                  |«      }|sŒ|D �cg c]  }|sŒ|‘Œ	 c}c S  g S c c}w rK   )rG   rN   r‹   )r6  r:  r;  Úoverrider5  rw   r=  Úvs           rD   r3  z!SAMLAuthHandler._attribute_valuesã  sd   € ô *×.Ñ.¨|Ó<ˆÙ19�xÐ- *Ò-¸zˆØò 	0ˆCØ—^‘^ CÓ(ˆFÚØ#)Ö/˜aªQšÒ/Ò/ð	0ð ˆ	ùò 0s   ½AÁArK   )&Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodra   rN   rR   rS   r\   r   re   rj   rl   ro   rr   r   r…   r†   r•   r­   r¼   rÅ   r	   rÖ   rá   rï   r   rû   ræ   r  r  r÷   rø   rÛ   Útupler2  r3  rB   rC   rD   rG   rG   m   sO  „ Ù@àñ(�3ð (  t¡ð (°s¸T±zò (ó ð(ð ðt ò tó ðtð ðA˜ð A dð A¨tò Aó ðAð ð:˜7ð : sò :ó ð:ð ðF˜7ð F tò Fó ðFð ðH˜'ð H cò Hó ðHð ðH˜wð H¨3ò Hó ðHð ðc˜wð c¨3ò có ðcð ð ¨	ð  °d¸3À¸;Ñ6Gò  ó ð ðD ðZ ð Z¸¸SÀ&¸[Ñ8Ið ZÈdÐSVÐX^ÐS^ÑN_ò Zó ðZð4 ñ

 wð 

¸4ÀÀSÀ¹>ÈDÑ;Pð 

Ð\`ÐadÐflÐalÑ\mò 

ó ð

ð ð ,0ñØðàðð ˜˜S˜‘> DÑ(ðð 
ò	ó ðð$ àFJñØðØ!*ðØ9<¸t¹ðà	òó ðð0 ð¨ð ¸ð Àsò ó ðð ð@¨'ð @°d¸3À¸8±nò @ó ð@ð. ð7 'ð 7°)ð 7ÈÈSÐRUÈXÉð 7Ð[gò 7ó ð7ð, ð
Ð 5ð 
¸#ò 
ó ð
ð ðÐ'<ð ÀÀtÁò ó ðð" ð4Ø#ð4àð4ð   $™Jð4ð 
ò	4ó ð4ðl ð9Ð 5ð 9¸,ò 9ó ð9ðv ð-Ø˜˜d 3™i˜Ñ(ð-àð-ð ˜#˜s˜(‘Oð-ð 
ˆt‰ò	-ó ð-ð ðØ˜˜d 3™i˜Ñ(ðàðð ˜#˜s˜(‘Oðð 
ˆc‰ò	ó ñrC   rG   );rD  r‡   r   rL   r  rþ   Útypingr   r   Úurllib.parser   Úfastapir   r   r   Úfastapi.responsesr	   Úpydanticr
   Úlitellm._loggingr   Úlitellm.caching.dual_cacher   Ú(litellm.proxy.management_endpoints.typesr   r   Úlitellm.proxy.utilsr   Úonelogin.saml2.authr   Ú"onelogin.saml2.idp_metadata_parserr   Úonelogin.saml2.settingsr   Úonelogin.saml2.xml_utilsr   r¿   ÚImportErrorr   Ú__annotations__r   r   r   r   r   r   r   r    r"   r#   r$   r%   r*   r.   r3   r7   r;   rE   rG   rB   rC   rD   ú<module>rV     sW  ðòó0 Û Û 	Û Û ß Ý "ç 2Ñ 2Ý .Ý $å 1Ý 0ß XÝ .ðÝ7ÝSÝ?Ý;à€Nð +Ð �%Ó *Ø0Ð �UÓ 0Ø0Ð �UÓ 0à"6Ð ˜%Ó 6Ø)<Ð  Ó <Ø*>Ð   %Ó >Ø/HÐ % uÓ HØ),Ð  Ó ,Ø(,Ð  Ó ,Ø.0Ð $ eÓ 0Ø-Ð �eÓ -ð 15Ð &¨Ó 4Ø,1Ð " EÓ 1ð&Ð ˜Uó ð+Ð   %ó ð*Ð  ó ð %FÐ ˜EÓ EØ(GÐ  Ó Gð	 ó 	÷Bò Bøðy ò Ø‚Nðús   ÁD  Ä D
Ä	D
