I'm attempting to follow this "how-to" (form POST to S3 bucket) and appear to be failing on my policy and signature.
I'm not so sure my policy and signature are wrong? But I do know I'm having an issue evaluating the methods I've created in my helper. I've tried converting the Policy & signature values to symbols <%= :S3_UPLOAD_SIGNATURE %>
and I've tried <%=h, <%=raw, "#{<%=..}".
I've called helper methods before with no issues so I'm a bit lost.
the error:
NameError in Proj_files#new
Showing /app/views/proj_files/new.html.erb where line #8 raised:
uninitialized constant ActionView::CompiledTemplates::S3_UPLOAD_POLICY
Extracted source (around line #8):
5: <input type="hidden" name="AWSAccessKeyId" value= <%= ENV['AWS_ACCESS_KEY_ID'] %> >
6: <input type="hidden" name="acl" value="private">
7: <input type="hidden" name="success_action_redirect" value="http://localhost/">
8: <input type="hidden" name="policy" value= <%= S3_UPLOAD_POLICY %> >
9: <input type="hidden" name="signature" value= <%= S3_UPLOAD_SIGNATURE %> >
10: <input type="hidden" name="Content-Type" value="image/png">
11: <!-- Include any additional input fields here -->
I have a proj_files controller with a corresponding new.html.erb:
<form action="https://s3.amazonaws.com/MY_BUCKET" method="post" enctype="multipart/form-data">
<input type="hidden" name="key" value="uploads/${filename}">
<input type="hidden" name="AWSAccessKeyId" value= <%= ENV['AWS_ACCESS_KEY_ID'] %> >
<input type="hidden" name="acl" value="private">
<input type="hidden" name="success_action_redirect" value="http://localhost/">
<input type="hidden" name="policy" value= <%= S3_UPLOAD_POLICY %> >
<input type="hidden" name="signature" value= <%= S3_UPLOAD_SIGNATURE %> >
<input type="hidden" name="Content-Type" value="image/png">
<!-- Include any additional input fields here -->
File to upload to S3:
<input name="file" type="file">
<br>
<input type="submit" value="Upload File to S3">
</form>
and the proj_files_helper.rb:
module ProjFilesHelper
def S3_UPLOAD_POLICY options = {}
options[:content_type] ||= ''
options[:acl] ||= 'private'
options[:max_file_size] ||= 500.megabyte
options[:path] ||= ''
Base64.encode64(
"{'expiration': '#{10.hours.from_now.utc.strftime('%Y-%m-%dT%H:%M:%S.000Z')}',
'conditions': [
{'bucket': '#{ENV['S3_BUCKET']}'},
['starts-with', '$key', ''],
{'acl': '#{options[:acl]}'},
{'success_action_status': '201'},
['content-length-range', 0, #{options[:max_file_size]}],
['starts-with','$Content-Type','']
]
}").gsub(/\n|\r/, '')
end
def S3_UPLOAD_SIGNATURE options = {}
Base64.encode64(
OpenSSL::HMAC.digest(
OpenSSL::Digest::Digest.new('sha1'),
ENV['AWS_SECRET_ACCESS_KEY'], s3_policy(options))).gsub("\n","")
end
end
Thanks for taking a look!
UPDATE: I changed the method names to lower case and that got me a bit further (I should have realized that!).
Now I get an S3 error:
<Error>
<Code>AccessDenied</Code>
<Message>
Invalid according to Policy: Policy Condition failed: ["eq", "$bucket", "MY_BUCKETS_NAME"]
</Message>
Seems like there may be an ENV variable $bucket bad reference i'll look for... "MY_BUCKETS_NAME" did display the proper buckets name....If anyone can offer any help on getting rails post form to S3 up and running / point out my errors I'd appreciate it.
Thanks
UPDATE2 Per comment below I modified my form action to "https://s3.amazonaws.com/MY_BUCKET" and received this error:
Invalid according to Policy: Policy Condition failed: ["eq", "$acl", "public-read"]
Getting close... Thanks!
UPDATE3 I'm fighting the fight!
I've modified the policy and form ACL to have same consistent value (private or public-read).
Comments below led me to modifying form action to: http://MY_BUCKET.s3.amazonaws.com/
I get this error:
<Code>AccessDenied</Code>
<Message>
Invalid according to Policy: Policy Condition failed: ["eq", "$success_action_status", "201"]
</Message>
Oddly enough when I go to AWS S3 management console and upload a file to my bucket, it tells me the link is of the `http://s3.amazonaws.com/MY_BUCKET' form. I've added MY_BUCKET before and after amazonaws and still received same error...
I'm not sure where there mis-configuration is occurring... I'm going to create a new bucket and see if I setup wrong....
Thanks!
IT WORKS NOW!!! I fixed everything from answer... but then had to make one more change...
My form had a "success_action_redirect" field but my policy had a success_action_status!
Policy and form fields must match! DUH!
Thanks for all the help... time to tweak it a bit further!
1/ To upload the file you must use this url "http://#{bucket_name}.s3.amazonaws.com/"
. It's clearly stated in the documentation:
The action defines the URL that will process the request; this must be set to the bucket's URL. For example, if your bucket's name is "johnsmith", then the URL would be "http://johnsmith.s3.amazonaws.com/"
2/ You must have consistent policy, seems you set public-read
in the signature and private
in the form.
I was getting the following error: Invalid according to Policy: Policy Condition failed: [\"eq\", \"$bucket\"
After many hours, I learned that you can't have a bucket with uppercase letters. Changing the bucket to lowercase fixed it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With