import time, os, json, base64, urllib, hmac, sha @app.route('/sign_s3_put/') @login_required def sign_s3_put(): """ Provide a temporary signature so that users can upload files directly from their browsers to our AWS S3 bucket. The authorization portion is taken from Example 3 on http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html """ # don't give user full control over filename - avoid ability to overwrite files random = base64.urlsafe_b64encode(os.urandom(2)) object_name = random+request.args.get('s3_object_name') object_name = urllib.quote_plus(object_name) # make sure it works for filenames with spaces, etc. mime_type = request.args.get('s3_object_type') expires = int(time.time()+300) # PUT request to S3 must start within X seconds amz_headers = "x-amz-acl:public-read" # set the public read permission on the uploaded file resource = '%s/%s' % (app.config['AWS_EMAIL_ATTACHMENTS_BUCKET_NAME'], object_name) str_to_sign = "PUT\n\n{mime_type}\n{expires}\n{amz_headers}\n/{resource}".format( mime_type=mime_type, expires=expires, amz_headers=amz_headers, resource=resource ) sig = urllib.quote_plus(base64.encodestring(hmac.new(app.config['AWS_EMAIL_ATTACHMENTS_SECRET_ACCESS_KEY'], str_to_sign, sha).digest()).strip()) url = 'https://%s.s3.amazonaws.com/%s' % (app.config['AWS_EMAIL_ATTACHMENTS_BUCKET_NAME'], object_name) return json.dumps({ 'signed_request': '{url}?AWSAccessKeyId={access_key}&Expires={expires}&Signature={sig}'.format( url=url, access_key=app.config['AWS_EMAIL_ATTACHMENTS_ACCESS_KEY_ID'], expires=expires, sig=sig ), 'url': url })