o
    RDiP>                     @  s  d dl mZ d dlZd dl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 d dlmZ d dl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mZ ee Z!edZ"G dd deZ#G dd de$Z%eG dd dZ&d1d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"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)Z0G d+d, d,e(Z1G d-d. d.e(Z2G d/d0 d0e(Z3dS )2    )annotationsN)ABCabstractmethod)	dataclass)Enum)Path)AnyTypeVar   )IS_LINUXIS_MACOS
IS_WINDOWS)FileLockFileLockError)installed_keyringkeyringTc                   @  s    e Zd ZdZdZdZdZdZdS )	TokenTypeaj  Types of credentials that can be cached to avoid repeated authentication.

    - ID_TOKEN: SSO identity token from external browser/Okta authentication
    - MFA_TOKEN: Multi-factor authentication token to skip MFA prompts
    - OAUTH_ACCESS_TOKEN: Short-lived OAuth access token
    - OAUTH_REFRESH_TOKEN: Long-lived OAuth token to obtain new access tokens
    ID_TOKEN	MFA_TOKENOAUTH_ACCESS_TOKENOAUTH_REFRESH_TOKENN)__name__
__module____qualname____doc__r   r   r   r    r   r   X/var/www/Datamplify/venv/lib/python3.10/site-packages/snowflake/connector/token_cache.pyr      s    r   c                   @     e Zd ZdS )_InvalidTokenKeyErrorNr   r   r   r   r   r   r   r   '       r   c                   @  s:   e Zd ZU ded< ded< ded< dddZdd	d
ZdS )TokenKeystruserhostr   	tokenTypereturnc                 C  sP   t | jdkrtdt | jdkrtd| j  d| j  d| jj S )Nr   zInvalid key, host is emptyzInvalid key, user is empty:)lenr%   r   r$   upperr&   valueselfr   r   r   
string_key1   s
   $zTokenKey.string_keyc                 C  s&   t  }||  jdd | S )Nutf-8)encoding)hashlibsha256updater.   encode	hexdigest)r-   mr   r   r   hash_key8   s   zTokenKey.hash_keyN)r'   r#   )r   r   r   __annotations__r.   r7   r   r   r   r   r"   +   s   
 
r"   warningr#   r'   Nonec                 C  s    t |  td|  tjd d S )Nz	Warning: )file)loggerr9   printsysstderr)r9   r   r   r   _warn>   s   
r@   c                   @  sJ   e Zd ZdZeddddZedddZedddZedddZ	dS )
TokenCachea  Secure storage for authentication credentials to avoid repeated login prompts.

    Platform-specific implementations:
    - macOS/Windows: Uses OS keyring (Keychain/Credential Manager) via 'keyring' library
    - Linux: Uses encrypted JSON file in ~/.cache/snowflake/ with 0o600 permissions
    - Fallback: NoopTokenCache (no caching) if secure storage unavailable

    Tokens are keyed by (host, user, token_type) to support multiple accounts.
    Fskip_file_permissions_checkboolr'   c                 C  sH   t strtstd t S t S tr"t| }|r|S td t S d S )Na.  Dependency 'keyring' is not installed, cannot cache id token. You might experience multiple authentication pop ups while using ExternalBrowser/OAuth/MFA Authenticator. To avoid this please install keyring module using the following command:
 pip install snowflake-connector-python[secure-local-storage]zFailed to initialize file based token cache. You might experience multiple authentication pop ups while using ExternalBrowser/OAuth/MFA Authenticator.)	r   r   r   r@   NoopTokenCacheKeyringTokenCacher   FileTokenCachemake)rB   cacher   r   r   rG   N   s    
zTokenCache.makekeyr"   tokenr#   r:   c                 C     d S Nr   r-   rI   rJ   r   r   r   storef      zTokenCache.store
str | Nonec                 C  rK   rL   r   r-   rI   r   r   r   retrievej   rO   zTokenCache.retrievec                 C  rK   rL   r   rQ   r   r   r   removen   rO   zTokenCache.removeNF)rB   rC   r'   rA   rI   r"   rJ   r#   r'   r:   rI   r"   r'   rP   rI   r"   r'   r:   )
r   r   r   r   staticmethodrG   r   rN   rR   rS   r   r   r   r   rA   C   s    
rA   c                   @  r   )_FileTokenCacheErrorNr    r   r   r   r   rY   s   r!   rY   c                   @  r   )_OwnershipErrorNr    r   r   r   r   rZ   w   r!   rZ   c                   @  r   )_PermissionsTooWideErrorNr    r   r   r   r   r[   {   r!   r[   c                   @  r   )_CacheDirNotFoundErrorNr    r   r   r   r   r\      r!   r\   c                   @  r   )_InvalidCacheDirErrorNr    r   r   r   r   r]      r!   r]   c                   @  r   )_MalformedCacheFileErrorNr    r   r   r   r   r^      r!   r^   c                   @  r   )_CacheFileReadErrorNr    r   r   r   r   r_      r!   r_   c                   @  r   )_CacheFileWriteErrorNr    r   r   r   r   r`      r!   r`   c                   @  s   e Zd ZdZed/d0ddZ	d/d1ddZd2ddZd3ddZd4ddZ	d5ddZ
d5ddZd6ddZd7d"d#Zed/d8d%d&Ze	d/d9d'd(Zd:d,d-Zd.S );rF   a  Linux implementation: stores tokens in JSON file with strict security.

    Cache location (in priority order):
    1. $SF_TEMPORARY_CREDENTIAL_CACHE_DIR/credential_cache_v1.json
    2. $XDG_CACHE_HOME/snowflake/credential_cache_v1.json
    3. $HOME/.cache/snowflake/credential_cache_v1.json

    Security: File must have 0o600 permissions and be owned by current user.
    Uses file locks to prevent concurrent access corruption.
    FrB   rC   r'   FileTokenCache | Nonec                 C  s2   t | }|d u rttd d S t || dS )NzfFailed to find suitable cache directory for token cache. File based token cache initialization failed.rB   )rF   find_cache_dirlogging	getLoggerr   debug)rB   	cache_dirr   r   r   rG      s   

zFileTokenCache.makerg   r   r:   c                 C  s   t t| _|| _|| _d S rL   )rd   re   r   r<   rg   _skip_file_permissions_check)r-   rg   rB   r   r   r   __init__   s   
zFileTokenCache.__init__rI   r"   rJ   r#   c              
   C  s  z4t | j| j t|   |  }||d | < | | W d    W d S 1 s-w   Y  W d S  t	yP } z| j
d| W Y d }~d S d }~w tyk } z| j
d| W Y d }~d S d }~w ty } z| j
d| W Y d }~d S d }~ww )NtokenszFailed to store token: e=Unable to lock file lock: e=Failed to produce token key e=)rF   validate_cache_dirrg   rh   r   	lock_file_read_cache_filer7   _write_cache_filerY   r<   errorr   r   )r-   rI   rJ   rH   er   r   r   rN      s&   &   zFileTokenCache.storerP   c              
   C  s(  zAt | j| j t|  ( |  }|d | d }t	|t
r-|W  d    W S 	 W d    W d S 1 s:w   Y  W d S  ty] } z| jd| W Y d }~d S d }~w tyx } z| jd| W Y d }~d S d }~w ty } z| jd| W Y d }~d S d }~ww )Nrj   zFailed to retrieve token: e=rk   rl   )rF   rm   rg   rh   r   rn   ro   getr7   
isinstancer#   rY   r<   rq   r   r   )r-   rI   rH   rJ   rr   r   r   r   rR      s2   
(zFileTokenCache.retrievec              
   C  s  z6t | j| j t|   |  }|d | d  | 	| W d    W d S 1 s/w   Y  W d S  t
yR } z| jd| W Y d }~d S d }~w tym } z| jd| W Y d }~d S d }~w ty } z| jd| W Y d }~d S d }~ww )Nrj   zFailed to remove token: e=rk   rl   )rF   rm   rg   rh   r   rn   ro   popr7   rp   rY   r<   rq   r   r   )r-   rI   rH   rr   r   r   r   rS      s&   &   zFileTokenCache.removec                 C  
   | j d S )Nzcredential_cache_v1.jsonrg   r,   r   r   r   
cache_file      
zFileTokenCache.cache_filec                 C  rv   )Nzcredential_cache_v1.json.lckrw   r,   r   r   r   rn      ry   zFileTokenCache.lock_filedict[str, dict[str, Any]]c              
   C  s  d}di i}zz3t |  t j}| js| |d t |dt j}t |dt j t 	||}t
t|d}W nw tyN   | j|   d Y nd t
jjyq } z| jd|   d|jj  W Y d }~nEd }~w ty } z| jd	|   d|jj  W Y d }~n$d }~w ty } z| jd
|   d|  W Y d }~nd }~ww W |dkrt | n|dkrt | w w d|vst|d tsi |d< |S )Nrj     r   r/   z
 not foundz+Failed to decode json read from cache file z: z,Failed to decode utf-8 read from cache file zFailed to read cache file )osopenrx   O_RDONLYrh   _ensure_permissionslseekSEEK_ENDSEEK_SETreadjsonloadscodecsdecodeFileNotFoundErrorr<   rf   decoderJSONDecodeErrorr9   	__class__r   UnicodeErrorOSErrorclosert   dict)r-   fd	json_datasizedatarr   r   r   r   ro      sH   (
zFileTokenCache._read_cache_filer   r   c              
   C  s   d}| j d|    zFz4t|  tjtjB tjB d}| js(| 	|d t
|tt|d |W W |dkrBt| S S  tyS } ztd|d }~ww |dkr^t| w w )Nr{   zWriting cache file r|   r/   r   zFailed to write cache file)r<   rf   rx   r}   r~   O_WRONLYO_CREATO_TRUNCrh   r   writer   r4   r   dumpsr   r   r`   )r-   r   r   rr   r   r   r   rp     s(   
z FileTokenCache._write_cache_filePath | Nonec                   sP   dfdd  fd	d
 fdd
 fdd
g}|D ]}| }|r%|  S qd S )Nenv_varr#   subpath_segments	list[str]r'   r   c              
     s  t | }|d u rtd|  d d S t|}t|dkra| s/tdt| d d S | s@tdt| d d S |d d D ]}|| }|j	dd	d
 qF||d  }|j	ddd
 z	t
|  |W S  ty } ztdt| d| d W Y d }~d S d }~ww )NzEnvironment variable z0 not set. Skipping it in cache directory lookup.r   zPath z7 does not exist. Skipping it in cache directory lookup.z; is not a directory. Skipping it in cache directory lookup.r{   Ti  )exist_okmode  z&Cache directory validation failed for z due to error 'z)'. Skipping it in cache directory lookup.)r}   getenvr<   rf   r   r)   existsr#   is_dirmkdirrF   rm   rY   r@   )r   r   env_val	directorysubpathrr   rb   r   r   lookup_env_dir"  sF   

z5FileTokenCache.find_cache_dir.<locals>.lookup_env_dirc                     s
    dg S )N!SF_TEMPORARY_CREDENTIAL_CACHE_DIRr   r   r   r   r   <lambda>L  s   
 z/FileTokenCache.find_cache_dir.<locals>.<lambda>c                     s    ddgS )NXDG_CACHE_HOME	snowflaker   r   r   r   r   r   M  s    c                     s    dddgS )NHOMEz.cacher   r   r   r   r   r   r   N  s    )r   r#   r   r   r'   r   r   )rB   lookup_functionslfrg   r   )r   rB   r   rc      s   
*

zFileTokenCache.find_cache_dirc                 C  s   zO|   }| d u rtdt |jstd|  d|sJt |j}|dkr3td|  d|ddt }|j	|krMt
d|  d| d	|j	 W d S W d S  ty^   td|  d
w )NzCache dir was not foundz
Cache dir z is not a directoryr    has incorrect permissions. oz != 0700 has incorrect owner.  != z was not found. Failed to stat.)statr\   S_ISDIRst_moder]   S_IMODEr[   r}   geteuidst_uidrZ   r   )rg   rB   statinfopermissionseuidr   r   r   rm   X  s0   

z!FileTokenCache.validate_cache_dirr   intr   c                 C  s   z<t |}t|j}||kr!td|   d|dd|dt  }|j|kr:t	d|   d| d|j W d S  t
yF   Y d S w )NzCache file r   r   r   r   )r}   fstatr   r   r   r[   rx   r   r   rZ   r   )r-   r   r   r   actual_permissionsr   r   r   r   r   w  s    

z"FileTokenCache._ensure_permissionsNrT   )rB   rC   r'   ra   )rg   r   rB   rC   r'   r:   rU   rV   rW   )r'   r   )r'   rz   )r   r   )rB   rC   r'   r   )rg   r   rB   rC   r'   r:   )r   r   r   r   r'   r:   )r   r   r   r   rX   rG   ri   rN   rR   rS   rx   rn   ro   rp   rc   rm   r   r   r   r   r   rF      s&    






 7rF   c                   @  s8   e Zd ZdZdddZdd
dZdddZdddZdS )rE   a  macOS/Windows implementation: uses OS-native secure credential storage.

    - macOS: Stores tokens in Keychain
    - Windows: Stores tokens in Windows Credential Manager

    Tokens are stored with service="{HOST}:{USER}:{TOKEN_TYPE}" and username="{USER}".
    r'   r:   c                 C  s   t t| _d S rL   )rd   re   r   r<   r,   r   r   r   ri     s   zKeyringTokenCache.__init__rI   r"   rJ   r#   c              
   C  s   zt | |j | W d S  ty/ } z| jd|j d| W Y d }~d S d }~w t j	j
yL } z| jdt| W Y d }~d S d }~ww )NCould not retrieve  from keyring, e=z'Could not store id_token to keyring, %s)r   set_passwordr.   r$   r*   r   r<   rq   r&   errorsKeyringErrorr#   )r-   rI   rJ   rr   ker   r   r   rN     s   
( zKeyringTokenCache.storerP   c              
   C  s   zt | |j W S  t jjy/ } z| jd	|j
jt| W Y d }~d S d }~w tyN } z| jd|j
 d| W Y d }~d S d }~ww )Nz.Could not retrieve {} from secure storage : {}r   r   )r   get_passwordr.   r$   r*   r   r   r<   rq   formatr&   r+   r#   r   )r-   rI   r   rr   r   r   r   rR     s    (zKeyringTokenCache.retrievec              
   C  s   zt | |j  W d S  ty. } z| jd|j d| W Y d }~d S d }~w t	yG } z| jd| W Y d }~d S d }~ww )Nr   r   z4Failed to delete credential in the keyring: err=[%s])
r   delete_passwordr.   r$   r*   r   r<   rq   r&   	Exception)r-   rI   rr   exr   r   r   rS     s"   
$zKeyringTokenCache.removeN)r'   r:   rU   rV   rW   )r   r   r   r   ri   rN   rR   rS   r   r   r   r   rE     s    


rE   c                   @  s*   e Zd ZdddZdd
dZdddZdS )rD   rI   r"   rJ   r#   r'   r:   c                 C  rK   rL   r   rM   r   r   r   rN        zNoopTokenCache.storerP   c                 C  rK   rL   r   rQ   r   r   r   rR     r   zNoopTokenCache.retrievec                 C  rK   rL   r   rQ   r   r   r   rS     r   zNoopTokenCache.removeNrU   rV   rW   )r   r   r   rN   rR   rS   r   r   r   r   rD     s    

rD   )r9   r#   r'   r:   )4
__future__r   r   r1   r   rd   r}   r   r>   abcr   r   dataclassesr   enumr   pathlibr   typingr   r	   compatr   r   r   	file_lockr   r   optionsr   r   re   r   r<   r   r   r   r   r"   r@   rA   rY   rZ   r[   r\   r]   r^   r_   r`   rF   rE   rD   r   r   r   r   <module>   sH    

0 y6