o
    i:                     @   sJ  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Zd dlm	Z	m
Z
mZ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mZmZmZ dd	lmZ eeZd
Z dZ!g dZ"dZ#dZ$G dd dZ%de&dee fddZ'de&fddZ(de&de&fddZ)de&dee& fddZ*dee& de+de&fddZ,dS )    )datetimeN)AnyDictListOptional)AccessTokenAccessTokenInfoTokenRequestOptions)ClientAuthenticationError   )CredentialUnavailableError)encode_base64resolve_tenant
within_dacvalidate_tenant_idvalidate_scope)log_get_tokenzAzure Developer CLI could not be found. Please visit https://aka.ms/azure-dev for installation instructions and then,once installed, authenticate to your Azure account using 'azd auth login'.zClaims challenges are not supported by the Azure Developer CLI version you are using. Please update to version 1.18.1 or later.)authtokenz--outputjsonz--no-promptZazdz_Please run 'azd auth login' from a command prompt to authenticate before using this credential.c                   @   s   e Zd ZdZdddddedeee  ded	dfd
dZdddZ	de
d	dfddZd ddZeddddedee dee de
d	ef
ddZedddedee d	efddZdddedee de
d	efddZdS )!AzureDeveloperCliCredentiala"	  Authenticates by requesting a token from the Azure Developer CLI.

    Azure Developer CLI is a command-line interface tool that allows developers to create, manage, and deploy
    resources in Azure. It's built on top of the Azure CLI and provides additional functionality specific
    to Azure developers. It allows users to authenticate as a user and/or a service principal against
    `Microsoft Entra ID <"https://learn.microsoft.com/entra/fundamentals/">`__.
    The AzureDeveloperCliCredential authenticates in a development environment and acquires a token on behalf of
    the logged-in user or service principal in Azure Developer CLI. It acts as the Azure Developer CLI logged-in user
    or service principal and executes an Azure CLI command underneath to authenticate the application against
    Microsoft Entra ID.

    To use this credential, the developer needs to authenticate locally in Azure Developer CLI using one of the
    commands below:

      * Run "azd auth login" in Azure Developer CLI to authenticate interactively as a user.
      * Run "azd auth login --client-id 'client_id' --client-secret 'client_secret' --tenant-id 'tenant_id'"
        to authenticate as a service principal.

    You may need to repeat this process after a certain time period, depending on the refresh token validity in your
    organization. Generally, the refresh token validity period is a few weeks to a few months.
    AzureDeveloperCliCredential will prompt you to sign in again.

    :keyword str tenant_id: Optional tenant to include in the token request.
    :keyword List[str] additionally_allowed_tenants: Specifies tenants in addition to the specified "tenant_id"
        for which the credential may acquire tokens. Add the wildcard value "*" to allow the credential to
        acquire tokens for any tenant the application can access.
    :keyword int process_timeout: Seconds to wait for the Azure Developer CLI process to respond. Defaults
        to 10 seconds.

    .. admonition:: Example:

        .. literalinclude:: ../samples/credential_creation_code_snippets.py
            :start-after: [START azure_developer_cli_credential]
            :end-before: [END azure_developer_cli_credential]
            :language: python
            :dedent: 4
            :caption: Create an AzureDeveloperCliCredential.
     N
   )	tenant_idadditionally_allowed_tenantsprocess_timeoutr   r   r   returnc                C   s&   |rt | || _|pg | _|| _d S N)r   r   _additionally_allowed_tenants_process_timeout)selfr   r   r    r!   Z/home/app/Keep/.python/lib/python3.10/site-packages/azure/identity/_credentials/azd_cli.py__init__P   s
   

z$AzureDeveloperCliCredential.__init__c                 C   s   | S r   r!   r    r!   r!   r"   	__enter__]      z%AzureDeveloperCliCredential.__enter__argsc                 G   s   d S r   r!   )r    r'   r!   r!   r"   __exit__`   r&   z$AzureDeveloperCliCredential.__exit__c                 C   s   dS )z#Calling this method is unnecessary.Nr!   r$   r!   r!   r"   closec   s    z!AzureDeveloperCliCredential.close)claimsr   scopesr*   kwargsc                O   s>   i }|r||d< |r||d< | j |d|i|}t|j|jS )a  Request an access token for `scopes`.

        This method is called automatically by Azure SDK clients. Applications calling this method directly must
        also handle token caching because this credential doesn't cache the tokens it acquires.

        :param str scopes: desired scope for the access token. This credential allows only one scope per request.
            For more information about scopes, see
            https://learn.microsoft.com/entra/identity-platform/scopes-oidc.
        :keyword str claims: additional claims required in the token, such as those returned in a resource provider's
            claims challenge following an authorization failure.
        :keyword str tenant_id: optional tenant to include in the token request.

        :return: An access token with the desired scopes.
        :rtype: ~azure.core.credentials.AccessToken

        :raises ~azure.identity.CredentialUnavailableError: the credential was unable to invoke
          the Azure Developer CLI.
        :raises ~azure.core.exceptions.ClientAuthenticationError: the credential invoked
          the Azure Developer CLI but didn't receive an access token.
        r   r*   options)_get_token_baser   r   
expires_on)r    r*   r   r+   r,   r-   Z
token_infor!   r!   r"   	get_tokenf   s   z%AzureDeveloperCliCredential.get_token)r-   r-   c                G   s   | j |d|iS )a  Request an access token for `scopes`.

        This is an alternative to `get_token` to enable certain scenarios that require additional properties
        on the token. This method is called automatically by Azure SDK clients. Applications calling this method
        directly must also handle token caching because this credential doesn't cache the tokens it acquires.

        :param str scopes: desired scopes for the access token. This method requires at least one scope.
            For more information about scopes, see https://learn.microsoft.com/entra/identity-platform/scopes-oidc.
        :keyword options: A dictionary of options for the token request. Unknown options will be ignored. Optional.
        :paramtype options: ~azure.core.credentials.TokenRequestOptions

        :rtype: ~azure.core.credentials.AccessTokenInfo
        :return: An AccessTokenInfo instance containing information about the token.

        :raises ~azure.identity.CredentialUnavailableError: the credential was unable to invoke
          the Azure Developer CLI.
        :raises ~azure.core.exceptions.ClientAuthenticationError: the credential invoked
          the Azure Developer CLI but didn't receive an access token.
        r-   )r.   )r    r-   r+   r!   r!   r"   get_token_info   s   z*AzureDeveloperCliCredential.get_token_infoc                O   s  |st d|r|dnd }|r|dnd }|rt| |D ]}t| q t }|D ]}|d|g7 }q-td| j|| jd|}|rK|d|g7 }|rU|dt	|g7 }t
|| j}	t|	}
|
st|	}|rj|}n
t|	}d| d	}t r}t|d
t|d
|
S )NzMissing scope in request. 
r   r*   z--scope)Zdefault_tenantr   r   z--tenant-idz--claimsz-Unexpected output from Azure Developer CLI: 'z'. 
To mitigate this issue, please refer to the troubleshooting guidelines here at https://aka.ms/azsdk/python/identity/azdevclicredential/troubleshoot.messager!   )
ValueErrorgetr   r   COMMAND_LINEcopyr   r   r   r   _run_commandr   parse_tokenextract_cli_error_messagesanitize_outputr   r   r
   )r    r-   r+   r,   r   r*   scopecommand_argsZtenantoutputr   Z	extractedr3   Zsanitized_outputr!   r!   r"   r.      sF   



z+AzureDeveloperCliCredential._get_token_base)r   r   )r   N)__name__
__module____qualname____doc__strr   r   intr#   r%   r   r(   r)   r   r   r0   r	   r   r1   r.   r!   r!   r!   r"   r   (   sV    *



$"r   r>   r   c              	   C   sP   zt | }t|d d}| }t|d t|W S  ttfy'   Y dS w )an  Parse to an AccessToken.

    In particular, convert the "expiresOn" value to epoch seconds. This value is a naive local datetime as returned by
    datetime.fromtimestamp.

    :param str output: The output of the Azure Developer CLI command.
    :return: An AccessToken or None if the output isn't valid.
    :rtype: azure.core.credentials.AccessToken or None
    Z	expiresOnz%Y-%m-%dT%H:%M:%SZr   N)	r   loadsr   strptime	timestampr   rD   KeyErrorr4   )r>   r   dtr/   r!   r!   r"   r9      s   

r9   c                  C   s.   t jdrtjd} | stdd| S dS )a   Invoke 'azd' from a directory controlled by the OS, not the executing program's directory.

    :return: The path to the directory.
    :rtype: str
    :raises ~azure.identity.CredentialUnavailableError: the SYSTEMROOT environment variable is not set.
    winZ
SYSTEMROOTzJAzure Developer CLI credential expects a 'SystemRoot' environment variabler2   z/bin)sysplatform
startswithosenvironr5   r   )pathr!   r!   r"   get_safe_working_dir   s   rQ   c                 C   s   t dd| S )zRedact tokens from CLI output to prevent error messages revealing them.

    :param str output: The output of the Azure Developer CLI command.
    :return: The output with tokens redacted.
    :rtype: str
    z\"token\": \"(.*?)(\"|$)z****)resub)r>   r!   r!   r"   r;      s   r;   c              	   C   s  g }|   D ]U}| }|sqzt|}W n
 tjy    Y qw t|tr[|d}t|trF|d}t|trF| rF|	|  q|d}t|tr[| r[|	|  q|s`dS |D ]}d|
 v rpt|  S qbt|dkr}t|d S t|d S )a  
    Extract a single, user-friendly message from azd consoleMessage JSON output.

    :param str output: The output from the Azure Developer CLI command.
    :return: A user-friendly error message if found, otherwise None.
    :rtype: Optional[str]

    Preference order:
    1) A message containing "Suggestion" (case-insensitive)
    2) The second message if multiple are present
    3) The first message if only one exists
    Returns None if no messages can be parsed.
    datar3   NZ
suggestion   r   )
splitlinesstripr   rE   JSONDecodeError
isinstancedictr5   rC   appendlowerr;   len)r>   messageslineobjrT   msgr!   r!   r"   r:     s<   




r:   r=   timeoutc           
   
   C   s  t t}|sttd|g|  }z#t }tjtj|dt	t
jdd|d}td| tj|fi |W S  tjy } zb|jdksM|jd urS|jdrSttd|d	|jpYd
|jp]d
}d|v rmd|vrmttd|d|v rwttd|t|jp|d
pt|jpd
p|jrt|jnd}t rt|d|t|d|d }~w ty } ztd|d d}	|	|d }~w ty } ztdd}	|	|d }~ww )Nr2   Ttrue)NO_COLOR)stderrstdincwduniversal_newlinesenvrc   z4Executing subprocess with the following arguments %s   z'azd' is not recognizedz{}
{}r   z,not logged in, run `azd auth login` to loginZAADSTSzunknown flag: --claimsz$Failed to invoke Azure Developer CLIzFailed to execute '{}'r   z(Failed to invoke the Azure Developer CLI)shutilwhichEXECUTABLE_NAMEr   CLI_NOT_FOUNDrQ   
subprocessPIPEDEVNULLr[   rN   rO   _LOGGERdebugcheck_outputCalledProcessError
returncoderf   rM   formatr>   NOT_LOGGED_INUNKNOWN_CLAIMS_FLAGr:   r;   r   r5   r
   OSError	Exception)
r=   rc   Zazd_pathr'   Zworking_directoryr,   exZcombined_textr3   errorr!   r!   r"   r8   3  sR   


	 
r8   )-r   r   loggingrN   rR   rl   rp   rK   typingr   r   r   r   Zazure.core.credentialsr   r   r	   Zazure.core.exceptionsr
   r   r   	_internalr   r   r   r   r   Z_internal.decoratorsr   	getLoggerr?   rs   ro   rz   r6   rn   ry   r   rC   r9   rQ   r;   r:   rD   r8   r!   r!   r!   r"   <module>   s:   
 +
0