o
    ɶd-                     @   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	m
Z
 d dlmZmZmZmZ ddlmZ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ZeeZdZ dddZ!dd Z"dd Z#G dd dej$j%Z&G dd dej'j(Z)G dd de)Z*dS )    )absolute_importN)six)record_body_position_for_rewindrewind_body,back_up_body_calculate_stream_content_lengthread_stream_for_signing   )httpsig_cffirequests)InvalidPrivateKeyMissingPrivateKeyPassphrase)UnsupportedAlgorithm)default_backend)serialization1c                 C   sP   t j| } tj| dd}|  }W d    n1 sw   Y  t||S )Nrb)mode)ospath
expanduserioopenreadstripload_private_key)filenamepass_phrasefZprivate_key_data r   .usr/lib/python3.10/site-packages/oci/signer.pyload_private_key_from_file   s
   
r    c                 C   s   t | tjr| d} t |tjr|d}t }z	tj| ||dW S  ty;   |du r1tdtj| d|d Y S  t	yf   tj
tjtjfD ]}z|| |d W td t	tfya   Y qIw tdw )zLoads a private key that may use a pass_phrase.

    Tries to correct or diagnose common errors:

    - provided pass_phrase but didn't need one
    - provided a public key
    ascii)backendNz'The provided key requires a passphrase.zEAuthentication requires a private key, but a public key was provided.zOThe provided key is not a private key, or the provided passphrase is incorrect.)
isinstancer   Z	text_typeencoder   r   Zload_pem_private_key	TypeErrorr   
ValueErrorZload_der_public_keyZload_pem_public_keyZload_ssh_public_keyr   r   )Zsecretr   r"   loaderr   r   r   r   $   s0   

r   c                 C   s  | j dtjjdd | j dtjjj	| j
j t| jds't| jdr.| j dd | j dd	 |rd
| j vr|r| jpBd}t }t|tjrc|d}| j dtt| || ndt|ttfrp|| nWt|dszt|drt|\}}|rt||}|dkrtd| j dt| t||}|stdn#td t|}	|	d| _||	d | j dt|	d |rt !|" }
|
#d}|| j d
< d S d S d S d S d S )NdateT)usegmthostbufferr   content-typezapplication/octet-streamzapplication/jsonx-content-sha256 zutf-8content-lengthznUnable to read stream for signing! Please sign the stream yourself by using the custom header x-content-sha256z,Unable to rewind request body while signing!z=Stream cannot be rewound, trying to backup and sign the body!Zbyte_contentcontent_length)$headers
setdefaultemailutils
formatdater   movesurllibparseurlparseurlnetlochasattrbodyhashlibsha256r#   Zstring_typesr$   strlenupdatebytes	bytearrayr   r   IOErrorr   loggerwarningr   getbase64	b64encodedigestdecode)request	sign_bodyenforce_content_headersr>   mZis_body_rewindableZoriginal_positionr1   Zis_rewind_successstreamZbase64digestZbase64stringr   r   r   inject_missing_headersY   sT   





rS   c                   @   s"   e Zd ZdZ	 dd Zdd ZdS )_PatchedHeaderSignerzTSignature algorithm="rsa-sha256",headers="{}",keyId="{}",signature="%s",version="{}"c                 C   sV   d| _ d| _d | _tjj| j | _|| _| j | _	|| _
| jd||t| _d S )Nrsar@    )Zsign_algorithmZhash_algorithm_hashr	   r5   ZHASHESZ_rsahash_rsa_private
public_key_rsa_publicr2   HEADER_SIGNER_TEMPLATEformatjoinSIGNATURE_VERSIONsignature_template)selfkey_idprivate_keyr2   r   r   r   __init__   s   z_PatchedHeaderSigner.__init__c                 C   s6   d | _ || _| j | _| jd| j|t| _	d S )NrV   )
rW   rX   rY   rZ   r[   r\   r]   r2   r^   r_   )r`   ra   rb   r   r   r   reset_signer   s   z!_PatchedHeaderSigner.reset_signerN)__name__
__module____qualname__r[   rc   rd   r   r   r   r   rT      s
    rT   c                   @   s<   e Zd Zdd Zdd ZdddZddd	Zed
d ZdS )AbstractBaseSignerc                 C   s(   t |||d| _t |||| d| _d S )N)ra   rb   r2   )rT   _basic_signer_body_signer)r`   api_keyrb   generic_headersbody_headersr   r   r   create_signers   s   z!AbstractBaseSigner.create_signersc                 C   s$   |j  }|dvrtd|d S )N)rI   headdeleteputpostpatchz&Don't know how to sign request verb {})methodlowerr&   r\   )r`   rN   verbr   r   r   validate_request   s   
z#AbstractBaseSigner.validate_requestTc                 C   sz   |j  }|dv }|r|r| j}n
| j}|jdd  t||| |j|jtj	j
j|jj|j |jd}|j| |S )N)rq   rr   rs   zTransfer-Encoding)r*   rt   r   )rt   ru   rj   ri   r2   poprS   signr   r7   r8   r9   r:   r;   r<   Zpath_urlrC   )r`   rN   rP   rv   rO   ZsignerZsigned_headersr   r   r   do_request_sign   s   
z"AbstractBaseSigner.do_request_signc                 C   s   |  | | ||S N)rw   rz   )r`   rN   rP   r   r   r   __call__   s   
zAbstractBaseSigner.__call__c                 C   s   t j| ddS )NF)rP   )	functoolspartial)r`   r   r   r   without_content_headers   s   z*AbstractBaseSigner.without_content_headersN)T)	re   rf   rg   rn   rw   rz   r|   propertyr   r   r   r   r   rh      s    

rh   c                   @   s&   e Zd ZdZdddZedd ZdS )Signera  
    A requests auth instance that can be reused across requests. This signer is intended to be used
    when signing requests for a given user and it requires that user's ID, their private key
    and cerificate fingerprint.

    The private key can be sourced from a file (private_key_file_location) or the PEM string can be
    provided directly (private_key_content).

    The headers to be signed by this signer are not customizable.

    You can manually sign calls by creating an instance of the signer, and
    providing it as the ``auth`` argument to Requests functions:

    .. code-block:: python

        import requests
        from oci import Signer

        auth = Signer(...)
        resp = requests.get("https://...", auth=auth)


    Nc           	      C   s\   |d | d | | _ |rt||| _nt||| _g d}g d}| | j | j|| d S )N/)r(   z(request-target)r*   )r/   r,   r-   )rk   r   rb   r    rn   )	r`   tenancyuserfingerprintprivate_key_file_locationr   private_key_contentrl   rm   r   r   r   rc      s   zSigner.__init__c              	   C   sD   ddl m} ||  t| d | d | d | d | d| dd	S )
Nr   )validate_configr   r   r   Zkey_filer   Zkey_content)r   r   r   )configr   r   rI   )r   r   r   r   r   from_config  s   zSigner.from_config)NN)re   rf   rg   __doc__rc   staticmethodr   r   r   r   r   r      s
    
r   r{   )+
__future__r   rJ   email.utilsr4   r?   r   r}   r   Zoci._vendorr   Zoci.utilr   r   r   r   _vendorr	   r
   
exceptionsr   r   Zcryptography.exceptionsr   Zcryptography.hazmat.backendsr   Zcryptography.hazmat.primitivesr   logging	getLoggerre   rG   r^   r    r   rS   ry   ZHeaderSignerrT   ZauthZAuthBaserh   r   r   r   r   r   <module>   s.   

55!1