FrankN
FrankN

Reputation: 33

S3 HTML POST Request

I have a html page running on GAE that I'd like to use to allow users to upload text files from their computers to my bucket on s3. Below is the code for that:

----- HTML Code-----

<!DOCTYPEhtml PUBLIC "-//W3C//DTDXHTML 1.0 transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-trnasitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">

  <head>
    <title>S3 POST Form</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link href="/static/def.css" rel="stylesheet" type="text/css"/>
    <title> Upload Page </title>
  </head>

  <body> 
    <form action="https://mys3bucket.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
      <input type="hidden" name="key" value="uploads/${filename}">
      <input type="hidden" name="AWSAccessKeyId" value="Put access key id here"> 
      <input type="hidden" name="acl" value="public-read"> 
      <input type="hidden" name="success_action_redirect" value="https://mys3bucket.s3.amazonaws.com/complete.htm">
      <input type="hidden" name="policy" value="***---How do I calculate this?---***">
      <input type="hidden" name="signature" value="***---How do I calculate this?---***">
      <!-- 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> 
  </body>
</html>

I'm having trouble calculating the policy and the signature values.

I was searching around and the general theme seems to be that the policy document is a JSON file, but I don't know exactly which fields I would need in the JSON file or how I would then plug that json file into the policy field. The general theme for the fields seems to be that they need to be calculated using a HMAC and base64 encoding, if so, how do I go about doing this?

I found some python code that is supposed to encode evrything but it doesn't seem to be working.

Thanks.

F

------ Below is the JSON file ------- (Updated)

       {
    "expiration": "2014-06-009T12:00:00.000Z",
    "conditions": [
        {
            "bucket": "https://mys3bucket.s3.amazonaws.com/"
        },
        {
            "$key": "uploads/${filename}"
        },
        {
            "AWSAccessKeyId": "axaxaxaxaxax"
        },
        {
            "acl": "public-read"
        },
        {
            "redirect": "http://mys3bucket.s3.amazonaws.com/complete.htm"
        }
    ]
}

------ Error MEssage -------

This is the error message I receive when I upload the application and run it:

<Error>
    <Code>InvalidPolicyDocument</Code>
    <Message>
      Invalid Policy: Expecting String Literal but found Field Reference
    </Message>
    <RequestId>6E2CADE36E18DDBA</RequestId>
    <HostId>
      gxxd2YJLcIz+wAVzasBc9yOpW0GOok1dAWwH2apv28epGhuAXGS/z4WiAtznUTLt
    </HostId>
</Error>

------ BAse 64 Python Programme ------

Below is a small programme I found that is supposed to encode the policy and the signature for me, is this correct, and if so where am I going wrong then?

import base64
import hmac, hashlib

secret_access_key = "ssxsxsxsxsxsxsxsxsxsx"

with open('GAEPOST.json') as file:
        policy_document = file.read()
        policy = base64.b64encode(policy_document)
        signature = base64.b64encode(hmac.new(secret_access_key, policy, hashlib.sha1).digest())

        print "This is the signature: " + signature
        print "This is the policy: " + policy

Upvotes: 1

Views: 760

Answers (1)

Basti
Basti

Reputation: 4042

I encountered the same problem just yet.

Invalid Policy: Expecting String Literal but found Field Reference occures when you put a "variable" as key for the condition like $key in this example

{
  "expiration": "2015-6-18T09:02:17.000Z", 
  "conditions": [
    {"acl": "public-read"}, 
    {"bucket": "my-bucket"}, 
    {"$key": "my-file.png"}, // INVALID CONDITION
    ["eq", "$Content-Type", "image/png"]
  ]
}

You have to put either {"key": "my-file.png"} (no $) or ["eq", "$key", "my-file.png"] (with $). Those two conditions are valid and equal.

So your example this condition is invalid:

{"$key": "uploads/${filename}"}

and should be replace by one of these

["eq", "$key": "uploads/${filename}"]
["starts-with", "$key": "uploads/"]

To address the second problem you described in the comments (["eq", "$bucket", "<bucket url>"]): you don't put the full bucket url into this condition, just the name of the bucket.

So instead of the condition {"bucket": "https://mys3bucket.s3.amazonaws.com/"} you put {"bucket": "mys3bucket"} or ["eq", "$bucket": "mys3bucket"].

I'll link the documentation for the exact syntax regardless of the fact that amazon keeps changing their URLs and the link will probably be dead withing months.

Upvotes: 5

Related Questions