Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Browser uploads to s3 with instance roles

This is a follow-up on my previous question regarding policy document signing using instance profiles.

I'm developing a system that allows drag & drop uploads directly to an S3 bucket; an AJAX request is first made to my server containing the file metadata. Once verified, my server responds with the form parameters that are used to complete the upload.

The process of setting up browser based uploads is well explained here and it all works as expected in my local test environment.

However, once my application gets deployed on an EC2 instance, I'm seeing this error when the browser attempts to upload the file:

<Error>
    <Code>InvalidAccessKeyId</Code>
    <Message>The AWS Access Key Id you provided does not exist in our records.</Message>
    <RequestId>...</RequestId>
    <HostId>...</HostId>
    <AWSAccessKeyId>ASIAxxxyyyzzz</AWSAccessKeyId>
</Error>

The value of ASIAxxxyyyzzz here comes from the instance role credentials, as obtained from the metadata service; it seems that those credentials can't be used outside of EC2 to facilitate browser based uploads.

I've looked at the Security Token Service as well to generate another set of temporary credentials by doing this:

$token = $sts->assumeRole(array(
    'RoleArn' => 'arn:aws:iam::xyz:role/mydomain.com',
    'RoleSessionName' => 'uploader',
));

$credentials = new Credentials($token['Credentials']['AccessKeyId'], $token['Credentials']['SecretAccessKey']);

The call givens me a new set of credentials, but it give the same error as above when I use it.

I hope that someone has done this before and can tell me what stupid thing I've missed out :)

like image 727
Ja͢ck Avatar asked Sep 19 '13 00:09

Ja͢ck


1 Answers

The AWS docs are very confusing on this, but I suspect that you need to include the x-amz-security-token parameter in the S3 upload POST request and that its value matches the SessionToken you get from STS ($token['Credentials']['SessionToken']).

STS temporary credentials are only valid when you include the corresponding security token.

The AWS documentation for the POST request states that:

Each request that uses Amazon DevPay requires two x-amz-security-token form fields: one for the product token and one for the user token.

but that parameter is also used outside of DevPay, to pass the STS token and you would only need to pass it once in the form fields.

like image 136
dcro Avatar answered Sep 21 '22 20:09

dcro