o
    i}                     @   s  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mZmZ ddlmZ ddlmZ ddlmZmZ dd	lmZ e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"dd Z#dd Z$e! Z%e! Z&e! Z'e! Z(e! Z)e! Z*dd Z+ddddee, deee,  fdd Z-d2d!d"Z.d#d$ Z/d%d& Z0d'd( Z1dddde,deee,  fd)d*Z2d+ej34d,d-Z5G d.d/ d/eZ6d0d1 Z7dS )3    N)urlparse)UserDict)ListOptionalUnion   )
TokenCache)_IndividualCache)ThrottledHttpClientBaseRetryAfterParser)_is_running_in_cloud_shellc                   @      e Zd ZdS )ManagedIdentityErrorN__name__
__module____qualname__ r   r   L/home/app/Keep/.python/lib/python3.10/site-packages/msal/managed_identity.pyr          r   c                       sn   e Zd ZdZdZdZdZdZdZdZ	eded	ed
iZ
edd Zedd Zedd Zd fdd	Z  ZS )ManagedIdentityzFeed an instance of this class to :class:`msal.ManagedIdentityClient`
    to acquire token for the specified managed identity.
    ZManagedIdentityIdTypeZIdZClientIdZ
ResourceIdZObjectIdZSystemAssigned	client_idZ
msi_res_id	object_idc                 C   s   t |tp| |p| |S N)
isinstancer   is_system_assignedis_user_assignedclsunknownr   r   r   is_managed_identity/   s
   
z#ManagedIdentity.is_managed_identityc                 C   s&   t |tpt |to|| j| jkS r   )r   SystemAssignedManagedIdentitydictgetID_TYPESYSTEM_ASSIGNEDr   r   r   r   r   5   s   

z"ManagedIdentity.is_system_assignedc                 C   s2   t |tpt |to|| j| jv o|| jS r   )r   UserAssignedManagedIdentityr"   r#   r$   _types_mappingIDr   r   r   r   r   ;   s   


z ManagedIdentity.is_user_assignedNc                    s    t t| | j|| j|i d S r   )superr   __init__r$   r(   )self
identifierid_type	__class__r   r   r*   B   s   

zManagedIdentity.__init__)NN)r   r   r   __doc__r$   r(   	CLIENT_IDRESOURCE_ID	OBJECT_IDr%   r'   classmethodr    r   r   r*   __classcell__r   r   r.   r   r      s&    


r   c                       s    e Zd ZdZ fddZ  ZS )r!   zRepresent a system-assigned managed identity.

    It is equivalent to a Python dict of::

        {"ManagedIdentityIdType": "SystemAssigned", "Id": None}

    or a JSON blob of::

        {"ManagedIdentityIdType": "SystemAssigned", "Id": null}
    c                    s   t t| j| jd d S )N)r-   )r)   r!   r*   r%   r+   r.   r   r   r*   U   s   z&SystemAssignedManagedIdentity.__init__r   r   r   r0   r*   r5   r   r   r.   r   r!   J   s    
r!   c                       s*   e Zd ZdZdddd fdd
Z  ZS )r&   a9  Represent a user-assigned managed identity.

    Depends on the id you provided, the outcome is equivalent to one of the below::

        {"ManagedIdentityIdType": "ClientId", "Id": "foo"}
        {"ManagedIdentityIdType": "ResourceId", "Id": "foo"}
        {"ManagedIdentityIdType": "ObjectId", "Id": "foo"}
    N)r   resource_idr   c                   sz   |r|s|st t| j| j|d d S |s&|r&|s&t t| j| j|d d S |s9|s9|r9t t| j| j|d d S td)N)r-   r,   zPYou shall specify one of the three parameters: client_id, resource_id, object_id)r)   r&   r*   r1   r2   r3   r   )r+   r   r8   r   r.   r   r   r*   b   s   





z$UserAssignedManagedIdentity.__init__r7   r   r   r.   r   r&   Y   s    r&   c                       s   e Zd Z fddZ  ZS )_ThrottledHttpClientc                    s@   t t j|i | t j fddtdjd j _d S )Nc              
      s.   d |d  t|dt|d S )Nz"REQ {} hash={} 429/5xx/Retry-Afterr   paramsdata)format_hashstrr#   )funcargskwargsr6   r   r   <lambda>w   s    z/_ThrottledHttpClient.__init__.<locals>.<lambda>   )mappingZ	key_maker
expires_in)r)   r9   r*   IndividualCacheZ_expiring_mappingr   parser#   )r+   r@   rA   r.   r6   r   r*   s   s   


z_ThrottledHttpClient.__init__)r   r   r   r*   r5   r   r   r.   r   r9   r   s    r9   c                   @   sp   e Zd ZdZdZdZdZdZdZddddde	e
eeef d	eee  fd
dZdddedee fddZdS )ManagedIdentityClienta*  This API encapsulates multiple managed identity back-ends:
    VM, App Service, Azure Automation (Runbooks), Azure Function, Service Fabric,
    and Azure Arc.

    It also provides token cache support.

    .. note::

        Cloud Shell support is NOT implemented in this class.
        Since MSAL Python 1.18 in May 2022, it has been implemented in
        :func:`PublicClientApplication.acquire_token_interactive` via calling pattern
        ``PublicClientApplication(...).acquire_token_interactive(scopes=[...], prompt="none")``.
        That is appropriate, because Cloud Shell yields a token with
        delegated permissions for the end user who has signed in to the Azure Portal
        (like what a ``PublicClientApplication`` does),
        not a token with application permissions for an app.
    	localhostmanaged_identityZtoken_sourceZidentity_providercacheN)token_cache
http_cacheclient_capabilitiesrN   c                C   sB   t |std| || _t||d| _|pt | _|| _dS )a  Create a managed identity client.

        :param managed_identity:
            It accepts an instance of :class:`SystemAssignedManagedIdentity`
            or :class:`UserAssignedManagedIdentity`.
            They are equivalent to a dict with a certain shape,
            which may be loaded from a JSON configuration file or an env var.

        :param http_client:
            An http client object. For example, you can use ``requests.Session()``,
            optionally with exponential backoff behavior demonstrated in this recipe::

                import msal, requests
                from requests.adapters import HTTPAdapter, Retry
                s = requests.Session()
                retries = Retry(total=3, backoff_factor=0.1, status_forcelist=[
                    429, 500, 501, 502, 503, 504])
                s.mount('https://', HTTPAdapter(max_retries=retries))
                managed_identity = ...
                client = msal.ManagedIdentityClient(managed_identity, http_client=s)

        :param token_cache:
            Optional. It accepts a :class:`msal.TokenCache` instance to store tokens.
            It will use an in-memory token cache by default.

        :param http_cache:
            Optional. It has the same characteristics as the
            :paramref:`msal.ClientApplication.http_cache`.

        :param list[str] client_capabilities: (optional)
            Allows configuration of one or more client capabilities, e.g. ["CP1"].

            Client capability is meant to inform the Microsoft identity platform
            (STS) what this client is capable for,
            so STS can decide to turn on certain features.

            Implementation details:
            Client capability in Managed Identity is relayed as-is
            via ``xms_cc`` parameter on the wire.

        Recipe 1: Hard code a managed identity for your app::

            import msal, requests
            client = msal.ManagedIdentityClient(
                msal.UserAssignedManagedIdentity(client_id="foo"),
                http_client=requests.Session(),
                )
            token = client.acquire_token_for_client("resource")

        Recipe 2: Write once, run everywhere.
        If you use different managed identity on different deployment,
        you may use an environment variable (such as MY_MANAGED_IDENTITY_CONFIG)
        to store a json blob like
        ``{"ManagedIdentityIdType": "ClientId", "Id": "foo"}`` or
        ``{"ManagedIdentityIdType": "SystemAssigned", "Id": null}``.
        The following app can load managed identity configuration dynamically::

            import json, os, msal, requests
            config = os.getenv("MY_MANAGED_IDENTITY_CONFIG")
            assert config, "An ENV VAR with value should exist"
            client = msal.ManagedIdentityClient(
                json.loads(config),
                http_client=requests.Session(),
                )
            token = client.acquire_token_for_client("resource")
        zIncorrect managed_identity: )rM   N)	r   r    r   _managed_identityr9   _http_clientr   _token_cache_client_capabilities)r+   rJ   http_clientrL   rM   rN   r   r   r   r*      s   
P
zManagedIdentityClient.__init__)claims_challengeresourcerT   c             
   C   s  d}d}| j tjd}t }	 | jj| jjj|gt	|| j
| jddd}|D ]K}t|d | }	|	dk r7q(|rA|sA|d } n3td	 d
|d d|dddt|	| j| ji}d|v rpt|d |d< t|d |k rp n|  S zit| j| j ||rt|d nd| jd}
d
|
v r|
dd}	d|
vr|	dkrt|	d |
d< | jt	||gd| j
| j|
i i d d|
v rt||
d  |
d< | j|
| j< |
rd|
vs|s|
W S W |S    |s Y |S )aE  Acquire token for the managed identity.

        The result will be automatically cached.
        Subsequent calls will automatically search from cache first.

        :param resource: The resource for which the token is acquired.

        :param claims_challenge:
            Optional.
            It is a string representation of a JSON object
            (which contains lists of claims being requested).

            The tenant admin may choose to revoke all Managed Identity tokens,
            and then a *claims challenge* will be returned by the target resource,
            as a `claims_challenge` directive in the `www-authenticate` header,
            even if the app developer did not opt in for the "CP1" client capability.
            Upon receiving a `claims_challenge`, MSAL will attempt to acquire a new token.

        .. note::

            Known issue: When an Azure VM has only one user-assigned managed identity,
            and your app specifies to use system-assigned managed identity,
            Azure VM may still return a token for your user-assigned identity.

            This is a service-side behavior that cannot be changed by this library.
            `Azure VM docs <https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http>`_
        NZ SYSTEM_ASSIGNED_MANAGED_IDENTITYT)r   environmentrealmZhome_account_id)targetquery
expires_oni,  secretzCache hit an ATaccess_token
token_typeBearerrE   Z
refresh_onzutf-8access_token_sha256_to_refreshrN   i  Z
refresh_ini      zhttps://{}/{})r   scopeZtoken_endpointresponser:   r;   error)rO   r#   r   r(   timerQ   searchZCredentialTypeZACCESS_TOKENr"    _ManagedIdentityClient__instance_tenantintloggerdebug_TOKEN_SOURCE_TOKEN_SOURCE_CACHE_obtain_tokenrP   hashlibsha256encode	hexdigestrR   addr<   _TOKEN_SOURCE_IDP)r+   rU   rT   Zaccess_token_to_refreshZaccess_token_from_cacheZclient_id_in_cachenowmatchesentryrE   resultr   r   r   acquire_token_for_client  s   !


	z.ManagedIdentityClient.acquire_token_for_client)r   r   r   r0   rg   rh   rl   rt   rm   r   r"   r   r!   r&   r   r   r>   r*   ry   r   r   r   r   rH      s6    

irH   c                 C   s"   t | }|jrd|j|jS | S )Nz{}://{})r   schemer<   netloc)rb   ur   r   r   _scope_to_resourcei  s   r}   c                   C   s^   dt jv rdt jv rt jd S tjdkrt jds)tjdkr+t jt jdr-dS d S d S )NIDENTITY_ENDPOINTZIMDS_ENDPOINTlinuxz/opt/azcmagent/bin/himdswin32z4${ProgramFiles}\AzureConnectedMachineAgent\himds.exez5http://localhost:40342/metadata/identity/oauth2/token)osenvironsysplatformpathexists
expandvarsr   r   r   r   _get_arc_endpointp  s   
r   c                   C   sj   dt jv rdt jv rdt jv rtS dt jv rdt jv rtS dt jv r)dt jv r)tS t r.tS t r3tS t	S )zDetect the current environment and return the likely identity source.

    When this function returns ``CLOUD_SHELL``, you should use
    :func:`msal.PublicClientApplication.acquire_token_interactive` with ``prompt="none"``
    to obtain a token.
    r~   IDENTITY_HEADERIDENTITY_SERVER_THUMBPRINTMSI_ENDPOINT
MSI_SECRET)
r   r   SERVICE_FABRICAPP_SERVICEMACHINE_LEARNINGr   	AZURE_ARCr   CLOUD_SHELLDEFAULT_TO_VMr   r   r   r   get_managed_identity_source  s   
r   r_   r`   rN   c             	   C   s   dt jv r*dt jv r*dt jv r*|rtd t| t jd t jd t jd |||dS dt jv rBdt jv rBt| t jd t jd ||S dt jv rZdt jv rZt| t jd t jd ||S t }|rnt	|rht
dt| ||S t| ||S )	Nr~   r   r   zIgnoring managed_identity parameter. Managed Identity in Service Fabric is configured in the cluster, not during runtime. See also https://learn.microsoft.com/en-us/azure/service-fabric/configure-existing-cluster-enable-managed-identity-token-servicer_   r   r   zInvalid managed_identity parameter. Azure Arc supports only system-assigned managed identity, See also https://learn.microsoft.com/en-us/azure/service-fabric/configure-existing-cluster-enable-managed-identity-token-service)r   r   rj   rk   _obtain_token_on_service_fabric_obtain_token_on_app_service!_obtain_token_on_machine_learningr   r   r   r   _obtain_token_on_arc_obtain_token_on_azure_vm)rS   rJ   rU   r`   rN   Zarc_endpointr   r   r   rn     sN   
	
rn   c                 C   s2   |pt j|t j}|r|t j | |< d S d S r   )r   r'   r#   r$   r(   )r:   rJ   types_mappingZid_namer   r   r   _adjust_param  s   

r   c                 C   s   t d d|d}t|| | jtdddd |dd	id
}z(t|j	}|drH|drH|d t
|d |d|dddW S |W S  tjjy[   t d|j	  w )Nz0Obtaining token via managed identity on Azure VMz
2018-02-01api-versionrU   Z!AZURE_POD_IDENTITY_AUTHORITY_HOSTzhttp://169.254.169.254/z/metadata/identity/oauth2/tokenMetadatatruer:   headersr\   rE   rU   r]   r^   r\   rE   rU   r]   !IMDS emits unexpected payload: %s)rj   rk   r   r#   r   getenvstripjsonloadstextri   decoderJSONDecodeError)rS   rJ   rU   r:   resppayloadr   r   r   r     s6   



r   c              	   C   s   t d d|d}t||tjdtjdtjdid | j|||dd	d
}z;t	|j
}|drQ|drQ|d t|d tt  |d|dddW S dd|d|ddW S  tjjyq   t d|j
  w )zObtains token for
    `App Service <https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#rest-endpoint-reference>`_,
    Azure Functions, and Azure Automation.
    z9Obtaining token via managed identity on Azure App Servicez
2019-08-01r   r   Z	mi_res_idr   )r   r   )zX-IDENTITY-HEADERr   r   r\   rZ   rU   r]   r^   r   invalid_scopez{}, {}Z
statusCodemessagerd   Zerror_descriptionr   )rj   rk   r   r   r1   r2   r3   r#   r   r   r   ri   re   r<   r   r   )rS   endpointidentity_headerrJ   rU   r:   r   r   r   r   r   r     sB   



r   c                 C   s   t d d|d}t|| |d dkr d|v r |d|d< | j||d|id}z4t|j}|d	rV|d
rV|d	 t|d
 tt		  |d|dddW S dd
|dW S  tjjyo   t d|j  w )Nz>Obtaining token via managed identity on Azure Machine Learningz
2017-09-01r   r   r   Zclientidr[   r   r\   rZ   rU   r]   r^   r   r   z{}r   r   )rj   rk   r   popr#   r   r   r   ri   re   r<   r   r   )rS   r   r[   rJ   rU   r:   r   r   r   r   r   r   $  s2   



r   c             	   C   s   t d | j|dd d|||rd|ndd D d|id	}zCt|j}|d
rL|drL|d
 t|d tt		  |d|d dW S |di }	dddd}
|
|	dd|jdW S  tj
jyv   t d|j  w )zfObtains token for
    `Service Fabric <https://learn.microsoft.com/en-us/azure/service-fabric/>`_
    z<Obtaining token via managed identity on Azure Service Fabricc                 S   s   i | ]\}}|d ur||qS r   r   .0kvr   r   r   
<dictcomp>U  s    z3_obtain_token_on_service_fabric.<locals>.<dictcomp>z2019-07-01-preview,N)r   rU   Ztoken_sha256_to_refreshZxms_ccZSecretr   r\   rZ   rU   r]   r   rd   Zunauthorized_clientZinvalid_clientr   )ZSecretHeaderNotFoundZManagedIdentityNotFoundZArgumentNullOrEmptycodeinvalid_requestr   r   )rj   rk   r#   joinitemsr   r   r   ri   re   r   r   )rS   r   r   Zserver_thumbprintrU   r`   rN   r   r   rd   Zerror_mappingr   r   r   r   F  sJ   


r   z/var/opt/azcmagent/tokensz/%ProgramData%\AzureConnectedMachineAgent\Tokens)r   r   c                   @   r   )ArcPlatformNotSupportedErrorNr   r   r   r   r   r   |  r   r   c           
   	      s  t d | j|d|dddid}d  fdd	|j D  d
d}t|dkr5|d  dks=td	|jt
jtvrKtdt
j dtjtt
j tjtj|d d d }t|jdkrotdt|}| }W d    n1 sw   Y  | j|d|ddd	|dd}z't|j}	|	dr|	dr|	d t|	d |	dd|	ddW S W n tjjy   Y nw d|jdS ) Nz1Obtaining token via managed identity on Azure Arcz
2020-06-01r   r   r   r   zwww-authenticatec                    s&   i | ]\}}|   kr|  |qS r   )lowerr   Zwww_authr   r   r     s     z(_obtain_token_on_arc.<locals>.<dictcomp> =ra   r   zbasic realmz*Unrecognizable WWW-Authenticate header: {}z	Platform z was undefined and unsupportedr   z.keyi   z+Local key file shall not be larger than 4KBzBasic {})r   Authorizationr\   rE   r]   r^   rU   )r\   rE   r]   rU   r   r   )rj   rk   r#   r   r   splitlenr   r   r<   r   r   +_supported_arc_platforms_and_their_prefixesr   r   r   r   splitextbasenamestatst_sizeopenreadr   r   r   ri   r   r   )
rS   r   rU   r   	challengefilenamefr[   rc   r   r   r   r   r     sb   







r   r   )8ro   r   loggingr   r   re   urllib.parser   collectionsr   typingr   r   r   rL   r   Zindividual_cacher	   rF   Zthrottled_http_clientr
   r   Z
cloudshellr   	getLoggerr   rj   
ValueErrorr   r   r!   r&   r9   objectrH   r}   r   r   r   r   r   r   r   r   r>   rn   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sj   
/ h


51%

2
