Created
October 6, 2012 01:27
-
-
Save philfreo/3843375 to your computer and use it in GitHub Desktop.
AWS S3 bucket policy to make all files public (+CORS)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Statement": [ | |
{ | |
"Sid": "AllowPublicRead", | |
"Effect": "Allow", | |
"Principal": { | |
"AWS": "*" | |
}, | |
"Action": "s3:GetObject", | |
"Resource": "arn:aws:s3:::bucket_name_here/*" | |
} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Statement": [{ | |
"Action": [ | |
"s3:GetObject", | |
"s3:PutObject", | |
"s3:PutObjectAcl" | |
], | |
"Effect": "Allow", | |
"Resource": [ | |
"arn:aws:s3:::bucket_name_here/*" | |
] | |
}] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
}) |
Can you confirm this still works? My OPTIONS request to s3 just freezes and nothing ever happens.
Nope?
@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.
@philfreo THANK YOU! 👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://philfreo.com/blog/how-to-allow-direct-file-uploads-from-javascript-to-amazon-s3-signed-by-python/