U
    h-j                     @   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dlmZ dZdZdZdZdZdZdZejdfddZG dd dejejejejZG dd dejZ g fdd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)metrics)_clientz*Unable to acquire impersonated credentialsi  z#https://oauth2.googleapis.com/tokenzKhttps://iamcredentials.{}/v1/projects/-/serviceAccounts/{}/allowedLocationsZauthorized_userservice_account external_account_authorized_userc              
   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_overrideiam_endpointresponseresponse_bodyZtoken_responsetokenexpiry
caught_excnew_exc r2   H/tmp/pip-unpacked-wheel-p8k_kup9/google/auth/impersonated_credentials.py_make_iam_token_request<   s6    
 


r4   c                       s   e Zd ZdZddedddf fdd	Zdd Z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 Zeejd!ddZed"dd Z  ZS )#Credentialsar
  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)

    **IMPORTANT**:
    This class does not validate the credential configuration. A security
    risk occurs when a credential configuration configured with malicious urls
    is used.
    When the credential configuration is accepted from an
    untrusted source, you should validate it before using.
    Refer https://cloud.google.com/docs/authentication/external/externally-sourced-credentials for more details.
    Nc
           
         s   t t|   t|| _t| jtjrX| jt	j
| _t| jdrX| jjrX| jd |j| _|| _|| _|| _|| _|p~t| _d| _t | _|| _|| _d| _|	| _dS )ap  
        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 (Optional[str]): The full IAM endpoint override
                with the target_principal embedded. This is useful when supporting
                impersonation with regional endpoints.
            subject (Optional[str]): sub field of a JWT. This field should only be set
                if you wish to impersonate as a user. This feature is useful when
                using domain wide delegation.
            trust_boundary (Mapping[str,str]): A credential trust boundary.
        _create_self_signed_jwtN)superr5   __init__copy_source_credentials
isinstancer   Scopedwith_scopesr   Z
_IAM_SCOPEr   Z_always_use_jwt_accessr6   r)   Z_universe_domain_target_principal_target_scopes
_delegates_subject_DEFAULT_TOKEN_LIFETIME_SECS	_lifetimer.   r   utcnowr/   _quota_project_id_iam_endpoint_override_cred_file_path_trust_boundary)
selfsource_credentialstarget_principaltarget_scopes	delegatessubjectlifetimequota_project_idr*   trust_boundary	__class__r2   r3   r8      s.    ,


zCredentials.__init__c                 C   s   t jS N)r
   ZCRED_TYPE_SA_IMPERSONATErI   r2   r2   r3   _metric_header_for_usage  s    z$Credentials._metric_header_for_usagec                 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 | | jr| jtjkrtdt }| jt| jpd| jtt|t|t d}t|| j||| jd}t|t|\| _| _}d	S 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)rM   scoperO   Content-Typeapplication/jsonzNDomain-wide delegation is not supported in universes other than googleapis.comr2   )ZissrX   subZaudZiatexp)r'   r(   r   payloadrM   N)r'   r(   r   r   r)   r*   )"r:   Ztoken_stater   Z
TokenStateZSTALEINVALIDrefreshr@   r?   strrC   r
   API_CLIENT_HEADERZ&token_request_access_token_impersonateapplyrA   r)   r   r   GoogleAuthErrorr   rD   r>   Zscopes_to_string_GOOGLE_OAUTH2_TOKEN_ENDPOINTZdatetime_to_secsrB   _sign_jwt_requestr   Z	jwt_grantr.   r/   r4   rF   )rI   r'   r   r   nowr]   Z	assertion_r2   r2   r3   _refresh_token  sb      	  zCredentials._refresh_tokenc                 C   s   | j stdt| j| j S )a  Builds and returns the URL for the trust boundary lookup API.

        This method constructs the specific URL for the IAM Credentials API's
        `allowedLocations` endpoint, using the credential's universe domain
        and service account email.

        Raises:
            ValueError: If `self.service_account_email` is None or an empty
                string, as it's required to form the URL.

        Returns:
            str: The URL for the trust boundary lookup endpoint.
        zIService account email is required to build the trust boundary lookup URL.)service_account_emailr&   _TRUST_BOUNDARY_LOOKUP_ENDPOINTr   r)   rU   r2   r2   r3    _build_trust_boundary_lookup_url[  s     z,Credentials._build_trust_boundary_lookup_urlc           
      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   )r]   rM   rY   rZ   )r   r   r   zError calling sign_bytes: {}Z
signedBlobz#exhausted signBlob endpoint retries)google.auth.transport.requestsrm   r   Z_IAM_SIGN_ENDPOINTr   r   r   r)   r   r>   base64	b64encoder   r@   r:   closer   ZExponentialBackoffpoststatus_codeZIAM_RETRY_CODESr   r    r   ZTransportErrorr   	b64decode)
rI   messagerm   iam_sign_endpointr   r   authed_sessionretriesrg   r,   r2   r2   r3   
sign_bytesq  s:     
  
zCredentials.sign_bytesc                 C   s   | j S rT   r>   rU   r2   r2   r3   signer_email  s    zCredentials.signer_emailc                 C   s   | j S rT   rz   rU   r2   r2   r3   ri     s    z!Credentials.service_account_emailc                 C   s   | S rT   r2   rU   r2   r2   r3   signer  s    zCredentials.signerc                 C   s   | j  S rT   )r?   rU   r2   r2   r3   requires_scopes  s    zCredentials.requires_scopesc                 C   s   | j r| j d| jdS d S )Nzimpersonated credentials)Zcredential_sourceZcredential_typer(   )rG   r>   rU   r2   r2   r3   get_cred_info  s    zCredentials.get_cred_infoc              
   C   s6   | j | j| j| j| j| j| j| j| jd}| j	|_	|S )N)rK   rL   rM   rO   rP   r*   rQ   )
rS   r:   r>   r?   r@   rC   rE   rF   rH   rG   )rI   credr2   r2   r3   
_make_copy  s    
zCredentials._make_copyc                 C   s   |   }||_|S rT   )r   rH   )rI   rQ   r   r2   r2   r3   with_trust_boundary  s    zCredentials.with_trust_boundaryc                 C   s   |   }||_|S rT   )r   rE   )rI   rP   r   r2   r2   r3   with_quota_project  s    zCredentials.with_quota_projectc                 C   s   |   }|p||_|S rT   )r   r?   )rI   scopesZdefault_scopesr   r2   r2   r3   r=     s    
zCredentials.with_scopesc                 C   s  | d}| d}|tkr6ddlm} |j|}nT|tkrXddlm} |j|}n2|t	krzddl
m} |j|}ntd|| d}	|	d	}
|	d
}|
dks|dks|
|krtd|	|	|
d | }| d}| d}| |||||dS )a  Creates a Credentials instance from parsed impersonated service account credentials info.

        **IMPORTANT**:
        This method does not validate the credential configuration. A security
        risk occurs when a credential configuration configured with malicious urls
        is used.
        When the credential configuration is accepted from an
        untrusted source, you should validate it before using with this method.
        Refer https://cloud.google.com/docs/authentication/external/externally-sourced-credentials for more details.

        Args:
            info (Mapping[str, str]): The impersonated service account credentials info in Google
                format.
            scopes (Sequence[str]): Optional list of scopes to include in the
                credentials.

        Returns:
            google.oauth2.credentials.Credentials: The constructed
                credentials.

        Raises:
            InvalidType: If the info["source_credentials"] are not a supported impersonation type
            InvalidValue: If the info["service_account_impersonation_url"] is not in the expected format.
            ValueError: If the info is not in the expected format.
        rJ   typer   r   )r   )r   z.source credential of type {} is not supported.Z!service_account_impersonation_url/z:generateAccessTokenz'Cannot extract target principal from {}   rM   rP   )rP   )get'_SOURCE_CREDENTIAL_AUTHORIZED_USER_TYPEgoogle.oauth2r   r5   Zfrom_authorized_user_info'_SOURCE_CREDENTIAL_SERVICE_ACCOUNT_TYPEr   Zfrom_service_account_info8_SOURCE_CREDENTIAL_EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPEgoogle.authr   Z	from_infor   ZInvalidTyper   rfindfindZInvalidValue)clsinfor   Zsource_credentials_infoZsource_credentials_typer   rJ   r   r   Zimpersonation_urlstart_indexZ	end_indexrK   rM   rP   r2   r2   r3   &from_impersonated_service_account_info  sT    






z2Credentials.from_impersonated_service_account_info)N)N)__name__
__module____qualname____doc__rB   r8   rV   rh   rk   ry   propertyr{   ri   r|   r}   r   copy_docstringr   r5   r~   r   CredentialsWithTrustBoundaryr   CredentialsWithQuotaProjectr   r<   r=   classmethodr   __classcell__r2   r2   rR   r3   r5   z   s>   JKH"





	




r5   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 )IDTokenCredentialsz;Open 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)r7   r   r8   r;   r5   r   rc   _target_credentials_target_audience_include_emailrE   )rI   target_credentialstarget_audienceinclude_emailrP   rR   r2   r3   r8     s    
zIDTokenCredentials.__init__c                 C   s   | j ||| j| jdS N)r   r   r   rP   )rS   r   rE   )rI   r   r   r2   r2   r3   from_credentials9  s    z#IDTokenCredentials.from_credentialsc                 C   s   | j | j|| j| jdS r   )rS   r   r   rE   )rI   r   r2   r2   r3   with_target_audienceA  s    z'IDTokenCredentials.with_target_audiencec                 C   s   | j | j| j|| jdS r   )rS   r   r   rE   )rI   r   r2   r2   r3   with_include_emailI  s    z%IDTokenCredentials.with_include_emailc                 C   s   | j | j| j| j|dS r   )rS   r   r   r   )rI   rP   r2   r2   r3   r   Q  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   rl   )ZaudiencerM   ZincludeEmailrY   rZ   )Zauth_requestr   )r   r   r   zError getting ID token: {}r.   F)verifyr\   )"rn   rm   r   Z_IAM_IDTOKEN_ENDPOINTr   r   r   r   r)   r   r{   r   r@   r   r
   ra   Z"token_request_id_token_impersonater:   rq   rr   r   r   r   rs   r   r    r   r!   r.   r   utcfromtimestampr	   r   r/   )	rI   r'   rm   rv   r   r   rw   r,   Zid_tokenr2   r2   r3   r_   Z  sH       

zIDTokenCredentials.refresh)NFN)N)r   r   r   r   r8   r   r   r   r   r   r   r   r   r5   r_   r   r2   r2   rR   r3   r     s      



r   c              
   C   s   t j|}|t|d}t|d}| |d||d}t|jdrT|jdn|j}|j	t
jkrrtt|zt|}	|	d }
|
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 to sign a JWT using a
    service account's system-managed private key.
    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.
        payload (Mapping[str, str]): The JWT payload to sign. Must be a
            serialized JSON object that contains a JWT Claims Set.
        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.

    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
    )rM   r]   r   r   r   r   Z	signedJwtz{}: No signed JWT in response.N)r   Z_IAM_SIGNJWT_ENDPOINTr   r   r   r   r   r   r   r   r   r    r   r!   r"   r#   r%   r&   )r'   r(   r   r]   rM   r+   r   r,   r-   Zjwt_responseZ
signed_jwtr0   r1   r2   r2   r3   re     s(    

 re   )"r   ro   r9   r   http.clientclientr   r   r   r   r   r   r   r   r	   r
   r   r   r"   rB   rd   rj   r   r   r   r   r4   r<   r   ZSigningr   r5   r   re   r2   r2   r2   r3   <module>   sH   

>
   $l