Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AWS S3 bucket policy to make all files public (+CORS)
{
"Statement": [
{
"Sid": "AllowPublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket_name_here/*"
}
]
}
// https://github.com/elasticsales/s3upload-coffee-javascript
var s3upload = new S3Upload({
file_dom_selector: '#files', // an <input type="file"> element
s3_sign_put_url: '/sign_s3_put',
onProgress: function(percent, message, publicUrl, file) { // Use this for live upload progress bars
console.log('Upload progress: ', percent, message);
},
onFinishS3Put: function(public_url, file) { // Get the URL of the uploaded file
console.log('Upload finished: ', public_url);
},
onError: function(status, file) {
console.log('Upload error: ', status);
}
});
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Content-Type</AllowedHeader>
<AllowedHeader>x-amz-acl</AllowedHeader>
<AllowedHeader>origin</AllowedHeader>
</CORSRule>
</CORSConfiguration>
{
"Statement": [{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::bucket_name_here/*"
]
}]
}
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
})
@ghost

This comment has been minimized.

Copy link

commented Jul 5, 2013

Can you confirm this still works? My OPTIONS request to s3 just freezes and nothing ever happens.

@ghost

This comment has been minimized.

Copy link

commented Jul 15, 2013

Nope?

@chosak

This comment has been minimized.

Copy link

commented Feb 3, 2015

@philfreo thanks for the helpful blog post and code examples.

@dangerfarms I just implemented this and had to make some minor changes. Specifically, Chrome was reporting a net::ERR_INSECURE_RESPONSE error on the OPTIONS call, because the certificate for https://<your bucket name>.s3.amazonaws.com isn't trusted.

To modify the code above, you could do something like

url = 'https://s3.amazonaws.com/%s/%s' % (
    app.config['AWS_EMAIL_ATTACHMENTS_BUCKET_NAME',
    object_name
)

This has the same effect -- use this URL both as the returned value for 'url' as well as in your signed request.

@tomasdev

This comment has been minimized.

Copy link

commented Dec 3, 2018

@philfreo THANK YOU! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.