Setting ACLs via headers at PUT Object creation

Originally [reported](http://lists.basho.com/pipermail/riak-users_lists.basho.com/2013-July/012795.html) by Eugene Doudine via the riak-users mailing list.

Attempts to set ACLs via `x-amz-grant-*` headers during object creation (`PUT`) are ignored. Setting them after an object is created via the XML body of a `PUT` with the query string parameter `?acl` appended works.

Test case using the AWS Ruby SDK:

```ruby
require "aws-sdk"
require "logger"

AWS.config(
  logger: Logger.new($stdout),
  log_formatter: AWS::Core::LogFormatter.debug,
  log_level: :debug
)

s3 = AWS::S3.new(
  # Credentials for admin@admin.com.
  access_key_id: "T3J4N9T8PNLAJMYLSWXB",
  secret_access_key: "oWl6LH9BJumR6tFMvzc8KduClDKfFYxi3ADXPA==",
  proxy_uri: "http://localhost:8888", # 8888 is for Charles Proxy
  use_ssl: false,
  http_read_timeout: 2000,
  max_retries: 0
)

timestamp   = Time.now.to_i
bucket_name = "acl-test-bucket-#{timestamp}"
object_name = "acl-test-object-#{timestamp}"

bucket = s3.buckets.create(bucket_name)

# Attempt to set ACLs at object creation time.
s3.buckets[bucket_name].objects[object_name].write("Joker",
  grant_full_control: "emailAddress\"admin@admin.com\"",
  grant_read: "emailAddress=\"acl_test@basho.com\""
)

# List ACLs to see if it worked -- it doesn't.
s3.buckets[bucket_name].objects[object_name].acl

# Create similar ACLs to those above.
acl = AWS::S3::AccessControlList.new
acl.grant(:full_control).to(amazon_customer_email: "admin@admin.com")
acl.grant(:read).to(amazon_customer_email: "acl_test@basho.com")

# Apply those ACLs after the object is created.
s3.buckets[bucket_name].objects[object_name].acl = acl

# List ACLs to see if it worked -- it did.
s3.buckets[bucket_name].objects[object_name].acl
```

Debugging output of the above script running against a local Riak CS instance with two active users:

```
+-------------------------------------------------------------------------------
| AWS us-east-1 S3 create_bucket 0.028978 0 retries
+-------------------------------------------------------------------------------
|   REQUEST
+-------------------------------------------------------------------------------
|    METHOD: PUT
|       URL: http://acl-test-bucket-1375233769.s3.amazonaws.com::80:/
|   HEADERS: {"user-agent"=>"aws-sdk-ruby/1.14.1 ruby/1.9.3 x86_64-darwin12.4.0", "date"=>"Wed, 31 Jul 2013 01:22:49 GMT", "authorization"=>"AWS T3J4N9T8PNLAJMYLSWXB:xoSN9EAmxvEl1LugYMfPpk6ic0c="}
|      BODY:
+-------------------------------------------------------------------------------
|  RESPONSE
+-------------------------------------------------------------------------------
|    STATUS: 200
|   HEADERS: {"server"=>["Riak CS"], "date"=>["Wed, 31 Jul 2013 01:22:49 GMT"], "content-type"=>["application/xml"], "content-length"=>["0"], "proxy-connection"=>["Keep-alive"]}
|      BODY:
+-------------------------------------------------------------------------------
| AWS us-east-1 S3 put_object 0.018525 0 retries
+-------------------------------------------------------------------------------
|   REQUEST
+-------------------------------------------------------------------------------
|    METHOD: PUT
|       URL: http://acl-test-bucket-1375233769.s3.amazonaws.com::80:/acl-test-object-1375233769
|   HEADERS: {"content-length"=>5, "x-amz-grant-read"=>"emailAddress=\"acl_test@basho.com\"", "x-amz-grant-full-control"=>"emailAddress\"admin@admin.com\"", "user-agent"=>"aws-sdk-ruby/1.14.1 ruby/1.9.3 x86_64-darwin12.4.0", "date"=>"Wed, 31 Jul 2013 01:22:49 GMT", "authorization"=>"AWS T3J4N9T8PNLAJMYLSWXB:yqhecCmkheKGsuIscKP1HSMU/sg="}
|      BODY:
+-------------------------------------------------------------------------------
|  RESPONSE
+-------------------------------------------------------------------------------
|    STATUS: 200
|   HEADERS: {"server"=>["Riak CS"], "etag"=>["\"e55318040a854ebdc8d0508d2522bee5\""], "date"=>["Wed, 31 Jul 2013 01:22:49 GMT"], "content-type"=>["text/plain"], "content-length"=>["0"], "proxy-connection"=>["Keep-alive"]}
|      BODY:
+-------------------------------------------------------------------------------
| AWS us-east-1 S3 get_object_acl 0.013928 0 retries
+-------------------------------------------------------------------------------
|   REQUEST
+-------------------------------------------------------------------------------
|    METHOD: GET
|       URL: http://acl-test-bucket-1375233769.s3.amazonaws.com::80:/acl-test-object-1375233769?acl
|   HEADERS: {"user-agent"=>"aws-sdk-ruby/1.14.1 ruby/1.9.3 x86_64-darwin12.4.0", "date"=>"Wed, 31 Jul 2013 01:22:49 GMT", "authorization"=>"AWS T3J4N9T8PNLAJMYLSWXB:QW094CPm9FHBaQZk5CcjgAwT58g="}
|      BODY:
+-------------------------------------------------------------------------------
|  RESPONSE
+-------------------------------------------------------------------------------
|    STATUS: 200
|   HEADERS: {"server"=>["Riak CS"], "date"=>["Wed, 31 Jul 2013 01:22:49 GMT"], "content-type"=>["application/octet-stream"], "content-length"=>["495"], "proxy-connection"=>["Keep-alive"]}
|      BODY: <?xml version="1.0" encoding="UTF-8"?><AccessControlPolicy><Owner><ID>51e365ea87a8cfb147ed24533cc36493f6664880c6960f5e378b1dcfe5d43039</ID><DisplayName>admin</DisplayName></Owner><AccessControlList><Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>51e365ea87a8cfb147ed24533cc36493f6664880c6960f5e378b1dcfe5d43039</ID><DisplayName>admin</DisplayName></Grantee><Permission>FULL_CONTROL</Permission></Grant></AccessControlList></AccessControlPolicy>
+-------------------------------------------------------------------------------
| AWS us-east-1 S3 put_object_acl 0.041236 0 retries
+-------------------------------------------------------------------------------
|   REQUEST
+-------------------------------------------------------------------------------
|    METHOD: PUT
|       URL: http://acl-test-bucket-1375233769.s3.amazonaws.com::80:/acl-test-object-1375233769?acl
|   HEADERS: {"content-length"=>529, "user-agent"=>"aws-sdk-ruby/1.14.1 ruby/1.9.3 x86_64-darwin12.4.0", "date"=>"Wed, 31 Jul 2013 01:22:49 GMT", "authorization"=>"AWS T3J4N9T8PNLAJMYLSWXB:mhdmPbILw1l3XqSdatQTTpeqiyE="}
|      BODY: <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><AccessControlList><Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="AmazonCustomerByEmail"><EmailAddress>admin@admin.com</EmailAddress></Grantee><Permission>FULL_CONTROL</Permission></Grant><Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="AmazonCustomerByEmail"><EmailAddress>acl_test@basho.com</EmailAddress></Grantee><Permission>READ</Permission></Grant></AccessControlList></AccessControlPolicy>
+-------------------------------------------------------------------------------
|  RESPONSE
+-------------------------------------------------------------------------------
|    STATUS: 200
|   HEADERS: {"server"=>["Riak CS"], "date"=>["Wed, 31 Jul 2013 01:22:49 GMT"], "content-type"=>["text/plain"], "content-length"=>["0"], "proxy-connection"=>["Keep-alive"]}
|      BODY:
+-------------------------------------------------------------------------------
| AWS us-east-1 S3 get_object_acl 0.010334 0 retries
+-------------------------------------------------------------------------------
|   REQUEST
+-------------------------------------------------------------------------------
|    METHOD: GET
|       URL: http://acl-test-bucket-1375233769.s3.amazonaws.com::80:/acl-test-object-1375233769?acl
|   HEADERS: {"user-agent"=>"aws-sdk-ruby/1.14.1 ruby/1.9.3 x86_64-darwin12.4.0", "date"=>"Wed, 31 Jul 2013 01:22:49 GMT", "authorization"=>"AWS T3J4N9T8PNLAJMYLSWXB:QW094CPm9FHBaQZk5CcjgAwT58g="}
|      BODY:
+-------------------------------------------------------------------------------
|  RESPONSE
+-------------------------------------------------------------------------------
|    STATUS: 200
|   HEADERS: {"server"=>["Riak CS"], "date"=>["Wed, 31 Jul 2013 01:22:49 GMT"], "content-type"=>["application/octet-stream"], "content-length"=>["676"], "proxy-connection"=>["Keep-alive"]}
|      BODY: <?xml version="1.0" encoding="UTF-8"?><AccessControlPolicy><Owner><ID></ID><DisplayName></DisplayName></Owner><AccessControlList><Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>51e365ea87a8cfb147ed24533cc36493f6664880c6960f5e378b1dcfe5d43039</ID><DisplayName>admin</DisplayName></Grantee><Permission>FULL_CONTROL</Permission></Grant><Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>d9fc95243a15bcb0253977cb65a8ed51204ed16c848241eb409a04c1e196bf07</ID><DisplayName>acl_test</DisplayName></Grantee><Permission>READ</Permission></Grant></AccessControlList></AccessControlPolicy>
```