When using boto3.client('s3').generate_presigned_post to generate an URL for a file upload via form submit an error from AWS occurs - amazon-s3

As mentioned in this question's title, when using the boto3.client('s3').generate_presigned_post to generate an upload URL as per here and injecting the response of the function into the following form:
<form class="s3-upload" action="URL_VALUE" method="post" enctype="multipart/form-data">
<input type="hidden" name="key" value="VALUE"/>
<input type="hidden" name="AWSAccessKeyId" value="VALUE"/>
<input type="hidden" name="policy" value="VALUE"/>
<input type="hidden" name="signature" value="VALUE"/>
<input type="hidden" name="success_action_redirect" value="VALUE"/>
<input type="file" name="file" class="upload-input">
<p class="drag-text">Drag your file here or click in this area.</p>
<button id="uploadS3" type="submit" title="">Upload</button>
</form>
I receive the following error from AWS: The AWS Access Key Id you provided does not exist in our records.
The application runs inside a docker on AWS Fargate and has an AWS role attached to it. This must probably have something to do with the solution because the whole functionality works fine on my local machine. Furthermore, all other AWS related operations with S3 (also with SQS) work fine with that AWS Fargate/AWS role setting. I'm looking forward to any suggestions about what to do.

Related

S3 upload on https with dots in bucket name

I've been trying to implement an ajax upload to Amazon's S3 on a site that uses https, so of course I also have to upload to the secure version of S3, https://bucket.name.s3.amazonaws.com. However, when I try this upload, I end up getting an error that the site has an invalid security certificate. From what I was reading, this is expected because amazon's s3 certificate only covers one level of subdomains (http://shlomoswidler.com/2009/08/amazon-s3-gotcha-using-virtual-host.html). Therefore, I changed the URL I'm uploading to to be https://s3.amazonaws.com/bucket.name, which from what I've also read, is supposed to be equivalent to https://bucket.name.s3.amazonaws.com. However, attempts to upload there gave me a 301 permanent redirect error. I know for a fact my code works, because when I attempted instead to upload to a bucket with no dots in the name, to https://bucket.s3.amazonaws.com, it went through fine, but it also gets a 301 when I attempt https://s3.amazonaws.com/bucket.
<form id="form">
<input type="hidden" name="key" value="..." />
<input type="hidden" name="acl" value="public-read" />
<input type="hidden" name="X-Amz-Credential" value="..." />
<input type="hidden" name="X-Amz-Algorithm" value="..." />
<input type="hidden" name="X-Amz-Date" value="..." />
<input type="hidden" name="Policy" value="..." />
<input type="hidden" name="X-Amz-Signature" value="..." />
<input type="hidden" name="success_action_redirect" value="..." />
<input id="upload" type="submit" value="Upload" class="submit-upload clearfix button blue save"/>
</form>
<script type="text/javascript">
document.getElementById('upload').addEventListener('click', function (e) {
e.preventDefault();
var formData = new FormData(document.getElementById('form'));
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://s3.amazonaws.com/bucket.name/', true);
xhr.send(formData);
});
</script>
So my question is: is there a way to implement an ajax upload to an S3 bucket with dots in the name over https?
On http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html
Amazon S3 supports virtual hosted-style and path-style access in all regions. The path-style syntax, however, requires that you use the region-specific endpoint when attempting to access a bucket. For example, if you have a bucket called mybucket that resides in the EU, you want to use path-style syntax, and the object is named puppy.jpg, the correct URI is http://s3-eu-west-1.amazonaws.com/mybucket/puppy.jpg. You will receive a "PermanentRedirect" error, an HTTP response code 301, and a message indicating what the correct URI is for your resource if you try to access a bucket outside the US East (N. Virginia) region with path-style syntax that uses either of the following:
http://s3.amazonaws.com
An endpoint for a region different from the one where the bucket resides, for example, http://s3-eu-west-1.amazonaws.com for a bucket that was created in the US West (Northern California) region

trouble setting content-type on amazon s3 with carrierwave direct

I have a rails app that successfully uploads product images to s3 using carrierwave and fog following the railscast tutorial. Now I'm trying to use Carrierwave direct gem to upload the file directly to s3. This works as well, except the content-type was set as binary/octet-stream which makes the images invoke a file download in the browser instead of just displaying the jpg.
So per the gem instructions at https://github.com/dwilkie/carrierwave_direct, I added to carrierwave config:
config.will_include_content_type = true
And added a hidden field Content-Type with value of image/jpeg.
The file upload form generated by the form helper seems to be correct:
<form accept-charset="UTF-8" action="https://mybucket.s3.amazonaws.com/" class="new_product_image_uploader" enctype="multipart/form-data" id="new_product_image_uploader" method="post">
<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
<input id="product_image_uploader_key" name="key" type="hidden" value="uploads/.../${filename}">
<input id="product_image_uploader_aws_access_key_id" name="AWSAccessKeyId" type="hidden" value="...">
<input id="product_image_uploader_acl" name="acl" type="hidden" value="public-read">
<input id="product_image_uploader_success_action_redirect" name="success_action_redirect" type="hidden" value="http://localhost:5000/products">
<input id="product_image_uploader_policy" name="policy" type="hidden" value="...">
<input id="product_image_uploader_signature" name="signature" type="hidden" value="...">
<input id="product_image_uploader_product_image" name="file" type="file">
<input id="Content-Type" name="Content-Type" type="hidden" value="image/jpeg"><br>
<input name="commit" type="submit" value="Create Product image uploader">
</form>
The base 64 encoded policy is:
{"expiration":"2013-06-21T13:35:42Z","conditions":[["starts-with","$utf8",""],["starts-with","$key","uploads"],["starts-with","$Content-Type",""],{"bucket":"mybucket"},{"acl":"public-read"},{"success_action_redirect":"http://localhost:5000/products"},["content-length-range",1,5242880]]}
Which appears to correspond with this article here: http://aws.amazon.com/articles/1434
But when I test it locally I get this error response in the browser:
<Error>
<Code>AccessDenied</Code>
<Message>Invalid according to Policy: Policy Condition failed:
["starts-with", "$Content-Type", ""]</Message>
...
</Error>
I don't really know what that means. I googled for this error and found this issue: https://github.com/dwilkie/carrierwave_direct/issues/63
But the solution is not helpful. Am I missing something?
I'm using:
carrierwave (0.8.0)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
carrierwave_direct (0.0.12)
rails (3.2.13)
After googling around some more, I found the following comment on this page: http://doc.s3.amazonaws.com/proposals/post.html
<!-- The file must be the last meaningful element in the request; other elements after this will be ignored -->
Switching the Content-Type hidden input field before the file input field fixes my issue.

Google Custom Search with SEO URL

Well i have this search engine into my site
<form action="/apps/search/" name="g_search" id="cse-search-box" method="post">
<input type="hidden" name="cof" value="FORID:11;NB:1" />
<input type="hidden" name="ie" value="utf-8" />
<input type="text" autocomplete="off" name="google_seach" class="search-text" onfocus="searchtext('focus')" onblur="searchtext('blur')" />
<label style="color:#796b6b;float:left;padding:0;">|</label>
<input type="submit" style="float:right;margin-top:3px;cursor:pointer;width:16px;height:16px;background:url(/template/img/main/search-icon.jpg);border:none;" value="" alt="Αναζήτηση" title="Αναζήτηση" />
</form>
Now i want some code to results page.Somehow the post request readed from a file called search.php
This file have access to $_POST[] array..
The file initializes $selector variable (for template use).
What we want to echo into contentarea div must put into $body variable..
Any help?
<?php
$selector="search";
$body="<div id=\"cse-search-form\" style=\"width: 100%;\">Loading</div>";
?>
I have a similar issue, just use GCS code provide by Google as it easy, make sure in the option in GSE you select to visualize the search result on your page and not an Iframe

Open documents in browser with zoho api

HI im trying to integrate zoho into my website and open a document in browser
Im using Wamp server.
This the code im trying to work with:
<html>
<head>
</head>
<body>
<form method="POST" action="http(s)://export.writer.zoho.com/remotedoc.im" target="_self"
accept-charset="UTF-8">
<input type="hidden" name="url" value="http://localhost/paper.doc">
<input type="hidden" name="apikey" value="here goes api key">
<input type="hidden" name="output" value="url">
<input type="hidden" name="mode" value="normaledit">
<input type="hidden" name="filename" value="paper.doc">
<input type="hidden" name="lang" value="en">
<input type="hidden" name="skey" value="here goes secret value">
<input type="hidden" name="id" value="12345678">
<input type="hidden" name="format" value="doc">
<input type="hidden" name="saveurl" value="http://localhost/save.php">
<input type="submit" name="submit" value="Open/Edit">
</form>
</body>
</html>
I dont know i get this error:
Forbidden
You don't have permission to access /http(s)://export.writer.zoho.com/remotedoc.im on this server.
I have entered the api key correctly and the secret key
Im just confused and stuck here.Im blocked
Here is the documentation : http://apihelp.wiki.zoho.com/Open-Document.html
You have taken the (s) out of the url right? I know it might seem like a silly question but I thought I should check in case you had overlooked it. The url resolves for me and gives an 'api key is invalid' warning.
The error given would seem to indicate the browser thinks its a relative instead of absolute url.
I dont know much more about ZOHO but i also want to implement this in my project in future. As i read in https://apihelp.wiki.zoho.com/Open-Document.html#mfs it says that saveurl must be publicly accessible and if it not accessible publicly it gives an error and localhost is not publicly accessible so it gives an error.

using paypals html api is safe?

im trying out paypals html api where you specify price, item_name, customer information and so on in the html:
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="payPalForm">
<input type="hidden" name="cmd" value="_cart" />
<input type="hidden" name="upload" value="1" />
<input type="hidden" name="no_note" value="1" />
<input type="hidden" name="business" value="your#paypalaccount.com" />
<input type="hidden" name="currency_code" value="SEK" />
<input type="hidden" name="return" value="http://freelanceswitch.com/payment-complete/" />
<input type="hidden" name="tax_rate" value="25" />
<input type="hidden" name="item_name_1" value="Apple Macpro" />
<input type="hidden" name="item_number_1" value="01 - Product 1" />
<input type="hidden" name="amount_1" value="25000" />
<input type="hidden" name="item_name_2" value="Apple Macbook" />
<input type="hidden" name="item_number_2" value="02 - Product 2" />
<input type="hidden" name="amount_2" value="12500" />
<input type="hidden" name="item_name_3" value="Apple Macbook Air" />
<input type="hidden" name="item_number_3" value="03 - Product 3" />
<input type="hidden" name="amount_3" value="12500" />
<input type="submit" name="Submit" value="Submit" />
</form>
when the user clicks submit it takes him/her to paypals payment page.
but doesn't this mean that a hacker could change the order by manipulating the html code?
i can´t figure out how paypal prevents this security problem.
Of course, it does appear as if someone could just change the HTML and re-submit the form.
I'm not sure about PayPal, but Google Checkout handles this by instead of setting HTML, it gets you to create XML, encrypt it using your merchant key, and use the encrypted string in your HTML to pass across to Google. Google then decrypts it using your merchant key and voila - tamper-free.
Have a look in PayPal's documentation for something along the lines of "cart signing" or "request encryption." They may also do a callback to your server, telling you what was sent and you can compare it to your database to see if the prices are still correct.
If this is anything like other html integrations, there should be a callback directly from Paypal to your server with all the fields that were entered. You can compare these to see if any have changed. There are usually various security mechanisms such as a shared hidden key so that you can validate that the callback is genuine.
It doesn't seem like it is safe by itself. On Paypal's Securing Your Website Payments Standard Buttons page, they talk about being able to create protected payment buttons. However further on they indicate that it doesn't work if Javascript is disabled which makes the protection useless! Then they talk about other manual processes that can be performed including reconciliation and instant notifications which should occur in any sound accounting process anyway.
Encrypted website payments really seems like the only secure option to me.