Lot of errors at Django S3 example
The first error I've got was at line 54: request_payload = json.loads(request.body), saying that the parameter must be 'str', not 'bytes'. I've fixed it writing this instead: request_payload = json.loads(request.body.decode()).
Then I've got one at line 113: policy = base64.b64encode(json.dumps(policy_document)). It said that a bytes-like object was required, not 'str'. So I changed that line to policy = base64.b64encode(json.dumps(policy_document).encode()), and it seemed to be fixed.
Now I'm getting an error at the next line, 114: signature = base64.b64encode(hmac.new(settings.AWS_CLIENT_SECRET_KEY, policy, hashlib.sha1).digest()). At some point of the hmac.new function I get this: key: expected bytes or bytearray, but got 'str'.
I'll try to fix it, but please tell me if I'm doing something wrong, maybe there's a better way of doing it.
Now I've converted from byte to str or backwards in every part of the code where I've got errors, but the signature is not correct, because I get a 403 (Forbidden) response from my bucket.
I don't have any working knowledge of Django. If you are seeing clear issues with the code, a pull request fixing the issues with explanations of the errors and fixes would be much appreciated. Any other issues you see that you are not able to immediately fix can be discussed in that PR as well.
@andresespinosapc did you find a solution?
It sounds like you are using Python 3 and the example is for Python 2
In my case I had to use v4 signature to make the signing work. I've modified the signature functions in the Django-s3 folder as follows
import base64, hmac, hashlib, json, sys, binascii
# Key derivation functions. See:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def sign(key, msg):
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
def getSignatureKey(key, dateStamp, regionName, serviceName):
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, 'aws4_request')
return kSigning
def sign_policy_document(policy_document, client_secret):
""" Sign and return the policy doucument for a simple upload.
http://aws.amazon.com/articles/1434/#signyours3postform
"""
# client_secret = bytearray(client_secret, 'utf-8')
dateStamp = get_condition(policy_document['conditions'], 'x-amz-date')
dateStamp = dateStamp[:8]
import logging
logger = logging.getLogger(__name__)
logger.error(client_secret)
# london
regionName = 'eu-west-2'
serviceName = 's3'
policy = base64.b64encode(
bytearray(
json.dumps(policy_document), 'utf-8'
)
)
sigKey = getSignatureKey(client_secret, dateStamp, regionName, serviceName)
signature = sign(sigKey, policy.decode('utf-8'))
return {
'policy': policy.decode("utf-8"),
'signature': binascii.hexlify(signature).decode('utf-8')
}