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):
- 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.
- 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?
- Set it to "public-read-write". Result is exactly as in (1).
- Set it to "authenticated-read". "Authenticated users" get "read" permission, bucket owner has full control.
- Set it to "bucket-owner-read". Result is exactly as in (2). Bucket owner has full control, no other permissions are defined.
- Set it to "bucket-owner-full-control". Unsurprisingly, bucket owner will have full control.
- Set it to a non-existant canned ACL name and get an error.
So it seems, that
- 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.
- x-amz-acl query string parameter does not influence the object's permissions directly, as in, it does nothing on its own.
- 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.
- 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 thex-amz-acl
header toauthenticated-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?