o
    l                     @   s   d 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 ddlm	Z	 ddlm
Z
 ddlmZ dZd	Zd
ZG dd dejZdd ZG dd deZdS )z/oauth2client Service account credentials class.    N)_helpers)client)crypt)	transport)util
notasecret_private_key_pkcs12a
  
This library only implements PKCS#12 support via the pyOpenSSL library.
Either install pyOpenSSL, or please convert the .p12 file
to .pem format:
    $ cat key.p12 | \
    >   openssl pkcs12 -nodes -nocerts -passin pass:notasecret | \
    >   openssl rsa > key.pem
c                       s<  e Zd ZdZdZ	 edgejjB Z	 dZ	dZ
dZddddejejf fdd	Zd( fdd		Ze	d)d
dZe		d*ddZe		d*ddZeddejejfddZeddejejfddZeddejejfddZdd Zdd Zedd Zedd Zedd Zd d! Zd"d# Zd$d% Z d&d' Z!  Z"S )+ServiceAccountCredentialsa  Service Account credential for OAuth 2.0 signed JWT grants.

    Supports

    * JSON keyfile (typically contains a PKCS8 key stored as
      PEM text)
    * ``.p12`` key (stores PKCS12 key and certificate)

    Makes an assertion to server using a signed JWT assertion in exchange
    for an access token.

    This credential does not require a flow to instantiate because it
    represents a two legged flow, and therefore has all of the required
    information to generate and refresh its own access tokens.

    Args:
        service_account_email: string, The email associated with the
                               service account.
        signer: ``crypt.Signer``, A signer which can be used to sign content.
        scopes: List or string, (Optional) Scopes to use when acquiring
                an access token.
        private_key_id: string, (Optional) Private key identifier. Typically
                        only used with a JSON keyfile. Can be sent in the
                        header of a JWT token assertion.
        client_id: string, (Optional) Client ID for the project that owns the
                   service account.
        user_agent: string, (Optional) User agent to use when sending
                    request.
        token_uri: string, URI for token endpoint. For convenience defaults
                   to Google's endpoints but any OAuth 2.0 provider can be
                   used.
        revoke_uri: string, URI for revoke endpoint.  For convenience defaults
                   to Google's endpoints but any OAuth 2.0 provider can be
                   used.
        kwargs: dict, Extra key-value pairs (both strings) to send in the
                payload body when making an assertion.
      _signerN c	           
         sL   t t| jd |||d || _|| _t|| _|| _|| _	|| _
|	| _d S )N)
user_agent	token_uri
revoke_uri)superr	   __init___service_account_emailr   r   scopes_to_string_scopes_private_key_id	client_id_user_agent_kwargs)
selfservice_account_emailsignerscopesprivate_key_idr   r   r   r   kwargs	__class__ E/tmp/google-cloud-sdk/lib/third_party/oauth2client/service_account.pyr   `   s   

z"ServiceAccountCredentials.__init__c                    sH   |du r
t  | j}|t}|durt||t< tt| j||dS )ac  Utility function that creates JSON repr. of a credentials object.

        Over-ride is needed since PKCS#12 keys will not in general be JSON
        serializable.

        Args:
            strip: array, An array of names of members to exclude from the
                   JSON.
            to_serialize: dict, (Optional) The properties for this object
                          that will be serialized. This allows callers to
                          modify before serializing.

        Returns:
            string, a JSON representation of this instance, suitable to pass to
            from_json().
        N)to_serialize)	copy__dict__get_PKCS12_KEYbase64	b64encoder   r	   _to_json)r   stripr#   
pkcs12_valr   r!   r"   r*   w   s   

z"ServiceAccountCredentials._to_jsonc              	   C   s   | d}|tjkrtd|dtj|d }|d }|d }|d }	|s+| dtj}|s4| d	tj}tj	|}
| ||
|||	||d
}||_
|S )a	  Helper for factory constructors from JSON keyfile.

        Args:
            keyfile_dict: dict-like object, The parsed dictionary-like object
                          containing the contents of the JSON keyfile.
            scopes: List or string, Scopes to use when acquiring an
                    access token.
            token_uri: string, URI for OAuth 2.0 provider token endpoint.
                       If unset and not present in keyfile_dict, defaults
                       to Google's endpoints.
            revoke_uri: string, URI for OAuth 2.0 provider revoke endpoint.
                       If unset and not present in keyfile_dict, defaults
                       to Google's endpoints.

        Returns:
            ServiceAccountCredentials, a credentials object created from
            the keyfile contents.

        Raises:
            ValueError, if the credential type is not :data:`SERVICE_ACCOUNT`.
            KeyError, if one of the expected keys is not present in
                the keyfile.
        typezUnexpected credentials typeExpectedclient_emailprivate_keyr   r   r   r   )r   r   r   r   r   )r&   r   SERVICE_ACCOUNT
ValueErroroauth2clientGOOGLE_TOKEN_URIGOOGLE_REVOKE_URIr   Signerfrom_string_private_key_pkcs8_pem)clskeyfile_dictr   r   r   
creds_typer   private_key_pkcs8_pemr   r   r   credentialsr!   r!   r"   _from_parsed_json_keyfile   s2   

z3ServiceAccountCredentials._from_parsed_json_keyfilec                 C   sF   t |d}t|}W d   n1 sw   Y  | j||||dS )a  Factory constructor from JSON keyfile by name.

        Args:
            filename: string, The location of the keyfile.
            scopes: List or string, (Optional) Scopes to use when acquiring an
                    access token.
            token_uri: string, URI for OAuth 2.0 provider token endpoint.
                       If unset and not present in the key file, defaults
                       to Google's endpoints.
            revoke_uri: string, URI for OAuth 2.0 provider revoke endpoint.
                       If unset and not present in the key file, defaults
                       to Google's endpoints.

        Returns:
            ServiceAccountCredentials, a credentials object created from
            the keyfile.

        Raises:
            ValueError, if the credential type is not :data:`SERVICE_ACCOUNT`.
            KeyError, if one of the expected keys is not present in
                the keyfile.
        rNr   r   )openjsonloadr>   )r9   filenamer   r   r   file_objclient_credentialsr!   r!   r"   from_json_keyfile_name   s   z0ServiceAccountCredentials.from_json_keyfile_namec                 C   s   | j ||||dS )a  Factory constructor from parsed JSON keyfile.

        Args:
            keyfile_dict: dict-like object, The parsed dictionary-like object
                          containing the contents of the JSON keyfile.
            scopes: List or string, (Optional) Scopes to use when acquiring an
                    access token.
            token_uri: string, URI for OAuth 2.0 provider token endpoint.
                       If unset and not present in keyfile_dict, defaults
                       to Google's endpoints.
            revoke_uri: string, URI for OAuth 2.0 provider revoke endpoint.
                       If unset and not present in keyfile_dict, defaults
                       to Google's endpoints.

        Returns:
            ServiceAccountCredentials, a credentials object created from
            the keyfile.

        Raises:
            ValueError, if the credential type is not :data:`SERVICE_ACCOUNT`.
            KeyError, if one of the expected keys is not present in
                the keyfile.
        r@   )r>   )r9   r:   r   r   r   r!   r!   r"   from_json_keyfile_dict   s   z0ServiceAccountCredentials.from_json_keyfile_dictc           	      C   sP   |du rt }tjtjurtttj||}| |||||d}||_||_|S )ax  Factory constructor from JSON keyfile.

        Args:
            service_account_email: string, The email associated with the
                                   service account.
            private_key_pkcs12: string, The contents of a PKCS#12 keyfile.
            private_key_password: string, (Optional) Password for PKCS#12
                                  private key. Defaults to ``notasecret``.
            scopes: List or string, (Optional) Scopes to use when acquiring an
                    access token.
            token_uri: string, URI for token endpoint. For convenience defaults
                       to Google's endpoints but any OAuth 2.0 provider can be
                       used.
            revoke_uri: string, URI for revoke endpoint. For convenience
                        defaults to Google's endpoints but any OAuth 2.0
                        provider can be used.

        Returns:
            ServiceAccountCredentials, a credentials object created from
            the keyfile.

        Raises:
            NotImplementedError if pyOpenSSL is not installed / not the
            active crypto library.
        N)r   r   r   )	_PASSWORD_DEFAULTr   r6   OpenSSLSignerNotImplementedError_PKCS12_ERRORr7   r   _private_key_password)	r9   r   private_key_pkcs12private_key_passwordr   r   r   r   r=   r!   r!   r"   _from_p12_keyfile_contents   s   z4ServiceAccountCredentials._from_p12_keyfile_contentsc           	      C   sH   t |d}| }W d   n1 sw   Y  | j||||||dS )ap  Factory constructor from JSON keyfile.

        Args:
            service_account_email: string, The email associated with the
                                   service account.
            filename: string, The location of the PKCS#12 keyfile.
            private_key_password: string, (Optional) Password for PKCS#12
                                  private key. Defaults to ``notasecret``.
            scopes: List or string, (Optional) Scopes to use when acquiring an
                    access token.
            token_uri: string, URI for token endpoint. For convenience defaults
                       to Google's endpoints but any OAuth 2.0 provider can be
                       used.
            revoke_uri: string, URI for revoke endpoint. For convenience
                        defaults to Google's endpoints but any OAuth 2.0
                        provider can be used.

        Returns:
            ServiceAccountCredentials, a credentials object created from
            the keyfile.

        Raises:
            NotImplementedError if pyOpenSSL is not installed / not the
            active crypto library.
        rbNrO   r   r   r   )rA   readrP   )	r9   r   rD   rO   r   r   r   rE   rN   r!   r!   r"   from_p12_keyfile+  s   
z*ServiceAccountCredentials.from_p12_keyfilec                 C   s   |  }| j||||||dS )a  Factory constructor from JSON keyfile.

        Args:
            service_account_email: string, The email associated with the
                                   service account.
            file_buffer: stream, A buffer that implements ``read()``
                         and contains the PKCS#12 key contents.
            private_key_password: string, (Optional) Password for PKCS#12
                                  private key. Defaults to ``notasecret``.
            scopes: List or string, (Optional) Scopes to use when acquiring an
                    access token.
            token_uri: string, URI for token endpoint. For convenience defaults
                       to Google's endpoints but any OAuth 2.0 provider can be
                       used.
            revoke_uri: string, URI for revoke endpoint. For convenience
                        defaults to Google's endpoints but any OAuth 2.0
                        provider can be used.

        Returns:
            ServiceAccountCredentials, a credentials object created from
            the keyfile.

        Raises:
            NotImplementedError if pyOpenSSL is not installed / not the
            active crypto library.
        rR   )rS   rP   )r9   r   file_bufferrO   r   r   r   rN   r!   r!   r"   from_p12_keyfile_bufferQ  s   z1ServiceAccountCredentials.from_p12_keyfile_bufferc                 C   sH   t t }| j| j||| j | jd}|| j tj	| j
|| jdS )z8Generate the assertion that will be used in the request.)audscopeiatexpisskey_id)inttimer   r   MAX_TOKEN_LIFETIME_SECSr   updater   r   make_signed_jwtr   r   )r   nowpayloadr!   r!   r"   _generate_assertionv  s   
z-ServiceAccountCredentials._generate_assertionc                 C   s   | j | j|fS )aU  Cryptographically sign a blob (of bytes).

        Implements abstract method
        :meth:`oauth2client.client.AssertionCredentials.sign_blob`.

        Args:
            blob: bytes, Message to be signed.

        Returns:
            tuple, A pair of the private key ID used to sign the blob and
            the signed contents.
        )r   r   sign)r   blobr!   r!   r"   	sign_blob  s   z#ServiceAccountCredentials.sign_blobc                 C   s   | j S )zGet the email for the current service account.

        Returns:
            string, The email associated with the service account.
        )r   r   r!   r!   r"   r     s   z/ServiceAccountCredentials.service_account_emailc                 C   s   d| j | j| j| jdS )Nservice_account)r-   r/   r   r0   r   )r   r   r8   r   ri   r!   r!   r"   serialization_data  s   z,ServiceAccountCredentials.serialization_datac                 C   s  t |tstt|}d}|t}d}|du r%|d }tj	
|}nt|}|d }tj	
||}| |d |f|d |d |d |d d	|d
 }|durV||_|dur]||_|durd||_|d |_|d |_|d |_|d |_|dd}|durtj|tj|_|S )aM  Deserialize a JSON-serialized instance.

        Inverse to :meth:`to_json`.

        Args:
            json_data: dict or string, Serialized JSON (as a string or an
                       already parsed dictionary) representing a credential.

        Returns:
            ServiceAccountCredentials from the serialized data.
        Nr8   rM   r   r   r   r   r   r   r   r   r   r   invalidaccess_tokenr   r   token_expiry)
isinstancedictrB   loadsr   _from_bytesr&   r'   r   r6   r7   r(   	b64decoder8   r   rM   rm   rn   r   r   datetimestrptimer   EXPIRY_FORMATro   )r9   	json_datar<   r,   passwordr   r=   ro   r!   r!   r"   	from_json  sL   


	



z#ServiceAccountCredentials.from_jsonc                 C   s   | j  S N)r   ri   r!   r!   r"   create_scoped_required  s   z0ServiceAccountCredentials.create_scoped_requiredc                 C   sV   | j | j| jf|| j| j| jd| j}| j|_| j|_| j	|_	| j
|_
| j|_|S )Nrl   )r    r   r   r   r   r   r   r   r   r8   r   rM   )r   r   resultr!   r!   r"   create_scoped  s    z'ServiceAccountCredentials.create_scopedc                 C   sj   t | j}|| | j| j| jf| j| j| j| j	d|}| j
|_
| j|_| j|_| j|_| j|_|S )a<  Create credentials that specify additional claims.

        Args:
            claims: dict, key-value pairs for claims.

        Returns:
            ServiceAccountCredentials, a copy of the current service account
            credentials with updated claims to use when obtaining access
            tokens.
        rl   )rq   r   ra   r    r   r   r   r   r   r   r   r   r8   r   rM   )r   claims
new_kwargsr}   r!   r!   r"   create_with_claims  s$   

z,ServiceAccountCredentials.create_with_claimsc                 C   s   |  d|iS )aY  Create credentials that act as domain-wide delegation of authority.

        Use the ``sub`` parameter as the subject to delegate on behalf of
        that user.

        For example::

          >>> account_sub = 'foo@email.com'
          >>> delegate_creds = creds.create_delegated(account_sub)

        Args:
            sub: string, An email address that this service account will
                 act on behalf of (via domain-wide delegation).

        Returns:
            ServiceAccountCredentials, a copy of the current service account
            updated to act on behalf of ``sub``.
        sub)r   )r   r   r!   r!   r"   create_delegated  s   z*ServiceAccountCredentials.create_delegatedr{   NN)r   NN)#__name__
__module____qualname____doc__r`   	frozensetr   AssertionCredentialsNON_SERIALIZED_MEMBERSr8   r   rM   r3   r4   r5   r   r*   classmethodr>   rG   rH   rP   rT   rV   re   rh   propertyr   rk   rz   r|   r~   r   r   __classcell__r!   r!   r   r"   r	   +   st    &1*%$



6r	   c                 C   s&   t  ddd}| | }|jd |j S )Ni     iQ )ru   daysseconds)utc_timeepoch
time_deltar!   r!   r"   _datetime_to_secs!  s   r   c                       s   e Zd ZdZdZ	 ddddejejdf fdd	Zdd Z	ddd	Z
d
d Zdd ZejejfddZdd Zdd ZdddZ  ZS )_JWTAccessCredentialszSelf signed JWT credentials.

    Makes an assertion to server using a self signed JWT from service account
    credentials.  These credentials do NOT use OAuth 2.0 and instead
    authenticate directly.
    r
   Nc
           
         s6   |	d u ri }	t t| j||f|||||d|	 d S )N)r   r   r   r   r   )r   r   r   )
r   r   r   r   r   r   r   r   r   additional_claimsr   r!   r"   r   3  s   


z_JWTAccessCredentials.__init__c                 C   s   t | | |S )a  Authorize an httplib2.Http instance with a JWT assertion.

        Unless specified, the 'aud' of the assertion will be the base
        uri of the request.

        Args:
            http: An instance of ``httplib2.Http`` or something that acts
                  like it.
        Returns:
            A modified instance of http that was passed in.
        Example::
            h = httplib2.Http()
            h = credentials.authorize(h)
        )r   wrap_http_for_jwt_accessr   httpr!   r!   r"   	authorizeI  s   z_JWTAccessCredentials.authorizec                 C   sT   |du r| j du s| jr| d tj| j |  dS | |\}}tj|| jdS )zCreate a signed jwt.

        Args:
            http: unused
            additional_claims: dict, additional claims to add to
                the payload of the JWT.
        Returns:
            An AccessTokenInfo with the signed jwt
        N)rn   
expires_in)rn   access_token_expiredrefreshr   AccessTokenInfo_expires_in_create_token_MAX_TOKEN_LIFETIME_SECS)r   r   r   tokenunused_expiryr!   r!   r"   get_access_token[  s   


z&_JWTAccessCredentials.get_access_tokenc                 C      dS )z*Cannot revoke JWTAccessCredentials tokens.Nr!   r   r!   r!   r"   revokep     z_JWTAccessCredentials.revokec                 C   r   )NTr!   ri   r!   r!   r"   r|   t  r   z,_JWTAccessCredentials.create_scoped_requiredc              	   C   sf   t | j| jf|| j| j| j||d| j}| jd ur| j|_| jd ur(| j|_| j	d ur1| j	|_	|S )N)r   r   r   r   r   r   )
r	   r   r   r   r   r   r   r8   r   rM   )r   r   r   r   r}   r!   r!   r"   r~   x  s&   
	

z#_JWTAccessCredentials.create_scopedc                 C   s   |  d  d S r{   )_refreshr   r!   r!   r"   r     s   z_JWTAccessCredentials.refreshc                 C   s   |   \| _| _d S r{   )r   rn   ro   )r   http_requestr!   r!   r"   r     s   z_JWTAccessCredentials._refreshc                 C   sx   t  }tj| jd}|| }t|t|| j| jd}|| j |d ur+|| t	j
| j|| jd}|d|fS )N)r   )rY   rZ   r[   r   r\   ascii)r   _UTCNOWru   	timedeltar   r   r   ra   r   r   rb   r   r   decode)r   r   rc   lifetimeexpiryrd   jwtr!   r!   r"   r     s   

z#_JWTAccessCredentials._create_tokenr   r{   )r   r   r   r   r   r3   r4   r5   r   r   r   r   r|   r~   r   r   r   r   r!   r!   r   r"   r   )  s,    

r   )r   r(   r$   ru   rB   r_   r3   r   r   r   r   r   rI   r'   rL   r   r	   r   r   r!   r!   r!   r"   <module>   s*   
   y