
    ɯeiC                    F   d dl m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 d dlZddlmZmZmZ erBej"                  j$                  Zej&                  j(                  Zej*                  j,                  ZddlmZmZ dd	lmZmZ dd
lmZmZ  ej@                  e!      Z"dZ#dZ$dZ%e G d de
             Z&e G d d             Z'ddZ(ddZ)d dZ*d!d"dZ+	 d!	 	 	 d#dZ,d$dZ-	 	 	 	 	 	 d%dZ.d$dZ/	 d!	 	 	 	 	 d&dZ0	 d!	 	 	 	 	 d'dZ1d(dZ2	 	 	 	 d)	 	 	 	 	 	 	 	 	 	 	 d*dZ3y)+    )annotationsN)	b64encode)	dataclass)Enumunique   )boto3botocoreinstalled_boto)ER_INVALID_WIF_SETTINGSER_WIF_CREDENTIALS_NOT_FOUND)MissingDependencyErrorProgrammingError)SessionManagerSessionManagerFactoryzsnowflakecomputing.comz*api://fd3f753b-eed3-462c-b6a7-a4b5bb650aadzKhttp://169.254.169.254/computeMetadata/v1/instance/service-accounts/defaultc                  L    e Zd ZdZdZ	 dZ	 dZ	 dZ	 ed	d       Z	ed
d       Z
y)AttestationProviderz>A WIF provider implementation that can produce an attestation.AWSAZUREGCPOIDCc           
         	 t         | j                            S # t        $ r9 t        d|  ddj	                  t         j                                t              w xY w)zHConverts a string to a strongly-typed enum value of AttestationProvider.%Unknown workload_identity_provider: 'z'. Expected one of: z, msgerrno)r   upperKeyErrorr   joinall_string_valuesr   providers    ^/var/www/html/glpi_dashboard/venv/lib/python3.12/site-packages/snowflake/connector/wif_util.pyfrom_stringzAttestationProvider.from_string,   sw    	&x~~'788 	";H:EYZ^ZcZcdw  eJ  eJ  eL  [M  ZN  O- 	s
    AAc                 H    t         D  cg c]  } | j                   c} S c c} w )zDReturns a list of all string values of the AttestationProvider enum.)r   valuer!   s    r#   r    z%AttestationProvider.all_string_values7   s     0CC8CCCs   N)r"   strreturnr   )r(   	list[str])__name__
__module____qualname____doc__r   r   r   r   staticmethodr$   r         r#   r   r      sM    H
CuE[
CYD3  D Dr0   r   c                  ,    e Zd ZU ded<   ded<   ded<   y)WorkloadIdentityAttestationr   r"   r'   
credentialdictuser_identifier_componentsN)r*   r+   r,   __annotations__r/   r0   r#   r2   r2   =   s    !!O $$r0   r2   c                    	 t        j                  | ddi      }d|v rd|v st        d	t
              |d   |d   fS # t         j                  $ r}t        d| t              d}~ww xY w)
a  Extracts the 'iss' and 'sub' claims from the given JWT, without verifying the signature.

    Note: the real token verification (including signature verification) happens on the Snowflake side. The driver doesn't have
    the keys to verify these JWTs, and in any case that's not where the security boundary is drawn.

    We only decode the JWT here to get some basic claims, which will be used for a) a quick smoke test to ensure the token is well-formed,
    and b) to find the unique user being asserted and populate assertion_content. The latter may be used for logging
    and possibly caching.

    Any errors during token parsing will be bubbled up. Missing 'iss' or 'sub' claims will also raise an error.
    verify_signatureF)optionszInvalid JWT token: r   Nisssubz'Token is missing 'iss' or 'sub' claims.)jwtdecodeInvalidTokenErrorr   r   r   )jwt_strclaimses      r#   2extract_iss_and_sub_without_signature_verificationrB   D   s    
G.@%-HI VO9.
 	

 %=&-''    
%aS))
 	

s   > A*A%%A*c                     t         j                  j                  d      xs t         j                  j                  d      } | st               j	                         } | st        dt              | S )zJGet the current AWS workload's region, or raises an error if it's missing.
AWS_REGIONAWS_DEFAULT_REGIONzBNo AWS region was found. Ensure the application is running on AWS.r   )osenvirongetInstanceMetadataRegionFetcherretrieve_regionr   r   )regions    r#   get_aws_regionrL   a   s\     ZZ^^L)QRZZ^^<P-QF /0@@BT.
 	

 Mr0   c                n    |dk(  rd|  dS |dk(  rd|  dS |dk(  rd|  dS t        d| dt        	      )
a  Constructs the AWS STS hostname for a given region and partition.

    Args:
        region (str): The AWS region (e.g., 'us-east-1', 'cn-north-1').
        partition (str): The AWS partition (e.g., 'aws', 'aws-cn', 'aws-us-gov').

    Returns:
        str: The AWS STS hostname (e.g., 'sts.us-east-1.amazonaws.com')
             if a valid hostname can be constructed, otherwise raises a ProgrammingError.

    References:
    - https://docs.aws.amazon.com/sdkref/latest/guide/feature-sts-regionalized-endpoints.html
    - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_region-endpoints.html
    - https://docs.aws.amazon.com/general/latest/gr/sts.html
    awszsts.z.amazonaws.comzaws-cnz.amazonaws.com.cnz
aws-us-govzInvalid AWS partition: ''.r   )r   r   rK   	partitions     r#   get_aws_sts_hostnamerR   t   sl      E fX^,,	h	fX.//	l	"6(.)	
 *9+R8.
 	
r0   c                    t         j                  j                         }| xs g } | D ]T  }|j                  d      j	                  |d      }|d   }t         j                  j                  |d   |d   |d         }V |S )	zCreates a boto3 session with the appropriate credentials.

    If impersonation_path is provided, this uses the role at the end of the path. Otherwise, this uses the role attached to the current workload.
    stszidentity-federation-session)RoleArnRoleSessionNameCredentialsAccessKeyIdSecretAccessKeySessionToken)aws_access_key_idaws_secret_access_keyaws_session_token)r	   sessionSessionclientassume_role)impersonation_pathr^   arnresponsecredss        r#   get_aws_sessionrf      s    
 mm##%G+1r! 	
>>%(44)F 5 
 '--''#M2"'(9":#N3 ( 
	
 Nr0   c                n   t         st        dt              t        |       }|j	                         }|st        dt              t               }|j                  |      }t        ||      }t        dd| d|t        d      }t        |d	|      j                  |       |j                  |j                  t        |j                   j#                               d
}t%        t'        j(                  |      j+                  d            j-                  d      }t/        t0        j2                  |||d      S )zTries to create a workload identity attestation for AWS.

    If the application isn't running on AWS or no credentials were found, raises an error.
    zAWS Workload Identity Federation can't be used because boto3 or botocore optional dependency is not installed. Try installing missing dependencies.r   zbNo AWS credentials were found. Ensure the application is running on AWS with an IAM role attached.POSTzhttps://z-/?Action=GetCallerIdentity&Version=2011-06-15)HostzX-Snowflake-AudiencemethodurlheadersrT   )rl   rk   rm   utf-8rP   )r   r   r   rf   get_credentialsr   rL   get_partition_for_regionrR   
AWSRequestSNOWFLAKE_AUDIENCE	SigV4Authadd_authrl   rk   r4   rm   itemsr   jsondumpsencoder=   r2   r   r   )	rb   r^   	aws_credsrK   rQ   sts_hostnamerequestassertion_dictr3   s	            r#   create_aws_attestationr}      s*    $ f.
 	
 01G'')It.
 	
 F008I'	:L|n$QR $6
G i'009 {{..--/0N
 4::n5<<WEFMMgVJ 'Y-W r0   c                    	 | j                  dt         dddi      }|j                          |j                         d   S # t        $ r}t        d| dt        	      d
}~ww xY w)zGets a GCP access token from the metadata server.

    If the application isn't running on GCP or no credentials were found, raises an error.
    GETz/tokenMetadata-FlavorGooglerj   access_tokenz!Error fetching GCP access token: +. Ensure the application is running on GCP.r   N)r{   %GCP_METADATA_SERVICE_ACCOUNT_BASE_URLraise_for_statusrv   	Exceptionr   r   session_managerresrA   s      r#   get_gcp_access_tokenr      s    

%%89@!8 & 
 	xxz.)) 
3A36ab.
 	

s   ?A 	A%A  A%c                b   | st        dt              t        |      }| D cg c]  }d| 	 } }	 |j                  d| d    dd| dd	| d
d t        d      }|j                          |j                         d   S c c}w # t        $ r }t        d| d    d| dt              d
}~ww xY w)Gets a GCP identity token from the metadata server.

    If the application isn't running on GCP or no credentials were found, raises an error.
    z*Error: impersonation_path cannot be empty.r   zprojects/-/serviceAccounts/z)https://iamcredentials.googleapis.com/v1/z:generateIdTokenzBearer zapplication/json)AuthorizationzContent-TypeN)	delegatesaudience)rl   rm   rv   tokenzHError fetching GCP identity token for impersonated GCP service account 'z': r   )r   r   r   postrr   r   rv   r   )rb   r   current_sa_token	client_idr   rA   s         r#   (get_gcp_identity_token_via_impersonationr      s    <.
 	

 ,O<CU6?
%i[1 
"";<Nr<R;SScd#*+;*<!= 2
 04. # 

 	xxz'""!"  
Z[mnp[qZrruvwux  yd  e.
 	

s   B AB 	B.B))B.c                    	 | j                  dt         dt         ddi      }|j                          |j                  j                  d      S # t        $ r}t        d| dt        	      d
}~ww xY w)r   r   z/identity?audience=r   r   rj   rn   z#Error fetching GCP identity token: r   r   N)	r{   r   rr   r   contentr=   r   r   r   r   s      r#   get_gcp_identity_tokenr     s    

%%899LM_L`a!8 & 
 	{{!!'** 
5aS8cd.
 	

s   AA 	A3A..A3c                    |rt        ||       }nt        |       }t        |      \  }}t        t        j
                  |d|i      S )zTries to create a workload identity attestation for GCP.

    If the application isn't running on GCP or no credentials were found, raises an error.
    r;   )r   r   rB   r2   r   r   )r   rb   r?   _subjects        r#   create_gcp_attestationr   1  sO     :
 )9CGLJAw&5'*: r0   c                   ddi}d}d|  }t         j                  j                  d      }t         j                  j                  d      }|du}|r|st        dt        	      |}d
|i}d|  }t         j                  j                  d      }|r|d| z  }	 |j                  d| d| |      }	|	j                          |	j                         j                  d      }|st        dt        	      t        |      \  }}t        t        j                  |||d      S # t        $ r}
t        d|
 dt        	      d}
~
ww xY w)zTries to create a workload identity attestation for Azure.

    If the application isn't running on Azure or no credentials were found, raises an error.
    MetadataTruez5http://169.254.169.254/metadata/identity/oauth2/tokenz api-version=2018-02-01&resource=IDENTITY_ENDPOINTIDENTITY_HEADERNz7Managed identity is not enabled on this Azure function.r   zX-IDENTITY-HEADERz api-version=2019-08-01&resource=MANAGED_IDENTITY_CLIENT_IDz&client_id=r   ?rj   zError fetching Azure metadata: z-. Ensure the application is running on Azure.r   z9No access token found in Azure metadata service response.r:   r;   )rF   rG   rH   r   r   r{   r   r   rv   rB   r2   r   r   )snowflake_entra_resourcer   rm   url_without_query_stringquery_paramsidentity_endpointidentity_headeris_azure_functionsmanaged_identity_client_idr   rA   r?   issuerr   s                 r#   create_azure_attestationr   F  s    6"GV56N5OPL 

':;jjnn%67O*$6"M2  $5 &89:R9ST "$0L!M!+&@%ABB
%%+,Al^< & 

 	 hhjnn^,GK.
 	

 IQOFG&!!7F7,K   
1!4ab.
 	

s   )D 	E(D==Ec                    | st        dt              t        |       \  }}t        t        j
                  | ||d      S )zjTries to create an attestation using the given token.

    If this is not populated, raises an error.
    z9token must be provided if workload_identity_provider=OIDCr   r   )r   r   rB   r2   r   r   )r   r   r   s      r#   create_oidc_attestationr     sJ    
 K.
 	

 IOOFG&  %)H r0   c                   |xs t         }|r|j                         nt        j                  dd      }| t        j
                  k(  rt        |      S | t        j                  k(  rt        ||      S | t        j                  k(  rt        ||      S | t        j                  k(  rt        |      S t        d| j                   dt              )zEntry point to create an attestation using the given provider.

    If an explicit entra_resource was provided to the connector, this will be used. Otherwise, the default Snowflake Entra resource will be used.
    Tr   )use_poolingmax_retriesr   rO   r   ) DEFAULT_ENTRA_SNOWFLAKE_RESOURCEcloner   get_managerr   r   r}   r   r   r   r   r   r   r   r&   r   )r"   entra_resourcer   rb   r   s        r#   create_attestationr     s     $G'GN  	"..4QO  &***%&899	(..	.'HH	(,,	,%o7IJJ	(--	-&u--77GrJ.
 	
r0   )r?   r'   r(   ztuple[str, str])r(   r'   )rK   r'   rQ   r'   r(   r'   )N)rb   list[str] | None)rb   r   r(   r2   )r   r   r(   r'   )rb   r)   r   r   r(   r'   )r   r   rb   r   r(   r2   )r   r'   r   SessionManager | Noner(   r2   )r   
str | Noner(   r2   )NNNN)r"   r   r   r   r   r   rb   r   r   r   r(   r2   )4
__future__r   rv   loggingrF   base64r   dataclassesr   enumr   r   r<   r9   r	   r
   r   authrs   
awsrequestrq   utilsrI   	errorcoder   r   errorsr   r   r   r   r   	getLoggerr*   loggerrr   r   r   r   r2   rB   rL   rR   rf   r}   r   r   r   r   r   r   r   r/   r0   r#   <module>r      s   "   	  !  
 4 4''I$$//J$,NN$P$P! L < B			8	$- #O  Q &
 D$ D D: % % %(:&"
J, ,0.(. .b
,#
!#
4B#
#
L
0 ,0#( !. .2:!:*: !:z& "&+/-1
!

 
 )	

 +
 !
r0   