Пример #1
0
def generate_presigned_url_for_uploading_part(
    bucket, key, credentials, uploadId, partNumber, region, expires
):
    """
    Generate presigned url for uploading object part given uploadId and part number

    Args:
        bucket(str): bucket
        key(str): key
        credentials(dict): dictionary of aws credentials
        uploadId(str): uploadID of the multipart upload
        partNumber(int): part number
        region(str): bucket region
        expires(int): expiration time
    
    Returns:
        presigned_url(str)
    """

    url = "https://{}.s3.amazonaws.com/{}".format(bucket, key)
    additional_signed_qs = {"partNumber": str(partNumber), "uploadId": uploadId}

    try:
        return generate_aws_presigned_url(
            url, "PUT", credentials, "s3", region, expires, additional_signed_qs
        )
    except Exception as e:
        raise InternalError(
            "Can not generate presigned url for part number {} of key {}. Detail {}".format(
                partNumber, key, e
            )
        )
Пример #2
0
def test_generate_presigned_url_escaped():
    cred = {
        "aws_access_key_id": "AKIDEXAMPLE",
        "aws_secret_access_key": "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY",
    }
    url = "https://s3.amazonaws.com/dummy/P0001_T1/[test]; .tar.gz"
    date = datetime.date(1999, 2, 19)
    with mock_datetime(date, datetime):
        presigned_url = generate_aws_presigned_url(
            url,
            "GET",
            cred,
            "s3",
            "us-east-1",
            86400,
            {
                "user-id": "value2",
                "username": "******"
            },
        )

    expected = (
        "https://{}".format(
            quote("s3.amazonaws.com/dummy/P0001_T1/[test]; .tar.gz")) +
        "?X-Amz-Algorithm=AWS4-HMAC-SHA256"
        "&X-Amz-Credential=AKIDEXAMPLE%2F19990219%2Fus-east-1%2Fs3%2Faws4_request"
        "&X-Amz-Date=19990219T000000Z"
        "&X-Amz-Expires=86400"
        "&X-Amz-SignedHeaders=host"
        "&user-id=value2"
        "&username=value1%20%28value3%29%40gmail.com"
        "&X-Amz-Signature=b4ac7428943c9801746b6d00112d3ae76739d79ee3e8e73070110979ddab4a1d"
    )
    assert presigned_url == expected
Пример #3
0
    def get_signed_url(
        self, action, expires_in, public_data=False, force_signed_url=True, **kwargs
    ):
        aws_creds = get_value(
            config, "AWS_CREDENTIALS", InternalError("credentials not configured")
        )
        s3_buckets = get_value(
            config, "S3_BUCKETS", InternalError("buckets not configured")
        )

        bucket_name = self.bucket_name()
        bucket = s3_buckets.get(bucket_name)

        if bucket and bucket.get("endpoint_url"):
            http_url = bucket["endpoint_url"].strip("/") + "/{}/{}".format(
                self.parsed_url.netloc, self.parsed_url.path.strip("/")
            )
        else:
            http_url = "https://{}.s3.amazonaws.com/{}".format(
                self.parsed_url.netloc, self.parsed_url.path.strip("/")
            )

        credential = S3IndexedFileLocation.get_credential_to_access_bucket(
            bucket_name, aws_creds, expires_in
        )

        # if it's public and we don't need to force the signed url, just return the raw
        # s3 url
        aws_access_key_id = get_value(
            credential,
            "aws_access_key_id",
            InternalError("aws configuration not found"),
        )
        # `aws_access_key_id == "*"` is a special case to support public buckets
        # where we do *not* want to try signing at all. the other case is that the
        # data is public and user requested to not sign the url
        if aws_access_key_id == "*" or (public_data and not force_signed_url):
            return http_url

        region = self.get_bucket_region()
        if not region and not bucket.get("endpoint_url"):
            region = flask.current_app.boto.get_bucket_region(
                self.parsed_url.netloc, credential
            )

        user_info = _get_user_info()

        url = generate_aws_presigned_url(
            http_url,
            ACTION_DICT["s3"][action],
            credential,
            "s3",
            region,
            expires_in,
            user_info,
        )

        return url
Пример #4
0
def test_generate_presigned_url():
    cred = {
        "aws_access_key_id":
        "AKIDEXAMPLE",
        "aws_secret_access_key":
        "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY",
        "aws_session_token":
        "FQoDYXdzEPv//////////wEaDD/RcZIzhOP3tz1Ut7N W7jud8VV53T59A2TNO2ZXkt",
    }
    url = "https://s3.amazonaws.com/cdis-presigned-url-test/testdata"
    date = datetime.date(2018, 2, 19)
    with mock_datetime(date, datetime):
        presigned_url = generate_aws_presigned_url(
            url,
            "GET",
            cred,
            "s3",
            "us-east-1",
            86400,
            {
                "user-id": "value2",
                "username": "******"
            },
        )
    print(presigned_url)
    expected = (
        "{}?X-Amz-Algorithm=AWS4-HMAC-SHA256"
        "&X-Amz-Credential=AKIDEXAMPLE%2F20180219%2Fus-east-1%2Fs3%2Faws4_request"
        "&X-Amz-Date=20180219T000000Z"
        "&X-Amz-Expires=86400"
        "&X-Amz-Security-Token={}"
        "&X-Amz-SignedHeaders=host"
        "&user-id=value2"
        "&username=value1%40gmail.com"
        "&X-Amz-Signature=e63e7c291b2c89abf7a94ca1ed7438862feaadffc47a0c925723798ffb5a9bea"
        .format(url, quote(cred.get("aws_session_token"), safe="")))
    assert presigned_url == expected
Пример #5
0
    def get_signed_url(self, action, expires_in, public_data=False):
        aws_creds = get_value(
            flask.current_app.config,
            "AWS_CREDENTIALS",
            InternalError("credentials not configured"),
        )

        http_url = "https://{}.s3.amazonaws.com/{}".format(
            self.parsed_url.netloc, self.parsed_url.path.strip("/"))

        config = self.get_credential_to_access_bucket(aws_creds, expires_in)

        aws_access_key_id = get_value(
            config, "aws_access_key_id",
            InternalError("aws configuration not found"))
        if aws_access_key_id == "*":
            return http_url

        region = flask.current_app.boto.get_bucket_region(
            self.parsed_url.netloc, config)

        user_info = {}
        if not public_data:
            user_info = S3IndexedFileLocation.get_user_info()

        url = generate_aws_presigned_url(
            http_url,
            ACTION_DICT["s3"][action],
            config,
            "s3",
            region,
            expires_in,
            user_info,
        )

        return url