U
    k7g#E                     @   s   d Z ddlZddlZddlmZ ddlmZ ddl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d	lmZ dd
lmZ dZdZejdfddZG dd dejejejZG dd dejZdS )a  Google Cloud Impersonated credentials.

This module provides authentication for applications where local credentials
impersonates a remote service account using `IAM Credentials API`_.

This class can be used to impersonate a service account as long as the original
Credential object has the "Service Account Token Creator" role on the target
service account.

    .. _IAM Credentials API:
        https://cloud.google.com/iam/credentials/reference/rest/
    N)datetime)_exponential_backoff)_helpers)credentials)
exceptions)iam)jwt)metricsz*Unable to acquire impersonated credentialsi  c              
   C   s   |pt jtj||}t|d}| |d||d}t	|j
drR|j
dn|j
}|jtjkrptt|z,t|}	|	d }
t|	d d}|
|fW S  ttfk
r } ztdt|}||W 5 d	}~X Y nX d	S )
a  Makes a request to the Google Cloud IAM service for an access token.
    Args:
        request (Request): The Request object to use.
        principal (str): The principal to request an access token for.
        headers (Mapping[str, str]): Map of headers to transmit.
        body (Mapping[str, str]): JSON Payload body for the iamcredentials
            API call.
        iam_endpoint_override (Optiona[str]): The full IAM endpoint override
            with the target_principal embedded. This is useful when supporting
            impersonation with regional endpoints.

    Raises:
        google.auth.exceptions.TransportError: Raised if there is an underlying
            HTTP connection error
        google.auth.exceptions.RefreshError: Raised if the impersonated
            credentials are not available.  Common reasons are
            `iamcredentials.googleapis.com` is not enabled or the
            `Service Account Token Creator` is not assigned
    utf-8POST)urlmethodheadersbodydecodeZaccessTokenZ
expireTimez%Y-%m-%dT%H:%M:%SZz6{}: No access token or invalid expiration in response.N)r   Z_IAM_ENDPOINTreplacer   DEFAULT_UNIVERSE_DOMAINformatjsondumpsencodehasattrdatar   statushttp_clientOKr   RefreshError_REFRESH_ERRORloadsr   strptimeKeyError
ValueError)request	principalr   r   universe_domainiam_endpoint_overrideZiam_endpointresponseZresponse_bodyZtoken_responsetokenexpiryZ
caught_excnew_exc r*   H/tmp/pip-unpacked-wheel-x0z3pcuk/google/auth/impersonated_credentials.py_make_iam_token_request0   s6    
 


r,   c                       s   e Zd ZdZdeddf fdd	Zdd Zee	j
dd Zd	d
 Zdd Zedd Zedd Zedd Zedd Zee	j
dd Zdd Zee	jdd Zee	jdddZ  ZS )Credentialsa  This module defines impersonated credentials which are essentially
    impersonated identities.

    Impersonated Credentials allows credentials issued to a user or
    service account to impersonate another. The target service account must
    grant the originating credential principal the
    `Service Account Token Creator`_ IAM role:

    For more information about Token Creator IAM role and
    IAMCredentials API, see
    `Creating Short-Lived Service Account Credentials`_.

    .. _Service Account Token Creator:
        https://cloud.google.com/iam/docs/service-accounts#the_service_account_token_creator_role

    .. _Creating Short-Lived Service Account Credentials:
        https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials

    Usage:

    First grant source_credentials the `Service Account Token Creator`
    role on the target account to impersonate.   In this example, the
    service account represented by svc_account.json has the
    token creator role on
    `impersonated-account@_project_.iam.gserviceaccount.com`.

    Enable the IAMCredentials API on the source project:
    `gcloud services enable iamcredentials.googleapis.com`.

    Initialize a source credential which does not have access to
    list bucket::

        from google.oauth2 import service_account

        target_scopes = [
            'https://www.googleapis.com/auth/devstorage.read_only']

        source_credentials = (
            service_account.Credentials.from_service_account_file(
                '/path/to/svc_account.json',
                scopes=target_scopes))

    Now use the source credentials to acquire credentials to impersonate
    another service account::

        from google.auth import impersonated_credentials

        target_credentials = impersonated_credentials.Credentials(
          source_credentials=source_credentials,
          target_principal='impersonated-account@_project_.iam.gserviceaccount.com',
          target_scopes = target_scopes,
          lifetime=500)

    Resource access is granted::

        client = storage.Client(credentials=target_credentials)
        buckets = client.list_buckets(project='your_project')
        for bucket in buckets:
          print(bucket.name)
    Nc                    s   t t|   t|| _t| jtjrX| jt	j
| _t| jdrX| jjrX| jd |j| _|| _|| _|| _|pxt| _d| _t | _|| _|| _d| _dS )aL  
        Args:
            source_credentials (google.auth.Credentials): The source credential
                used as to acquire the impersonated credentials.
            target_principal (str): The service account to impersonate.
            target_scopes (Sequence[str]): Scopes to request during the
                authorization grant.
            delegates (Sequence[str]): The chained list of delegates required
                to grant the final access_token.  If set, the sequence of
                identities must have "Service Account Token Creator" capability
                granted to the prceeding identity.  For example, if set to
                [serviceAccountB, serviceAccountC], the source_credential
                must have the Token Creator role on serviceAccountB.
                serviceAccountB must have the Token Creator on
                serviceAccountC.
                Finally, C must have Token Creator on target_principal.
                If left unset, source_credential must have that role on
                target_principal.
            lifetime (int): Number of seconds the delegated credential should
                be valid for (upto 3600).
            quota_project_id (Optional[str]): The project ID used for quota and billing.
                This project may be different from the project used to
                create the credentials.
            iam_endpoint_override (Optiona[str]): The full IAM endpoint override
                with the target_principal embedded. This is useful when supporting
                impersonation with regional endpoints.
        _create_self_signed_jwtN)superr-   __init__copy_source_credentials
isinstancer   Scopedwith_scopesr   Z
_IAM_SCOPEr   Z_always_use_jwt_accessr.   r$   Z_universe_domain_target_principal_target_scopes
_delegates_DEFAULT_TOKEN_LIFETIME_SECS	_lifetimer'   r   utcnowr(   _quota_project_id_iam_endpoint_override_cred_file_path)selfZsource_credentialstarget_principaltarget_scopes	delegateslifetimequota_project_idr%   	__class__r*   r+   r0      s*    &


zCredentials.__init__c                 C   s   t jS N)r	   ZCRED_TYPE_SA_IMPERSONATEr?   r*   r*   r+   _metric_header_for_usage   s    z$Credentials._metric_header_for_usagec                 C   s   |  | d S rG   )_update_token)r?   r"   r*   r*   r+   refresh   s    zCredentials.refreshc                 C   s   | j jtjjks | j jtjjkr,| j | | j| jt	| j
d d}ddtjt i}| j | t|| j||| j| jd\| _| _dS )zUpdates credentials with a new access_token representing
        the impersonated account.

        Args:
            request (google.auth.transport.requests.Request): Request object
                to use for refreshing credentials.
        s)rB   ZscoperC   Content-Typeapplication/json)r"   r#   r   r   r$   r%   N)r2   Ztoken_stater   Z
TokenStateZSTALEINVALIDrK   r8   r7   strr:   r	   API_CLIENT_HEADERZ&token_request_access_token_impersonateapplyr,   r6   r$   r=   r'   r(   )r?   r"   r   r   r*   r*   r+   rJ      s.      zCredentials._update_tokenc           
      C   s   ddl m} tjtj| j| j	}t
|d| jd}ddi}|| j}zlt }|D ]Z}|j|||d}	|	jtjkrq^|	jtjkrtd|	 t
|	 d	   W S W 5 |  X td
d S )Nr   AuthorizedSessionr
   )payloadrB   rM   rN   )r   r   r   zError calling sign_bytes: {}Z
signedBlobz#exhausted signBlob endpoint retries)google.auth.transport.requestsrT   r   Z_IAM_SIGN_ENDPOINTr   r   r   r$   r   r6   base64	b64encoder   r8   r2   closer   ZExponentialBackoffpoststatus_codeZIAM_RETRY_CODESr   r   r   ZTransportErrorr   	b64decode)
r?   messagerT   iam_sign_endpointr   r   authed_sessionretries_r&   r*   r*   r+   
sign_bytes  s:     
  
zCredentials.sign_bytesc                 C   s   | j S rG   r6   rH   r*   r*   r+   signer_emailA  s    zCredentials.signer_emailc                 C   s   | j S rG   rc   rH   r*   r*   r+   service_account_emailE  s    z!Credentials.service_account_emailc                 C   s   | S rG   r*   rH   r*   r*   r+   signerI  s    zCredentials.signerc                 C   s   | j  S rG   )r7   rH   r*   r*   r+   requires_scopesM  s    zCredentials.requires_scopesc                 C   s   | j r| j d| jdS d S )Nzimpersonated credentials)Zcredential_sourceZcredential_typer#   )r>   r6   rH   r*   r*   r+   get_cred_infoQ  s    zCredentials.get_cred_infoc              	   C   s2   | j | j| j| j| j| j| j| jd}| j|_|S )N)r@   rA   rB   rC   rD   r%   )	rF   r2   r6   r7   r8   r:   r<   r=   r>   )r?   credr*   r*   r+   
_make_copy[  s    	zCredentials._make_copyc                 C   s   |   }||_|S rG   )rj   r<   )r?   rD   ri   r*   r*   r+   with_quota_projecth  s    zCredentials.with_quota_projectc                 C   s   |   }|p||_|S rG   )rj   r7   )r?   ZscopesZdefault_scopesri   r*   r*   r+   r5   n  s    
zCredentials.with_scopes)N)__name__
__module____qualname____doc__r9   r0   rI   r   copy_docstringr   r-   rK   rJ   rb   propertyrd   re   rf   rg   rh   rj   CredentialsWithQuotaProjectrk   r4   r5   __classcell__r*   r*   rE   r+   r-   n   s4   BC

'"





	


r-   c                       sd   e Zd ZdZd fdd	ZdddZdd	 Zd
d Ze	e
jdd Ze	e
jdd Z  ZS )IDTokenCredentialszAOpen ID Connect ID Token-based service account credentials.

    NFc                    s>   t t|   t|ts"td|| _|| _|| _	|| _
dS )a  
        Args:
            target_credentials (google.auth.Credentials): The target
                credential used as to acquire the id tokens for.
            target_audience (string): Audience to issue the token for.
            include_email (bool): Include email in IdToken
            quota_project_id (Optional[str]):  The project ID used for
                quota and billing.
        z4Provided Credential must be impersonated_credentialsN)r/   rt   r0   r3   r-   r   ZGoogleAuthError_target_credentials_target_audience_include_emailr<   )r?   target_credentialstarget_audienceinclude_emailrD   rE   r*   r+   r0   z  s    
zIDTokenCredentials.__init__c                 C   s   | j ||| j| jdS N)rx   ry   rz   rD   )rF   rw   r<   )r?   rx   ry   r*   r*   r+   from_credentials  s    z#IDTokenCredentials.from_credentialsc                 C   s   | j | j|| j| jdS r{   )rF   ru   rw   r<   )r?   ry   r*   r*   r+   with_target_audience  s    z'IDTokenCredentials.with_target_audiencec                 C   s   | j | j| j|| jdS r{   )rF   ru   rv   r<   )r?   rz   r*   r*   r+   with_include_email  s    z%IDTokenCredentials.with_include_emailc                 C   s   | j | j| j| j|dS r{   )rF   ru   rv   rw   )r?   rD   r*   r*   r+   rk     s    z%IDTokenCredentials.with_quota_projectc           	      C   s   ddl m} tjtj| jj	| jj
}| j| jj| jd}ddtjt i}|| jj|d}z |j||t|dd}W 5 |  X |jtjkrtd		| | d
 }|| _ttj |ddd | _!d S )Nr   rS   )ZaudiencerB   ZincludeEmailrM   rN   )Zauth_requestr
   )r   r   r   zError getting ID token: {}r'   F)verifyexp)"rV   rT   r   Z_IAM_IDTOKEN_ENDPOINTr   r   r   ru   r$   r   rd   rv   r8   rw   r	   rQ   Z"token_request_id_token_impersonater2   rY   rZ   r   r   r   r[   r   r   r   r   r'   r   utcfromtimestampr   r   r(   )	r?   r"   rT   r^   r   r   r_   r&   Zid_tokenr*   r*   r+   rK     sH       

zIDTokenCredentials.refresh)NFN)N)rl   rm   rn   ro   r0   r|   r}   r~   r   rp   r   rr   rk   r-   rK   rs   r*   r*   rE   r+   rt   u  s      



rt   )ro   rW   r1   r   http.clientclientr   r   Zgoogle.authr   r   r   r   r   r   r	   r   r9   r   r,   r4   rr   ZSigningr-   rt   r*   r*   r*   r+   <module>   s2   
>
    	