Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pre-signed URLs and x-amz-acl

I want to create a so-called "pre-signed" URL for uploading a particular object (PUT) to Amazon S3 bucket.

So far so good. I am using the python library boto to create an URL, that contains all necessary stuff (expires, signature and so on). The URL looks like this:

https://<bucketname>.s3.amazonaws.com/<key>?Signature=<sig>&Expires=<expires>&AWSAccessKeyId=<my key id>&x-amz-acl=public-read

Note the last parameter.

This, at least, as I understand, limits whoever uses this URL to uploading an object to a particular key in a particular bucket and also limits the canned ACL that will be set on the object to "public-read".

My last statement is quite incorrect though.

As it turns out, if you are using this URL, you can do the following with the x-amz-acl header (as opposed to the query string parameter with the same name, that you must set for the signature check to succeed):

  1. Set it to "public-read". The object's permissions will consist of two entries: "read" for "Everyone" and "full control" for bucket owner. This is quite expected.
  2. Omit the x-amz-acl header. The permissions on the object will be the same as the per-bucket default (bucket owner has full control). Why?
  3. Set it to "public-read-write". Result is exactly as in (1).
  4. Set it to "authenticated-read". "Authenticated users" get "read" permission, bucket owner has full control.
  5. Set it to "bucket-owner-read". Result is exactly as in (2). Bucket owner has full control, no other permissions are defined.
  6. Set it to "bucket-owner-full-control". Unsurprisingly, bucket owner will have full control.
  7. Set it to a non-existant canned ACL name and get an error.

So it seems, that

  1. The x-amz-acl header does not take part in the signature check, because you can change it at will and the request succeeds. The query string parameter, however, definitely is taken into account during the signature check.
  2. x-amz-acl query string parameter does not influence the object's permissions directly, as in, it does nothing on its own.
  3. If you send a x-amz-acl header, the resultant permissions never be
    • more restrictive for the bucket owner, than they are by default.
    • less restricvie for the non-bucket-owner.
  4. They can, however, be more restrictive for non-bucket-owner. That is, if you specify x-amz-acl=public-read in the query string, you can set the x-amz-acl header to authenticated-read and instead of a publicly readable object get an object, that can be only read by authenticated users.

What is the real relation between the x-amz-acl QS parameter and the header, that goes by the same name? Is there a way to restrict permissions on the object, that is to be uploaded via a PUT request to a so-called "pre-signed" URL?

like image 918
shylent Avatar asked Dec 15 '12 20:12

shylent


1 Answers

As I understand it (and I might be wrong here), the header x-amz-acl takes priority over the querystring argument--and they do serve the same purpose. The reason that only the querystring parameter is taken into account during the signature check is simply due to the fact that headers are not part of the signature check for the policy.

This page might help you; it helped me a lot when creating forms to upload directly to S3.

like image 184
jdotjdot Avatar answered Oct 04 '22 12:10

jdotjdot