codekiln
codekiln

Reputation: 3720

Amazon S3 CORS works with HTTP but not HTTPS

I can get Amazon S3 to pass CORS headers with http, but not with https. How do I get it to work with both? What if we're using Akamai as a CDN?

Here's my bucket configuration:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   <CORSRule>
        <AllowedOrigin>https://*</AllowedOrigin>
        <AllowedOrigin>http://*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule> 
</CORSConfiguration>

Here's my test. The only difference between these is that one uses http, the other uses https. Both resources load just fine in the browser, but I would like to use them in a CORS setting where it could be https.

pnore@mbp> curl -i -H "Origin: http://example.com"   -H "Access-Control-Request-Method: GET" -H 'Pragma: no-cache' --verbose http://my.custom.domain/path/to/file/in/bucket | head -n 15
* Adding handle: conn: 0x7fee83803a00
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fee83803a00) send_pipe: 1, recv_pipe: 0
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* About to connect() to my.custom.domain port 80 (#0)
*   Trying 23.23.23.23...
* Connected to my.custom.domain (23.23.23.23) port 80 (#0)
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0> GET /path/to/file/in/bucket HTTP/1.1
> User-Agent: curl/7.30.0
> Host: my.custom.domain
> Accept: */*
> Origin: http://example.com
> Access-Control-Request-Method: GET
> Pragma: no-cache
>
< HTTP/1.1 200 OK
< x-amz-id-2: random
< x-amz-request-id: random
< Access-Control-Allow-Origin: http://example.com
< Access-Control-Allow-Methods: GET
< Access-Control-Max-Age: 3000
< Access-Control-Allow-Credentials: true
< Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
< Last-Modified: Tue, 10 Jun 2014 15:34:38 GMT
< ETag: "random"
< Accept-Ranges: bytes
< Content-Type: video/webm
< Content-Length: 8981905
* Server AmazonS3 is not blacklisted
< Server: AmazonS3
< Date: Fri, 19 Jun 2015 21:31:22 GMT
< Connection: keep-alive
<
{ [data not shown]
HTTP/1.1 200 OK
x-amz-id-2: random
x-amz-request-id: random
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Access-Control-Allow-Credentials: true
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Tue, 10 Jun 2014 15:34:38 GMT
ETag: "random"
Accept-Ranges: bytes
Content-Type: video/webm
Content-Length: 8981905
Server: AmazonS3
Date: Fri, 19 Jun 2015 21:31:22 GMT
...

pnore@mbp> curl -i -H "Origin: http://example.com"   -H "Access-Control-Request-Method: GET" -H 'Pragma: no-cache' --verbose https://my.custom.comain/path/to/file/in/bucket | head -n 15
* Adding handle: conn: 0x7fd24380c000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fd24380c000) send_pipe: 1, recv_pipe: 0
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* About to connect() to my.custom.domain port 443 (#0)
*   Trying 23.23.23.23...
* Connected to my.custom.domain (23.23.23.23) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_AES_256_CBC_SHA
* Server certificate: my.custom.domain
* Server certificate: GeoTrust SSL CA - G4
* Server certificate: GeoTrust Global CA
> GET /path/to/file/in/bucket HTTP/1.1
> User-Agent: curl/7.30.0
> Host: my.custom.domain
> Accept: */*
> Origin: http://example.com
> Access-Control-Request-Method: GET
> Pragma: no-cache
>
< HTTP/1.1 200 OK
< x-amz-id-2: 
< x-amz-request-id: 
< Last-Modified: Tue, 10 Jun 2014 15:34:38 GMT
< ETag: "random"
< Accept-Ranges: bytes
< Content-Type: video/webm
< Content-Length: 8981905
* Server AmazonS3 is not blacklisted
< Server: AmazonS3
< Date: Fri, 19 Jun 2015 21:31:29 GMT
< Connection: keep-alive
<
{ [data not shown]
HTTP/1.1 200 OK
x-amz-id-2: 
x-amz-request-id: 
Last-Modified: Tue, 10 Jun 2014 15:34:38 GMT
ETag: "random"
Accept-Ranges: bytes
Content-Type: video/webm
Content-Length: 8981905
Server: AmazonS3
Date: Fri, 19 Jun 2015 21:31:29 GMT
Connection: keep-alive

...

Note that the first request contains the desired Access-Control-Allow-Origin header, and the second does not.

I've also tried <AllowedOrigin>*</AllowedOrigin> and using different <CORSRule> blocks for each <AllowedOrigin>.

References I've checked:

  1. Getting S3 CORS Access-Control-Allow-Origin to dynamically echo requesting domain 1
  2. Amazon S3 CORS (Cross-Origin Resource Sharing) and Firefox cross-domain font loading 1
  3. Getting S3 CORS Access-Control-Allow-Origin to dynamically echo requesting domain
  4. Aws S3 Bucket CORS configuration is not saving properly
  5. http://blog.errorception.com/2014/11/enabling-cors-on-amazon-cloudfront-with.html
  6. Correct S3 + Cloudfront CORS Configuration?
  7. https://forums.aws.amazon.com/thread.jspa?messageID=377513
  8. How to Configure SSL for Amazon S3 bucket
  9. HTTPS for Amazon S3 static website
  10. SSL on Amazon S3 as "static website"

Upvotes: 3

Views: 3674

Answers (1)

coryfoo
coryfoo

Reputation: 191

I couldn't find documentation that explicitly mentioned it, but it appears that the CORS configuration for the bucket only allows one <AllowedOrigin> per <CORSRule> element entry. You are allowed up to 100 <CORSRule> entries in the configuration. Therefore, in order to get your configuration to support both http and https you should create two <CORSRule> entries, like so:

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>https://*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule> 
  <CORSRule>
    <AllowedOrigin>http://*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule> 
</CORSConfiguration>

FWIW, I have not tried it, but the configuration may also support a protocol agnostic format, e.g. simply <AllowedOrigin>//*</AllowedOrigin>.

Upvotes: 5

Related Questions