AWS S3 предопределенные URL с boto3 - несоответствие подписи - PullRequest
0 голосов
/ 07 мая 2018

Я хочу создать предопределенный URL для объектов в моем ведре. Я использую следующий код Python:

    client = boto3.client(
    's3',
    aws_access_key_id=os.environ['AWS_ACCESS_KEY'],
    aws_secret_access_key=os.environ['AWS_SECRETS_KEY'],
    config=botocore.client.Config(signature_version='s3v4'),
    region_name='eu-central-1'
)
url = client.generate_presigned_url(
    ClientMethod='get_object',
    ExpiresIn=60,
    Params={
        'Bucket': MYBUCKET,
        'Key': MYKEY
    })

Затем я отправляю сгенерированный URL на мой интерфейс На клиенте я создам тег со сгенерированной ссылкой и использую метод click (). Это работало нормально в других проектах, но здесь я получаю только ошибку:

The request signature we calculated does not match the signature you provided. Check your key and signing method.

Что странно. Пользователь должен иметь все необходимые права. Потому что перечисление всех файлов в моем ведре работает нормально.

Может ли кто-нибудь указать мне правильное направление, почему это не работает?

EDIT

Я использую next.js на внешнем интерфейсе, если это поможет.

Ответы [ 2 ]

0 голосов
/ 05 августа 2018

Была такая же проблема. Изучил документы AWS и сам написал процедуру (signature v4). Ниже на основе

https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html

и отлично работает.

ENCODING = 'utf8'
SEVEN_DAYS = 604800
logger = logging.getLogger()
logger.setLevel(logging.INFO)


def sign(key, msg):
    return hmac.new(key, msg.encode(ENCODING), hashlib.sha256).digest()


def get_signature_key(key, dateStamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode(ENCODING), dateStamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, 'aws4_request')
    return kSigning


def generate_presigned_s3_get(bucket, object_key, region, expires_in, access_key, secret_key):
    METHOD = 'GET'
    SERVICE = 's3'
    host = bucket + '.s3.' + region + '.amazonaws.com'
    endpoint = 'https://' + host
    t = datetime.datetime.utcnow()
    amz_date = t.strftime('%Y%m%dT%H%M%SZ')
    datestamp = t.strftime('%Y%m%d')
    canonical_uri = '/' + object_key
    canonical_headers = 'host:' + host + '\n'
    signed_headers = 'host'
    algorithm = 'AWS4-HMAC-SHA256'
    credential_scope = datestamp + '/' + region + '/' + SERVICE + '/' + 'aws4_request'
    canonical_querystring = '?X-Amz-Algorithm=AWS4-HMAC-SHA256'
    canonical_querystring += '&X-Amz-Credential=' + urllib.parse.quote_plus(access_key + '/' + credential_scope)
    canonical_querystring += '&X-Amz-Date=' + amz_date
    canonical_querystring += '&X-Amz-Expires=' + str(expires_in)
    canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
    canonical_request = METHOD + '\n' + canonical_uri + '\n' + canonical_querystring[1:] + '\n' + canonical_headers + '\n' + signed_headers + '\nUNSIGNED-PAYLOAD'
    string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode(ENCODING)).hexdigest()
    signing_key = get_signature_key(secret_key, datestamp, region, SERVICE)
    signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
    canonical_querystring += '&X-Amz-Signature=' + signature
    url = endpoint + canonical_uri + canonical_querystring
    logger.info('presigned url: %s' % url)
    return url

Я также сообщил об этой проблеме в peto boto3: https://github.com/boto/boto3/issues/1644

0 голосов
/ 07 мая 2018

Проблема была в версии boto3.

Я попробовал последнюю версию (boto3 1.7.14), которая привела к вышеупомянутой ошибке.

Работает так же, как я хочу с версией 1.6.6.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...