o
    <i7                     @   s  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 d dlZd dlmZmZmZ d dlmZ d dlmZmZ d dlmZ d	Zd
ZeeZG dd deZG dd deZG dd deZG dd deZG dd dZ G dd deZ!G dd deZ"G dd deZ#G dd deZ$G dd dZ%e%&de e%&d e e%&d!e e%&d"e! e%&d#e" e%&d$e# dS )%    N)ABCabstractmethod)cached_property)Any)	HTTPErrorPreparedRequestSession)AuthBase)TokenResponse_handle_non_200_response)
OAuthErrorzauth.manager:c                   @   s&   e Zd ZdZededB fddZdS )AuthManagerz
    Abstract base class for Authentication Managers used to supply authorization headers to HTTP clients (e.g. requests.Session).

    Subclasses must implement the `auth_header` method to return an Authorization header value.
    returnNc                 C   s   dS )zAReturn the Authorization header value, or None if not applicable.N selfr   r   X/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/pyiceberg/catalog/rest/auth.pyauth_header/   s    zAuthManager.auth_header)__name__
__module____qualname____doc__r   strr   r   r   r   r   r   (   s    r   c                   @   s"   e Zd ZdZdedB fddZdS )NoopAuthManagerz)Auth Manager implementation with no auth.r   Nc                 C   s   d S Nr   r   r   r   r   r   7   s   zNoopAuthManager.auth_header)r   r   r   r   r   r   r   r   r   r   r   4   s    r   c                   @   s0   e Zd ZdZdedefddZdefddZd	S )
BasicAuthManagerz=AuthManager implementation that supports basic password auth.usernamepasswordc                 C   s&   | d| }t |  | _d S )Nr   )base64	b64encodeencodedecode_token)r   r   r   credentialsr   r   r   __init__>   s   zBasicAuthManager.__init__r   c                 C      d| j  S )NBasic r#   r   r   r   r   r   B      zBasicAuthManager.auth_headerN)r   r   r   r   r   r%   r   r   r   r   r   r   ;   s    r   c                   @   s   e Zd ZU dZeed< edB ed< edB ed< edB ed< eeef dB ed< 				dded	edB d
edB dedB deeef dB f
ddZd
edefddZ	dddZ
defddZdS )LegacyOAuth2AuthManagerzLegacy OAuth2 AuthManager implementation.

    This class exists for backward compatibility, and will be removed in
    PyIceberg 1.0.0 in favor of OAuth2AuthManager.
    _sessionN	_auth_urlr#   _credential_optional_oauth_paramssessionauth_url
credentialinitial_tokenoptional_oauth_paramsc                 C   s*   || _ || _|| _|| _|| _|   d S r   )r+   r,   r#   r-   r.   _refresh_token)r   r/   r0   r1   r2   r3   r   r   r   r%   S   s   z LegacyOAuth2AuthManager.__init__r   c              
   C   s   t |v r|jt dd\}}nd |}}d||d}| jr"|| j | jd u r+td| jj| j|i | jjddid}z|	  W n t
y] } zt|ttd	 W Y d }~nd }~ww t|jjS )
N   )maxsplitclient_credentials)
grant_type	client_idclient_secretz1Cannot fetch access token from undefined auth_urlzContent-typez!application/x-www-form-urlencoded)urldataheaders)i  i  )COLONsplitr.   updater,   
ValueErrorr+   postr=   raise_for_statusr   r   r   r
   model_validate_jsontextaccess_token)r   r1   r9   r:   r<   responseexcr   r   r   _fetch_access_tokenb   s$   

z+LegacyOAuth2AuthManager._fetch_access_tokenc                 C   s    | j d ur| | j | _d S d S r   )r-   rI   r#   r   r   r   r   r4   z   s   
z&LegacyOAuth2AuthManager._refresh_tokenc                 C   r&   NBearer r(   r   r   r   r   r   ~   r)   z#LegacyOAuth2AuthManager.auth_header)NNNNr   N)r   r   r   r   r   __annotations__r   dictr%   rI   r4   r   r   r   r   r   r*   F   s2   
 

r*   c                   @   s   e Zd ZU dZeed< eed< eed< edB ed< eed< edB ed< edB ed	< eed
< ejed< 			ddededededB dededB fddZ	e
defddZdddZdefddZdS )OAuth2TokenProviderz=Thread-safe OAuth2 token provider with token refresh support.r9   r:   	token_urlNscoperefresh_margin
expires_inr#   _expires_at_lock<   c                 C   s>   || _ || _|| _|| _|| _|| _d | _d| _t	 | _
d S )Nr   )r9   r:   rP   rQ   rR   rS   r#   rT   	threadingLockrU   r   r9   r:   rP   rQ   rR   rS   r   r   r   r%      s   	zOAuth2TokenProvider.__init__r   c                 C   s6   | j  d| j }|d}t|d}d| S )Nr   zutf-8r'   )r9   r:   r!   r   r    r"   )r   credscreds_bytes	b64_credsr   r   r   _client_secret_header   s   

z)OAuth2TokenProvider._client_secret_headerc                 C   s   ddi}| j r| j |d< tj| j|d| jid}|  | }|d | _|d| j	}|d u r4t
dt | | j | _d S )	Nr8   r7   rQ   Authorization)r<   r=   rF   rS   zThe expiration time of the Token must be provided by the Server in the Access Token Response in `expires_in` field, or by the PyIceberg Client.)rQ   requestsrB   rP   r]   rC   jsonr#   getrS   rA   time	monotonicrR   rT   )r   r<   rG   resultrS   r   r   r   r4      s   

z"OAuth2TokenProvider._refresh_tokenc                 C   s^   | j " | jrt | jkr|   | jd u rtd| jW  d    S 1 s(w   Y  d S )Nz)Authorization token is None after refresh)rU   r#   rb   rc   rT   r4   rA   r   r   r   r   	get_token   s   
$zOAuth2TokenProvider.get_tokenNrV   NrL   )r   r   r   r   r   rM   intrW   rX   r%   r   r]   r4   re   r   r   r   r   rO      s>   
 


rO   c                   @   sP   e Zd ZdZ			ddededededB ded	edB fd
dZdefddZdS )OAuth2AuthManagerzLAuth Manager implementation that supports OAuth2 as defined in IETF RFC6749.NrV   r9   r:   rP   rQ   rR   rS   c                 C   s   t ||||||| _d S r   )rO   token_providerrY   r   r   r   r%      s   	
zOAuth2AuthManager.__init__r   c                 C   s   d| j   S rJ   )ri   re   r   r   r   r   r      s   zOAuth2AuthManager.auth_headerrf   )r   r   r   r   r   rg   r%   r   r   r   r   r   rh      s&    
rh   c                   @   s>   e Zd ZdZd
dedB dee dB fddZdefdd	ZdS )GoogleAuthManagerzDAn auth manager that is responsible for handling Google credentials.Ncredentials_pathscopesc              
   C   s   z
ddl }ddl}W n ty } ztd|d}~ww |r*|jj||d\| _}ntd |jj|d\| _}|jj	j
 | _dS )z
        Initialize GoogleAuthManager.

        Args:
            credentials_path: Optional path to Google credentials JSON file.
            scopes: Optional list of OAuth2 scopes.
        r   Nz>Google Auth libraries not found. Please install 'google-auth'.)rl   z,Using Google Default Application Credentials)google.authgoogle.auth.transport.requestsImportErrorauthload_credentials_from_filer$   loggerinfodefault	transportr_   Request_auth_request)r   rk   rl   googlee_r   r   r   r%      s   

zGoogleAuthManager.__init__r   c                 C   s   | j | j d| j j S rJ   )r$   refreshrw   tokenr   r   r   r   r      s   zGoogleAuthManager.auth_header)NN)r   r   r   r   r   listr%   r   r   r   r   r   rj      s     rj   c                   @   sX   e Zd ZdZdZ	ddee dB defddZdd	d
Z	defddZ
defddZdS )EntraAuthManagera  Auth Manager implementation that supports Microsoft Entra ID (Azure AD) authentication.

    This manager uses the Azure Identity library's DefaultAzureCredential which automatically
    tries multiple authentication methods including environment variables, managed identity,
    and Azure CLI.

    See https://learn.microsoft.com/en-us/azure/developer/python/sdk/authentication/credential-chains
    for more details on DefaultAzureCredential.
    z"https://storage.azure.com/.defaultNrl   credential_kwargsc              
   K   sl   zddl m} W n ty } ztd|d}~ww |p| jg| _t | _d| _d| _	|di || _
dS )a  
        Initialize EntraAuthManager.

        Args:
            scopes: List of OAuth2 scopes. Defaults to ["https://storage.azure.com/.default"].
            **credential_kwargs: Arguments passed to DefaultAzureCredential.
                Supported authentication methods:
                - Environment Variables: Set AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET
                - Managed Identity: Works automatically on Azure; for user-assigned, pass managed_identity_client_id
                - Azure CLI: Works automatically if logged in via `az login`
                - Workload Identity: Works automatically in AKS with workload identity configured  # codespell:ignore aks
        r   )DefaultAzureCredentialzXAzure Identity library not found. Please install with: pip install pyiceberg[entra-auth]Nr   )azure.identityr   ro   DEFAULT_SCOPE_scopesrW   rX   rU   r#   rT   r-   )r   rl   r   r   ry   r   r   r   r%   	  s   

zEntraAuthManager.__init__r   c                 C   s&   | j j| j }|j| _|jd | _dS )z$Refresh the access token from Azure.rV   N)r-   re   r   r|   r#   
expires_onrT   )r   r|   r   r   r   r4   %  s   zEntraAuthManager._refresh_tokenc                 C   s^   | j " | jrt | jkr|   | jdu rtd| jW  d   S 1 s(w   Y  dS )z2Get a valid access token, refreshing if necessary.Nz#Failed to obtain Entra access token)rU   r#   rb   rT   r4   rA   r   r   r   r   
_get_token,  s   
$zEntraAuthManager._get_tokenc                 C   s   d|    S )z@Return the Authorization header value with a valid Bearer token.rK   )r   r   r   r   r   r   5  s   zEntraAuthManager.auth_headerr   rL   )r   r   r   r   r   r}   r   r   r%   r4   r   r   r   r   r   r   r~      s    



	r~   c                   @   s0   e Zd ZdZdefddZdedefddZd	S )
AuthManagerAdaptera  A `requests.auth.AuthBase` adapter for integrating an `AuthManager` into a `requests.Session`.

    This adapter automatically attaches the appropriate Authorization header to every request.
    This adapter is useful when working with `requests.Session.auth`
    and allows reuse of authentication strategies defined by `AuthManager`.
    This AuthManagerAdapter is only intended to be used against the REST Catalog
    Server that expects the Authorization Header.
    auth_managerc                 C   s
   || _ dS )z
        Initialize AuthManagerAdapter.

        Args:
            auth_manager (AuthManager): An instance of an AuthManager subclass.
        N)r   )r   r   r   r   r   r%   D  s   
zAuthManagerAdapter.__init__requestr   c                 C   s   | j   }r||jd< |S )a  
        Modify the outgoing request to include the Authorization header.

        Args:
            request (requests.PreparedRequest): The HTTP request being prepared.

        Returns:
            requests.PreparedRequest: The modified request with Authorization header.
        r^   )r   r   r=   )r   r   r   r   r   r   __call__M  s   

zAuthManagerAdapter.__call__N)r   r   r   r   r   r%   r   r   r   r   r   r   r   :  s    		r   c                   @   sf   e Zd ZU i Zeeed f ed< ededed ddfddZ	ed	ed
eee
f defddZdS )AuthManagerFactoryr   	_registrynameauth_manager_classr   Nc                 C   s   || j |< dS )a  
        Register a string name to a known AuthManager class.

        Args:
            name (str): unique name like 'oauth2' to register the AuthManager with
            auth_manager_class (Type["AuthManager"]): Implementation of AuthManager

        Returns:
            None
        N)r   )clsr   r   r   r   r   register_  s   zAuthManagerFactory.registerclass_or_nameconfigc              
   C   sx   || j v r| j | }n*z|dd\}}t|}t||}W n ty4 } z	td| d|d}~ww |di |S )a{  
        Create an AuthManager by name or fully-qualified class path.

        Args:
            class_or_name (str): Either a name like 'oauth2' or a full class path like 'my.module.CustomAuthManager'
            config (Dict[str, Any]): Configuration passed to the AuthManager constructor

        Returns:
            AuthManager: An instantiated AuthManager subclass
        .r5   z&Could not load AuthManager class for ''Nr   )r   rsplit	importlibimport_modulegetattr	ExceptionrA   )r   r   r   manager_clsmodule_path
class_namemoduleerrr   r   r   createm  s   

zAuthManagerFactory.create)r   r   r   r   rN   r   typerM   classmethodr   r   r   r   r   r   r   r   r   \  s   
 $r   noopbasiclegacyoauth2oauth2rx   entra)'r   r   loggingrW   rb   abcr   r   	functoolsr   typingr   r_   r   r   r   requests.authr	   pyiceberg.catalog.rest.responser
   r   pyiceberg.exceptionsr   AUTH_MANAGERr>   	getLoggerr   rr   r   r   r   r*   rO   rh   rj   r~   r   r   r   r   r   r   r   <module>   s@   
<D>"*