U
    M8c~                     @   s  d Z ddlZddlZddlZddlmZ ddlmZmZ ddl	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mZmZmZmZmZmZmZmZmZ dd	lm Z m!Z! e"e#Z$d
Z%di iZ&G dd dZ'G dd de'Z(G dd de)eZ*G dd dZ+dS )zResolves regions and endpoints.

This module implements endpoint resolution, including resolving endpoints for a
given service and region and resolving the available endpoints for a service
in a specific AWS partition.
    N)Enum)UNSIGNED
xform_name)AUTH_TYPE_MAPSHAS_CRTCRT_SUPPORTED_AUTH_TYPES)EndpointProvider)EndpointProviderErrorEndpointVariantError!InvalidEndpointConfigurationErrorInvalidHostLabelErrorMissingDependencyExceptionNoRegionErrorParamValidationError$UnknownEndpointResolutionBuiltInNameUnknownRegionErrorUnknownSignatureVersionError*UnsupportedS3AccesspointConfigurationErrorUnsupportedS3ConfigurationErrorUnsupportedS3ControlArnError&UnsupportedS3ControlConfigurationError)ensure_booleaninstance_cachez{service}.{region}.{dnsSuffix}	endpointsc                   @   s,   e Zd ZdZdddZdd Zdd	d
ZdS )BaseEndpointResolverz3Resolves regions and endpoints. Must be subclassed.Nc                 C   s   t dS )a7  Resolves an endpoint for a service and region combination.

        :type service_name: string
        :param service_name: Name of the service to resolve an endpoint for
            (e.g., s3)

        :type region_name: string
        :param region_name: Region/endpoint name to resolve (e.g., us-east-1)
            if no region is provided, the first found partition-wide endpoint
            will be used if available.

        :rtype: dict
        :return: Returns a dict containing the following keys:
            - partition: (string, required) Resolved partition name
            - endpointName: (string, required) Resolved endpoint name
            - hostname: (string, required) Hostname to use for this endpoint
            - sslCommonName: (string) sslCommonName to use for this endpoint.
            - credentialScope: (dict) Signature version 4 credential scope
              - region: (string) region name override when signing.
              - service: (string) service name override when signing.
            - signatureVersions: (list<string>) A list of possible signature
              versions, including s3, v4, v2, and s3v4
            - protocols: (list<string>) A list of supported protocols
              (e.g., http, https)
            - ...: Other keys may be included as well based on the metadata
        NNotImplementedError)selfservice_nameregion_name r!   4/tmp/pip-unpacked-wheel-ozje0y8b/botocore/regions.pyconstruct_endpoint6   s    z'BaseEndpointResolver.construct_endpointc                 C   s   t dS )zLists the partitions available to the endpoint resolver.

        :return: Returns a list of partition names (e.g., ["aws", "aws-cn"]).
        Nr   r   r!   r!   r"   get_available_partitionsS   s    z-BaseEndpointResolver.get_available_partitionsawsFc                 C   s   t dS )a  Lists the endpoint names of a particular partition.

        :type service_name: string
        :param service_name: Name of a service to list endpoint for (e.g., s3)

        :type partition_name: string
        :param partition_name: Name of the partition to limit endpoints to.
            (e.g., aws for the public AWS endpoints, aws-cn for AWS China
            endpoints, aws-us-gov for AWS GovCloud (US) Endpoints, etc.

        :type allow_non_regional: bool
        :param allow_non_regional: Set to True to include endpoints that are
             not regional endpoints (e.g., s3-external-1,
             fips-us-gov-west-1, etc).
        :return: Returns a list of endpoint names (e.g., ["us-east-1"]).
        Nr   )r   r   partition_nameallow_non_regionalr!   r!   r"   get_available_endpointsZ   s    z,BaseEndpointResolver.get_available_endpoints)N)r&   F)__name__
__module____qualname____doc__r#   r%   r)   r!   r!   r!   r"   r   3   s   
   r   c                   @   s   e Zd ZdZddgZd%ddZd&dd	Zd
d Zd'ddZd(ddZ	d)ddZ
dd Zd*ddZdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ ZdS )+EndpointResolverz7Resolves endpoints based on partition endpoint metadatazaws-isoz	aws-iso-bFc                 C   s    d|krt d|| _|| _dS )a  
        :type endpoint_data: dict
        :param endpoint_data: A dict of partition data.

        :type uses_builtin_data: boolean
        :param uses_builtin_data: Whether the endpoint data originates in the
            package's data directory.
        
partitionsz%Missing "partitions" in endpoint dataN)
ValueError_endpoint_datauses_builtin_data)r   endpoint_datar2   r!   r!   r"   __init__u   s    	zEndpointResolver.__init__r&   c                 C   sB   | j d D ]2}|d |krq
|d }||kr.q
|| d   S d S )Nr/   	partitionservicesr   )r1   )r   r   r'   r5   r6   r!   r!   r"   get_service_endpoints_data   s    z+EndpointResolver.get_service_endpoints_datac                 C   s&   g }| j d D ]}||d  q|S )Nr/   r5   )r1   append)r   resultr5   r!   r!   r"   r%      s    z)EndpointResolver.get_available_partitionsNc                 C   s   g }| j d D ]}|d |kr q|d }||kr2q|| d }|D ]J}	|	|d k}
|rz|
rz| ||	 |}|r||	 qB|s|
rB||	 qBq|S )Nr/   r5   r6   r   regions)r1   _retrieve_variant_datar8   )r   r   r'   r(   endpoint_variant_tagsr9   r5   r6   Zservice_endpointsendpoint_nameZis_regional_endpointZvariant_datar!   r!   r"   r)      s(     z(EndpointResolver.get_available_endpointsc                 C   s\   | j d D ]L}|d |kr
|rJ| |d|}|rVd|krV|d   S q
|d   S q
d S )Nr/   r5   defaults	dnsSuffix)r1   r;   get)r   r'   r<   r5   variantr!   r!   r"   get_partition_dns_suffix   s     z)EndpointResolver.get_partition_dns_suffixc           	      C   s   |dkr|r|d krd}|d k	rhd }| j d D ]}|d |kr.|}q.|d k	rd| |||||d}|S d S | j d D ]6}|r|d | jkrqr| |||||}|rr|  S qrd S )Ns3z	us-east-1r/   r5   T)r1   _endpoint_for_partition!_UNSUPPORTED_DUALSTACK_PARTITIONS)	r   r   r    r'   use_dualstack_endpointuse_fips_endpointZvalid_partitionr5   r9   r!   r!   r"   r#      sN    	z#EndpointResolver.construct_endpointc                 C   s8   | j d D ]}| ||r
|d   S q
t|ddd S )Nr/   r5   z,No partition found for provided region_name.)r    	error_msg)r1   _region_matchr   )r   r    r5   r!   r!   r"   get_partition_for_region   s    z)EndpointResolver.get_partition_for_regionc                 C   s   |d }|r,|| j kr,d| }tdg|d|d |t}	|d kr\d|	krV|	d }nt |||	|||d}
||	d kr| jf |
S | ||s|r|	d}|	d	d
}|r|std||| ||
d< | jf |
S td|| | jf |
S d S )Nr5   z@Dualstack endpoints are currently not supported for %s partition	dualstacktagsrH   r6   ZpartitionEndpoint)r5   r   service_datar=   rF   rG   r   ZisRegionalizedTz'Using partition endpoint for %s, %s: %sr=   z*Creating a regex based endpoint for %s, %s)	rE   r   r@   DEFAULT_SERVICE_DATAr   _resolverI   LOGdebug)r   r5   r   r    rF   rG   Zforce_partitionr'   rH   rN   Zresolve_kwargsZpartition_endpointZis_regionalizedr!   r!   r"   rD      sZ    	 


z(EndpointResolver._endpoint_for_partitionc                 C   s0   ||d krdS d|kr,t |d |S dS )Nr:   TZregionRegexF)recompilematch)r   r5   r    r!   r!   r"   rI   9  s
    zEndpointResolver._region_matchc                 C   s>   | dg }|D ](}t|d t|kr| }|  S qd S )NvariantsrM   )r@   setcopy)r   r3   rM   rV   rA   r9   r!   r!   r"   r;   @  s
    z'EndpointResolver._retrieve_variant_datac                 C   s$   g }|r| d |r | d |S )NrK   Zfips)r8   )r   rF   rG   rM   r!   r!   r"   _create_tag_listG  s    

z!EndpointResolver._create_tag_listc                 C   s4   i }|||fD ] }|  ||}|r| || q|S N)r;   _merge_keys)r   rM   r3   service_defaultspartition_defaultsr9   rV   rA   r!   r!   r"   _resolve_variantO  s    z!EndpointResolver._resolve_variantc                 C   s$  | di  |i }| dr,td|  | di }| di }	| ||}
|
r| |
|||	}|i krd| d| }t|
|d| || n|}d|kr|d |d< |d	 |d	< ||d
< | || | |	| | ||d |||d |d< d|kr | ||d |||d |d< |S )Nr   
deprecatedz5Client is configured with the deprecated endpoint: %sr>   zEndpoint does not exist for z in region rL   r?   r5   ZendpointNamehostnameZsslCommonName)r@   rQ   warningrY   r^   r   r[   _expand_template)r   r5   r   rN   r=   rF   rG   r3   r\   r]   rM   r9   rH   r!   r!   r"   rP   Y  s`    	 
   
zEndpointResolver._resolvec                 C   s"   |D ]}||kr|| ||< qd S rZ   r!   )r   Z	from_datar9   keyr!   r!   r"   r[     s    zEndpointResolver._merge_keysc                 C   s   |j |||dS )N)Zserviceregionr?   )format)r   r5   templater   r=   r?   r!   r!   r"   rb     s
      z!EndpointResolver._expand_template)F)r&   )r&   FN)N)NNFF)F)r*   r+   r,   r-   rE   r4   r7   r%   r)   rB   r#   rJ   rD   rI   r;   rY   r^   rP   r[   rb   r!   r!   r!   r"   r.   p   s4   

		   
 
    
2 
A
Br.   c                   @   s8   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdS )EndpointResolverBuiltinszAWS::RegionzAWS::UseFIPSzAWS::UseDualStackzAWS::STS::UseGlobalEndpointzAWS::S3::UseGlobalEndpointzAWS::S3::AcceleratezAWS::S3::ForcePathStylezAWS::S3::UseArnRegionzAWS::S3Control::UseArnRegionz'AWS::S3::DisableMultiRegionAccessPointszSDK::EndpointN)r*   r+   r,   Z
AWS_REGIONZAWS_USE_FIPSZAWS_USE_DUALSTACKZAWS_STS_USE_GLOBAL_ENDPOINTZAWS_S3_USE_GLOBAL_ENDPOINTZAWS_S3_ACCELERATEZAWS_S3_FORCE_PATH_STYLEZAWS_S3_USE_ARN_REGIONZAWS_S3CONTROL_USE_ARN_REGIONZAWS_S3_DISABLE_MRAPZSDK_ENDPOINTr!   r!   r!   r"   rg     s   rg   c                   @   s   e Zd ZdZd$ddZdd Zdd	 Z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dd Zdd Zdd Zd d! Zd"d# ZdS )%EndpointRulesetResolverz5Resolves endpoints using a service's endpoint rulesetTNc	           	      C   sH   t ||d| _| jjj| _|| _|| _|| _|| _|| _	|| _
i | _d S )N)Zruleset_datapartition_data)r	   	_providerZruleset
parameters_param_definitions_service_model	_builtins_client_context_event_emitter_use_ssl_requested_auth_schemeZ_instance_cache)	r   Zendpoint_ruleset_datari   Zservice_modelbuiltinsZclient_contextZevent_emitterZuse_sslZrequested_auth_schemer!   r!   r"   r4     s    z EndpointRulesetResolver.__init__c              
   C   s   |dkri }|dkri }|  |||}td|  z| jjf |}W n@ tk
r } z"| ||}|dkrp n||W 5 d}~X Y nX td|j  | js|j	dr|j
d|jdd  d}|j
dd	 |j D d
}|S )zAInvokes the provider with params defined in the service's rulesetNz-Calling endpoint provider with parameters: %szEndpoint provider result: %szhttps://zhttp://   )urlc                 S   s   i | ]\}}||d  qS )r   r!   ).0rc   valr!   r!   r"   
<dictcomp>  s     z>EndpointRulesetResolver.construct_endpoint.<locals>.<dictcomp>)headers)_get_provider_paramsrQ   rR   rj   Zresolve_endpointr
   #ruleset_error_to_botocore_exceptionru   rq   
startswith_replacery   items)r   operation_model	call_argsrequest_contextprovider_paramsZprovider_resultexZbotocore_exceptionr!   r!   r"   r#     sF       z*EndpointRulesetResolver.construct_endpointc           	      C   sl   i }|  |||}| j D ]J\}}| j|||d}|dkrV|jdk	rV| j|j|d}|dk	r|||< q|S )a  Resolve a value for each parameter defined in the service's ruleset

        The resolution order for parameter values is:
        1. Operation-specific static context values from the service definition
        2. Operation-specific dynamic context values from API parameters
        3. Client-specific context parameters
        4. Built-in values such as region, FIPS usage, ...
        )
param_namer   r   N)builtin_namers   )_get_customized_builtinsrl   r~   _resolve_param_from_contextbuiltin_resolve_param_as_builtin)	r   r   r   r   r   customized_builtinsr   Z	param_defZ	param_valr!   r!   r"   rz     s(      
z,EndpointRulesetResolver._get_provider_paramsc                 C   s<   |  ||}|d k	r|S | |||}|d k	r2|S | |S rZ   )&_resolve_param_as_static_context_param'_resolve_param_as_dynamic_context_param&_resolve_param_as_client_context_param)r   r   r   r   ZstaticZdynamicr!   r!   r"   r   5  s       z3EndpointRulesetResolver._resolve_param_from_contextc                 C   s   |  |}||S rZ   )_get_static_context_paramsr@   )r   r   r   Zstatic_ctx_paramsr!   r!   r"   r   D  s    
z>EndpointRulesetResolver._resolve_param_as_static_context_paramc                 C   s(   |  |}||kr$|| }||S d S rZ   )_get_dynamic_context_paramsr@   )r   r   r   r   Zdynamic_ctx_paramsmember_namer!   r!   r"   r   J  s    
z?EndpointRulesetResolver._resolve_param_as_dynamic_context_paramc                 C   s(   |   }||kr$|| }| j|S d S rZ   )_get_client_context_paramsro   r@   )r   r   Zclient_ctx_paramsZclient_ctx_varnamer!   r!   r"   r   R  s    z>EndpointRulesetResolver._resolve_param_as_client_context_paramc                 C   s"   |t j krt|d||S )Nname)rg   __members__valuesr   r@   )r   r   rs   r!   r!   r"   r   X  s    
z1EndpointRulesetResolver._resolve_param_as_builtinc                 C   s   dd |j D S )z=Mapping of param names to static param value for an operationc                 S   s   i | ]}|j |jqS r!   )r   valuerv   paramr!   r!   r"   rx   `  s    zFEndpointRulesetResolver._get_static_context_params.<locals>.<dictcomp>)Zstatic_context_parametersr   r   r!   r!   r"   r   ]  s    z2EndpointRulesetResolver._get_static_context_paramsc                 C   s   dd |j D S )z7Mapping of param names to member names for an operationc                 S   s   i | ]}|j |jqS r!   )r   r   r   r!   r!   r"   rx   h  s    zGEndpointRulesetResolver._get_dynamic_context_params.<locals>.<dictcomp>)Zcontext_parametersr   r!   r!   r"   r   e  s    z3EndpointRulesetResolver._get_dynamic_context_paramsc                 C   s   dd | j jD S )z7Mapping of param names to client configuration variablec                 S   s   i | ]}|j t|j qS r!   )r   r   r   r!   r!   r"   rx   p  s    zFEndpointRulesetResolver._get_client_context_params.<locals>.<dictcomp>)rm   Zclient_context_parametersr$   r!   r!   r"   r   m  s    z2EndpointRulesetResolver._get_client_context_paramsc                 C   s6   | j j }t| j}| jjd| ||||d |S )Nzbefore-endpoint-resolution.%s)rs   modelparamscontext)rm   
service_idZ	hyphenizerX   rn   rp   emit)r   r   r   r   r   r   r!   r!   r"   r   u  s    z0EndpointRulesetResolver._get_customized_builtinsc                    s  t |trt|dkrtdtdddd |D  j  jtkrPdi fS  fdd|D } jd	k	rzt	 fd
d|D \}}W n t
k
r   d	i f Y S X n~zt	dd |D \}}W nb t
k
r&   d}dd |D }ts tdd |D }|rtddntd|dY nX i }d|krD|d |d< n,d|krpt|d dkrp|d d |d< d|kr|j|d d d|krt|d |d< td|d || ||fS )a  Convert an Endpoint's authSchemes property to a signing_context dict

        :type auth_schemes: list
        :param auth_schemes: A list of dictionaries taken from the
            ``authSchemes`` property of an Endpoint object returned by
            ``EndpointProvider``.

        :rtype: str, dict
        :return: Tuple of auth type string (to be used in
            ``request_context['auth_type']``) and signing context dict (for use
            in ``request_context['signing']``).
        r   z&auth_schemes must be a non-empty list.z_Selecting from endpoint provider's list of auth schemes: %s. User selected auth scheme is: "%s"z, c                 S   s   g | ]}d | d d qS )"r   )r@   rv   sr!   r!   r"   
<listcomp>  s     zGEndpointRulesetResolver.auth_schemes_to_signing_ctx.<locals>.<listcomp>nonec                    s"   g | ]}|d   |d  iqS r   )_strip_sig_prefixrv   schemer$   r!   r"   r     s   Nc                 3   s*   | ]"}   j|d  r j|fV  qdS r   N)._does_botocore_authname_match_ruleset_authnamerr   r   r$   r!   r"   	<genexpr>  s    zFEndpointRulesetResolver.auth_schemes_to_signing_ctx.<locals>.<genexpr>c                 s   s&   | ]}|d  t kr|d  |fV  qdS r   )r   r   r!   r!   r"   r     s   Fc                 S   s   g | ]}|d  qS r   r!   r   r!   r!   r"   r     s     c                 s   s   | ]}|t kV  qd S rZ   r   r   r!   r!   r"   r     s   zbThis operation requires an additional dependency. Use pip install botocore[crt] before proceeding.msg)Zsignature_versionZsigningRegionrd   ZsigningRegionSetZsigningName)Zsigning_nameZdisableDoubleEncodingz?Selected auth type "%s" as "%s" with signing context params: %sr   )
isinstancelistlen	TypeErrorrQ   rR   joinrr   r   nextStopIterationr   anyr   r   updater   )r   Zauth_schemesr   r   Zfixable_with_crtZauth_type_optionsZsigning_contextr!   r$   r"   auth_schemes_to_signing_ctx  sp    






z3EndpointRulesetResolver.auth_schemes_to_signing_ctxc                 C   s   | dr|dd S |S )z6Normalize auth type names by removing any "sig" prefixsig   N)r|   )r   Z	auth_namer!   r!   r"   r     s    z)EndpointRulesetResolver._strip_sig_prefixc                 C   s>   |  |}|dd }|dkr6|dr6|dd }||kS )a\  
        Whether a valid string provided as signature_version parameter for
        client construction refers to the same auth methods as a string
        returned by the endpoint ruleset provider. This accounts for:

        * The ruleset prefixes auth names with "sig"
        * The s3 and s3control rulesets don't distinguish between v4[a] and
          s3v4[a] signers
        * The v2, v3, and HMAC v1 based signers (s3, s3-*) are botocore legacy
          features and do not exist in the rulesets
        * Only characters up to the first dash are considered

        Example matches:
        * v4, sigv4
        * v4, v4
        * s3v4, sigv4
        * s3v7, sigv7 (hypothetical example)
        * s3v4a, sigv4a
        * s3v4-query, sigv4

        Example mismatches:
        * v4a, sigv4
        * s3, sigv4
        * s3-presign-post, sigv4
        -r   rC      N)r   splitr|   )r   ZbotonameZrsnamer!   r!   r"   r     s
    
zFEndpointRulesetResolver._does_botocore_authname_match_ruleset_authnamec                 C   sz  |j d}|dkrdS |drXz|dd }W n tk
rL   |}Y nX t|dS | jj}|dkr|dksx|d	krt|d
S |ds|ds|ds|ds|ds|drt	|d
S |
 drt|dS |dkrB|dr|d}t||dS |ds$|dr.t|d
S |dkrBt|dS |dkrv|drbt|d
S |dkrvt|d
S dS )zAttempts to translate ruleset errors to pre-existing botocore
        exception types by string matching exception strings.
        r   NzInvalid region in ARN: `   )labelrC   z/S3 Object Lambda does not support S3 Acceleratez#Accelerate cannot be used with FIPSr   zS3 Outposts does not supportzS3 MRAP does not supportz!S3 Object Lambda does not supportzAccess Points do not supportzInvalid configuration:z#Client was configured for partitionzinvalid arn:)reportZ	s3controlzInvalid ARN:ZBucket)arnr   z!AccountId is required but not seteventszUInvalid Configuration: FIPS is not supported with EventBridge multi-region endpoints.z&EndpointId must be a valid host label.)kwargsr@   r|   r   
IndexErrorr   rm   r   r   r   lowerr   r   r   r   )r   Zruleset_exceptionr   r   r   r   r   r!   r!   r"   r{   	  sb    














z;EndpointRulesetResolver.ruleset_error_to_botocore_exception)TN)r*   r+   r,   r-   r4   r#   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r{   r!   r!   r!   r"   rh     s,   
  
2!


a rh   ),r-   rX   loggingrS   enumr   Zbotocorer   r   Zbotocore.authr   r   Zbotocore.crtr   Zbotocore.endpoint_providerr	   Zbotocore.exceptionsr
   r   r   r   r   r   r   r   r   r   r   r   r   r   Zbotocore.utilsr   r   	getLoggerr*   rQ   ZDEFAULT_URI_TEMPLATErO   r   r.   strrg   rh   r!   r!   r!   r"   <module>   s&   @
=  :