J'utilise le code suivant pour faire une simple demande de PUT à AWS S3 en utilisant une signature version 4:Ce que je fais de mal à S3 demande PUT utilisant AWS Signature Version 4
from collections import OrderedDict
from dateutil import parser
import datetime
import hashlib
import hmac
import requests
key_id = "REDACTED"
secret = "REDACTED"
bucket_name = "REDACTED"
def hashb16(message):
return hashlib.sha256(message).hexdigest()
def HMAC(key, message):
return hmac.new(key, message, hashlib.sha256)
current_time = datetime.datetime.utcnow()
url = "https://s3-eu-west-2.amazonaws.com/{}/sometest.txt".format(bucket_name)
payload = "Welcome to Amazon S3."
headers = {
'date': current_time.strftime("%a, %d %b %Y %H:%m:%S GMT"),
'host': "s3-eu-west-2.amazonaws.com",
'x-amz-content-sha256': hashb16(payload),
'x-amz-date': current_time.strftime('%Y%m%dT%H%M%SZ'),
'x-amz-storage-class': 'REDUCED_REDUNDANCY'
}
sorted_headers = sorted([k for k in headers])
region = "eu-west-2"
service = "s3"
# step 1
HTTPRequestMethod = "PUT"
CanonicalURI = "/sometest.txt"
CanonicalQueryString = ""
CanonicalHeaders = ""
for key in sorted_headers:
CanonicalHeaders += "{}:{}\n".format(key.lower(), headers[key])
SignedHeaders = "{}".format(";".join(sorted_headers))
HexEncondeHashRequestPayload = hashb16(payload)
CanonicalRequest = "{}\n{}\n{}\n{}{}\n{}".format(HTTPRequestMethod, CanonicalURI, CanonicalQueryString, CanonicalHeaders, SignedHeaders, HexEncondeHashRequestPayload)
# step 2
Algorithm = "AWS4-HMAC-SHA256"
RequestDateTime = current_time.strftime('%Y%m%dT%H%M%SZ')
CredentialScope = "{}/{}/{}/{}".format(current_time.strftime("%Y%m%d"), region, service, "aws4_request")
HashedCanonicalRequest = hashb16(CanonicalRequest)
StringToSign = "{}\n{}\n{}\n{}".format(Algorithm, RequestDateTime, CredentialScope, HashedCanonicalRequest)
#step 3
kDate = HMAC("AWS4" + secret, current_time.strftime("%Y%m%d")).digest()
kRegion = HMAC(kDate, region).digest()
kService = HMAC(kRegion, service).digest()
kSigning = HMAC(kService, "aws4_request").digest()
signature = HMAC(kSigning, StringToSign).hexdigest()
#step 4
Authorization = "AWS4-HMAC-SHA256 Credential={}/{},SignedHeaders={},Signature={}".format(key_id, CredentialScope, ";".join(sorted_headers), signature)
headers["Authorization"] = Authorization
response = requests.request("PUT", url, headers=headers)
print response.status_code
print response.text
Les étapes sont ci-dessus par le AWS documentation. J'ai testé les fonctions de hachage en utilisant les exemples de this page et ils vérifient.
Malheureusement, lorsque j'effectue la demande réelle, j'obtiens un code d'état 403 avec le message de signature invalide habituel. Qu'est-ce qui me manque dans le code ci-dessus?