
    Pew                         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 d dl	m
Z
 d dlmZmZmZ d dlmZmZ d dlmZ  G d d      Z G d	 d
      Zd ZddZ G d d      Zd Z	 ddZd Z	 ddZd Zy)    N)create_request_objectprepare_request_dict)OrderedDict)UnknownClientMethodErrorUnknownSignatureVersionError UnsupportedSignatureVersionError)	ArnParserdatetime2timestamp)fix_s3_hostc                       e Zd ZdZ	 ddZed        Zed        Zed        ZddZ		 	 	 	 ddZ
d	 Zd
 Z	 ddZeZ	 	 	 ddZy)RequestSignera0  
    An object to sign requests before they go out over the wire using
    one of the authentication mechanisms defined in ``auth.py``. This
    class fires two events scoped to a service and operation name:

    * choose-signer: Allows overriding the auth signer name.
    * before-sign: Allows mutating the request before signing.

    Together these events allow for customization of the request
    signing pipeline, including overrides, request path manipulation,
    and disabling signing per operation.


    :type service_id: botocore.model.ServiceId
    :param service_id: The service id for the service, e.g. ``S3``

    :type region_name: string
    :param region_name: Name of the service region, e.g. ``us-east-1``

    :type signing_name: string
    :param signing_name: Service signing name. This is usually the
                         same as the service name, but can differ. E.g.
                         ``emr`` vs. ``elasticmapreduce``.

    :type signature_version: string
    :param signature_version: Signature name like ``v4``.

    :type credentials: :py:class:`~botocore.credentials.Credentials`
    :param credentials: User credentials with which to sign requests.

    :type event_emitter: :py:class:`~botocore.hooks.BaseEventHooks`
    :param event_emitter: Extension mechanism to fire events.
    Nc                     || _         || _        || _        || _        || _        || _        t        j                  |      | _        y N)	_region_name_signing_name_signature_version_credentials_auth_token_service_idweakrefproxy_event_emitter)self
service_idregion_namesigning_namesignature_versioncredentialsevent_emitter
auth_tokens           2/usr/lib/python3/dist-packages/botocore/signers.py__init__zRequestSigner.__init__D   sG     ()"3'%% &mmM:    c                     | j                   S r   )r   r   s    r!   r   zRequestSigner.region_nameX   s       r#   c                     | j                   S r   )r   r%   s    r!   r   zRequestSigner.signature_version\   s    &&&r#   c                     | j                   S r   )r   r%   s    r!   r   zRequestSigner.signing_name`   s    !!!r#   c                 &    | j                  ||      S r   )sign)r   operation_namerequestkwargss       r!   handlerzRequestSigner.handlerd   s    
 yy11r#   c           	         |}|| j                   }|| j                  }| j                  |||j                        }| j                  j                  dj                  | j                  j                         |      ||| j                   || |       |t        j                  k7  r|||d}	|||	d<   |j                  j                  di       }
|s|
j                  d      r|
d   |	d<   |
j                  d	      r|
d	   |	d	<   |
j                  d
      | j                  |	|
d
   |
d          	  | j                  di |	}|j!                  |       yy# t        $ r}|dk7  rt        |      |d}~ww xY w)a<  Sign a request before it goes out over the wire.

        :type operation_name: string
        :param operation_name: The name of the current operation, e.g.
                               ``ListBuckets``.
        :type request: AWSRequest
        :param request: The request object to be sent over the wire.

        :type region_name: str
        :param region_name: The region to sign the request for.

        :type signing_type: str
        :param signing_type: The type of signing to perform. This can be one of
            three possible values:

            * 'standard'     - This should be used for most requests.
            * 'presign-url'  - This should be used when pre-signing a request.
            * 'presign-post' - This should be used when pre-signing an S3 post.

        :type expires_in: int
        :param expires_in: The number of seconds the presigned url is valid
            for. This parameter is only valid for signing type 'presign-url'.

        :type signing_name: str
        :param signing_name: The name to use for the service when signing.
        Nzbefore-sign.{}.{})r+   r   r   r   request_signerr*   )r   r   r   expiressigningregionr   r   identity_cache	cache_keystandardr    )r   r   _choose_signercontextr   emitformatr   	hyphenizebotocoreUNSIGNEDget_resolve_identity_cacheget_auth_instancer   r   add_auth)r   r*   r+   r   signing_type
expires_inr   explicit_region_namer   r,   signing_contextauthes                r!   r)   zRequestSigner.signk   s   F  +++K--L //L'//

 	  &&  **,n %))/) 	! 
	
  1 11 ,*%6F
 %$.y!%oo11)R@O'O,?,?,I(7(A}%"">2)8)H~&""#34@,,#$45#K0
-t--77 MM'"; 2* 0 :-:*;  Gs   +E 	E1E,,E1c                     ||d<   ||d<   y )Nr3   r4   r7   )r   r,   cacher4   s       r!   r@   z%RequestSigner._resolve_identity_cache   s    #( '{r#   c                 D   ddd}|j                  |d      }|j                  d      xs | j                  }|j                  di       }|j                  d| j                        }|j                  d| j                        }	|t        j
                  ur|j                  |      s||z  }| j                  j                  d	j                  | j                  j                         |      ||	||
      \  }
}|*|}|t        j
                  ur|j                  |      s||z  }|S )ai  
        Allow setting the signature version via the choose-signer event.
        A value of `botocore.UNSIGNED` means no signing will be performed.

        :param operation_name: The operation to sign.
        :param signing_type: The type of signing that the signer is to be used
            for.
        :return: The signature version to sign with.
        z-presign-postz-query)presign-postpresign-url 	auth_typer1   r   r2   zchoose-signer.{}.{})r   r   r   r9   )r?   r   r   r   r=   r>   endswithr   emit_until_responser;   r   r<   )r   r*   rC   r9   signing_type_suffix_mapsuffixr   r1   r   r   r-   responses               r!   r8   zRequestSigner._choose_signer   s3    ,##
 ),,\2> $KK4O8O8O++i,{{>43E3EFkk(D,=,=>X%6%66%..v6' //CC!((  **,n &#/ D 
  ( "):)::)226:!V+!  r#   c                 D   || j                   }t        j                  j                  j	                  |      }|t        |      |j                  du r2d}| j                  | j                  j                         } ||      }|S | j                  }t        |dd      du r|d   }	|d   }
|	j                  |
      }|d= d}||j                         }||d<   |j                  r4| j                  t        j                  j!                         ||d<   ||d	<    |d
i |}|S )a  
        Get an auth instance which can be used to sign a request
        using the given signature version.

        :type signing_name: string
        :param signing_name: Service signing name. This is usually the
                             same as the service name, but can differ. E.g.
                             ``emr`` vs. ``elasticmapreduce``.

        :type region_name: string
        :param region_name: Name of the service region, e.g. ``us-east-1``

        :type signature_version: string
        :param signature_version: Signature name like ``v4``.

        :rtype: :py:class:`~botocore.auth.BaseSigner`
        :return: Auth instance to sign a request.
        Nr6   TREQUIRES_IDENTITY_CACHEr3   r4   r   r   service_namer7   )r   r=   rG   AUTH_TYPE_MAPSr?   r   REQUIRES_TOKENr   get_frozen_tokenr   getattrget_credentialsget_frozen_credentialsREQUIRES_REGIONr   
exceptionsNoRegionError)r   r   r   r   r,   clsfrozen_tokenrG   r   rJ   keyfrozen_credentialss               r!   rA   zRequestSigner.get_auth_instance   sI   * $ $ 7 7mm**../@A;."3  %L+#//@@B|$DK''3148D@+,E%C//4K{# ""!,!C!C!E 2}  ())7799$/F=!%1F>"}V}r#   c                 |    t        |      }| j                  |||d||       |j                          |j                  S )a  Generates a presigned url

        :type request_dict: dict
        :param request_dict: The prepared request dictionary returned by
            ``botocore.awsrequest.prepare_request_dict()``

        :type operation_name: str
        :param operation_name: The operation being signed.

        :type expires_in: int
        :param expires_in: The number of seconds the presigned url is valid
            for. By default it expires in an hour (3600 seconds)

        :type region_name: string
        :param region_name: The region name to sign the presigned url.

        :type signing_name: str
        :param signing_name: The name to use for the service when signing.

        :returns: The presigned url
        rM   )r   r)   prepareurl)r   request_dictr*   rD   r   r   r+   s          r!   generate_presigned_urlz$RequestSigner.generate_presigned_url:  sB    : (5			
 	{{r#   r   NN)Nr5   NN)  NN)__name__
__module____qualname____doc__r"   propertyr   r   r   r-   r)   r@   r8   rA   get_authri   r7   r#   r!   r   r   !   s     T ;( ! ! ' ' " "2 X#t(0!f <@:z !H (r#   r   c                   4    e Zd ZdZd ZddZd Z	 ddZd Zy)	CloudFrontSignera  A signer to create a signed CloudFront URL.

    First you create a cloudfront signer based on a normalized RSA signer::

        import rsa
        def rsa_signer(message):
            private_key = open('private_key.pem', 'r').read()
            return rsa.sign(
                message,
                rsa.PrivateKey.load_pkcs1(private_key.encode('utf8')),
                'SHA-1')  # CloudFront requires SHA-1 hash
        cf_signer = CloudFrontSigner(key_id, rsa_signer)

    To sign with a canned policy::

        signed_url = cf_signer.generate_signed_url(
            url, date_less_than=datetime(2015, 12, 1))

    To sign with a custom policy::

        signed_url = cf_signer.generate_signed_url(url, policy=my_policy)
    c                      || _         || _        y)a  Create a CloudFrontSigner.

        :type key_id: str
        :param key_id: The CloudFront Key Pair ID

        :type rsa_signer: callable
        :param rsa_signer: An RSA signer.
               Its only input parameter will be the message to be signed,
               and its output will be the signed content as a binary string.
               The hash algorithm needed by CloudFront is SHA-1.
        N)key_id
rsa_signer)r   ru   rv   s      r!   r"   zCloudFrontSigner.__init__}  s     $r#   Nc                    |duxr |du}|du xr |du }|s|rd}t        |      || j                  ||      }t        |t              r|j	                  d      }|dt        t        |            z  g}n$d| j                  |      j                  d      z  g}| j                  |      }|j                  d| j                  |      j                  d       d| j                   g       | j                  ||      S )a  Creates a signed CloudFront URL based on given parameters.

        :type url: str
        :param url: The URL of the protected object

        :type date_less_than: datetime
        :param date_less_than: The URL will expire after that date and time

        :type policy: str
        :param policy: The custom policy, possibly built by self.build_policy()

        :rtype: str
        :return: The signed URL.
        Nz=Need to provide either date_less_than or policy, but not bothutf8z
Expires=%sz	Policy=%sz
Signature=zKey-Pair-Id=)
ValueErrorbuild_policy
isinstancestrencodeintr
   _url_b64encodedecoderv   extendru   
_build_url)	r   rg   date_less_thanpolicyboth_args_suppliedneither_arg_suppliedrH   params	signatures	            r!   ri   z'CloudFrontSigner.generate_presigned_url  s    ,47NF$<N-5H&D.!5OAQ-%&&sN;Ffc"]]6*F%"S);N)K%LLMF!D$7$7$?$F$Fv$NNOFOOF+	T00;BB6JKLt{{m,	
 sF++r#   c                 @    d|v rdnd}||z   dj                  |      z   S )N?&)join)r   base_urlextra_params	separators       r!   r   zCloudFrontSigner._build_url  s(    (?C	)#chh|&<<<r#   c                     t        t        |            }t        dd|ii      }|rd|vr|dz  }d|i|d<   |rt        t        |            }d|i|d<   d|fd	|fg}d
t        |      gi}t        j                  |d      S )a0  A helper to build policy.

        :type resource: str
        :param resource: The URL or the stream filename of the protected object

        :type date_less_than: datetime
        :param date_less_than: The URL will expire after the time has passed

        :type date_greater_than: datetime
        :param date_greater_than: The URL will not be valid until this time

        :type ip_address: str
        :param ip_address: Use 'x.x.x.x' for an IP, or 'x.x.x.x/x' for a subnet

        :rtype: str
        :return: The policy in a compact string.
        DateLessThanzAWS:EpochTime/z/32zAWS:SourceIp	IpAddressDateGreaterThanResource	Condition	Statement),:)
separators)r~   r
   r   jsondumps)	r   resourcer   date_greater_than
ip_addressmoment	conditionordered_payloadcustom_policys	            r!   rz   zCloudFrontSigner.build_policy  s    : '78/61J KL	*$e#
&4j%AIk"+,=>?F,;V+DI'(&1K3KL${?'C&DEzz-J??r#   c                     t        j                  |      j                  dd      j                  dd      j                  dd      S )N   +   -   =   _   /   ~)base64	b64encodereplace)r   datas     r!   r   zCloudFrontSigner._url_b64encode  s;     T"WT4 WT4 WT4 		
r#   rj   )	rl   rm   rn   ro   r"   ri   r   rz   r   r7   r#   r!   rs   rs   e  s*    .%$,L=
 LP(@T
r#   rs   c                     t         | d<   y )Ngenerate_db_auth_token)r   class_attributesr,   s     r!   add_generate_db_auth_tokenr         1G-.r#   c                     |}|| j                   j                  }d|d}ddi |dd}d}| | d	| }	t        ||	       | j                  j	                  d||d
d      }
|
t        |      d S )a  Generates an auth token used to connect to a db with IAM credentials.

    :type DBHostname: str
    :param DBHostname: The hostname of the database to connect to.

    :type Port: int
    :param Port: The port number the database is listening on.

    :type DBUsername: str
    :param DBUsername: The username to log in as.

    :type Region: str
    :param Region: The region the database is in. If None, the client
        region will be used.

    :return: A presigned url which can be used as an auth token.
    Nconnect)ActionDBUserr   rN   GET)url_pathquery_stringheadersbodymethodzhttps://r   i  zrds-db)r*   rh   r   rD   r   )metar   r   _request_signerri   len)r   
DBHostnamePort
DBUsernameRegionr2   r   rh   schemeendpoint_urlpresigned_urls              r!   r   r     s    $ F~&& F L FXj\4&1L|4((?? ! @ M V''r#   c                   "    e Zd Zd Z	 	 	 	 ddZy)S3PostPresignerc                     || _         y r   )r   )r   r/   s     r!   r"   zS3PostPresigner.__init__&  s
    -r#   Nc                    |i }|g }i }t         j                   j                         }|t        j                  |      z   }|j                  t        j
                  j                        |d<   g |d<   |D ]  }	|d   j                  |	        t        |      }
||
j                  d<   ||
j                  d<   | j                  j                  d|
|d       |
j                  |dS )	a  Generates the url and the form fields used for a presigned s3 post

        :type request_dict: dict
        :param request_dict: The prepared request dictionary returned by
            ``botocore.awsrequest.prepare_request_dict()``

        :type fields: dict
        :param fields: A dictionary of prefilled form fields to build on top
            of.

        :type conditions: list
        :param conditions: A list of conditions to include in the policy. Each
            element can be either a list or a structure. For example:
            [
             {"acl": "public-read"},
             {"bucket": "mybucket"},
             ["starts-with", "$key", "mykey"]
            ]

        :type expires_in: int
        :param expires_in: The number of seconds the presigned post is valid
            for.

        :type region_name: string
        :param region_name: The region name to sign the presigned post to.

        :rtype: dict
        :returns: A dictionary with two elements: ``url`` and ``fields``.
            Url is the url to post to. Fields is a dictionary filled with
            the form fields and respective values to use when submitting the
            post. For example:

            {'url': 'https://mybucket.s3.amazonaws.com
             'fields': {'acl': 'public-read',
                        'key': 'mykey',
                        'signature': 'mysignature',
                        'policy': 'mybase64 encoded policy'}
            }
        )seconds
expiration
conditionszs3-presign-post-fieldszs3-presign-post-policy	PutObjectrL   )rg   fields)datetimeutcnow	timedeltastrftimer=   rG   ISO8601appendr   r9   r   r)   rg   )r   rh   r   r   rD   r   r   datetime_nowexpire_dater   r+   s              r!   generate_presigned_postz'S3PostPresigner.generate_presigned_post)  s    ^ >FJ   ((//1"X%7%7
%KK*33HMM4I4IJ|  "|# 	3I< ''	2	3 (54:014:01!!+~	
 {{f55r#   )NNrk   N)rl   rm   rn   r"   r   r7   r#   r!   r   r   %  s    . K6r#   r   c                     t         | d<   y )Nri   )ri   r   s     r!   add_generate_presigned_urlr   w  r   r#   c                    |}|}|i }|}|}dt        |       d}	| j                  }
	 | j                  |   }| j
                  j                  j                  |      }| j                  |||	      }t        j                  |j                  dd            }| j                  |||	|       \  }}}| j                  ||||	|d	      }|||d
<   |
j                  |||      S # t        $ r t	        |      w xY w)ax  Generate a presigned url given a client, its method, and arguments

    :type ClientMethod: string
    :param ClientMethod: The client method to presign for

    :type Params: dict
    :param Params: The parameters normally passed to
        ``ClientMethod``.

    :type ExpiresIn: int
    :param ExpiresIn: The number of seconds the presigned url is valid
        for. By default it expires in an hour (3600 seconds)

    :type HttpMethod: string
    :param HttpMethod: The http method to use on the generated url. By
        default, the http method is whatever is used in the method's model.

    :returns: The presigned url
    Tis_presign_requestuse_global_endpoint)method_name
api_paramsoperation_modelr9   BucketrN   ignore_signing_regionFr   r   r   r9   r   set_user_agent_headerr   )rh   rD   r*   )_should_use_global_endpointr   _PY_TO_OP_NAMEKeyErrorr   r   service_modelr   _emit_api_paramsr	   is_arnr?   _resolve_endpoint_ruleset_convert_to_request_dictri   )r   ClientMethodParams	ExpiresIn
HttpMethodclient_methodr   rD   http_methodr9   r/   r*   r   bucket_is_arnr   additional_headers
propertiesrh   s                     r!   ri   ri   {  s]   , !MF~JK":4@G
 ))NB,,]; ii--==nMO""' # F
 $$VZZ"%=>M
 	&&#00	 	' 		 00'!"# 1 L !,X 00!% 1  G  B&=AABs   C! !C7c                     t         | d<   y )Nr   )r   r   s     r!   add_generate_presigned_postr     s    2I./r#   c           	         |}|}|}|}	|}
|i }n|j                         }|	g }	dt        |       d}t        | j                        }| j                  j
                  j                  d      }| j                  d|i||      }t        j                  |j                  dd            }| j                  ||||       \  }}}| j                  |||||d	
      }|	j                  d|i       |j                  d      r"|	j                  dd|dt        d        g       n|	j                  d|i       ||d<   |j!                  |||	|
      S )a	  Builds the url and the form fields used for a presigned s3 post

    :type Bucket: string
    :param Bucket: The name of the bucket to presign the post to. Note that
        bucket related conditions should not be included in the
        ``conditions`` parameter.

    :type Key: string
    :param Key: Key name, optionally add ${filename} to the end to
        attach the submitted filename. Note that key related conditions and
        fields are filled out for you and should not be included in the
        ``Fields`` or ``Conditions`` parameter.

    :type Fields: dict
    :param Fields: A dictionary of prefilled form fields to build on top
        of. Elements that may be included are acl, Cache-Control,
        Content-Type, Content-Disposition, Content-Encoding, Expires,
        success_action_redirect, redirect, success_action_status,
        and x-amz-meta-.

        Note that if a particular element is included in the fields
        dictionary it will not be automatically added to the conditions
        list. You must specify a condition for the element as well.

    :type Conditions: list
    :param Conditions: A list of conditions to include in the policy. Each
        element can be either a list or a structure. For example:

        [
         {"acl": "public-read"},
         ["content-length-range", 2, 5],
         ["starts-with", "$success_action_redirect", ""]
        ]

        Conditions that are included may pertain to acl,
        content-length-range, Cache-Control, Content-Type,
        Content-Disposition, Content-Encoding, Expires,
        success_action_redirect, redirect, success_action_status,
        and/or x-amz-meta-.

        Note that if you include a condition, you must specify
        the a valid value in the fields dictionary as well. A value will
        not be added automatically to the fields dictionary based on the
        conditions.

    :type ExpiresIn: int
    :param ExpiresIn: The number of seconds the presigned post
        is valid for.

    :rtype: dict
    :returns: A dictionary with two elements: ``url`` and ``fields``.
        Url is the url to post to. Fields is a dictionary filled with
        the form fields and respective values to use when submitting the
        post. For example:

        {'url': 'https://mybucket.s3.amazonaws.com
         'fields': {'acl': 'public-read',
                    'key': 'mykey',
                    'signature': 'mysignature',
                    'policy': 'mybase64 encoded policy'}
        }
    NTr   CreateBucketr   r   rN   r   Fr   bucketz${filename}zstarts-withz$keyrc   )rh   r   r   rD   )copyr   r   r   r   r   r   r   r	   r   r?   r   r   r   rP   r   r   )r   r   KeyFields
Conditionsr   r   rc   r   r   rD   r9   post_presignerr   r   r   r   r   r   rh   s                       r!   r   r     s   B F
CFJJ~
 #:4@G
 %T%9%9:N ii--==nMO""f%' # F
 $$VZZ"%=>M
 	&&#00	 	' 		 00'!"# 1 L x() ||M"=&#6K]9K8K2LMN5#,' F5M11!	 2  r#   c                 <   | j                   j                  dk7  ry| j                   j                  j                  }|r`|j	                  dd      ry|j	                  d      dk(  r$| j                   j                  j
                  dk(  ry|j	                  d      dk(  ryy	)
NawsFuse_dualstack_endpointus_east_1_regional_endpointregionalz	us-east-1addressing_stylevirtualT)r   	partitionconfigs3r?   r   )client	s3_configs     r!   r   r   V  s    {{%""%%I==159MM78JF""..+===+,	9r#   r   )Nrk   N)NNrk   )r   r   r   r   r=   botocore.authbotocore.awsrequestr   r   botocore.compatr   botocore.exceptionsr   r   r   botocore.utilsr	   r
   r   r   rs   r   r   r   r   ri   r   r   r   r7   r#   r!   <module>r     s          K ' 
 9 'A AH
C
 C
LH3(lO6 O6dH
 AEL^J
 @DEPr#   