cfritz1
1 Copper

CORS Allowed Origin Issue

Jump to solution

I am configuring a bucket on a customer's ECS appliance and having an issue with CORS. I have uploaded the configuration via boto and confirmed it was set using the below anonymized code:

#!/bin/python

import ssl

from boto.s3.connection import S3Connection

from boto.s3.cors import CORSConfiguration

conn = S3Connection(aws_access_key_id=s3_accessKeyId,

                aws_secret_access_key=s3_secretKey,

                host=s3_host,

                port=s3_port,

                calling_format='boto.s3.connection.ProtocolIndependentOrdinaryCallingFormat',

                is_secure=True)

ssl._create_default_https_context = ssl._create_unverified_context

bucket = conn.get_bucket(s3_bucket)

cors_xml = """

<CORSConfiguration>

    <CORSRule>

        <AllowedOrigin>https://[our_domain]</AllowedOrigin>

        <AllowedMethod>GET</AllowedMethod>

        <AllowedMethod>PUT</AllowedMethod>

        <AllowedMethod>POST</AllowedMethod>

        <AllowedMethod>HEAD</AllowedMethod>

        <ExposeHeader>Accept-Ranges</ExposeHeader>

        <ExposeHeader>Content-Range</ExposeHeader>

        <ExposeHeader>Content-Encoding</ExposeHeader>

        <ExposeHeader>Content-Length</ExposeHeader>

        <AllowedHeader>*</AllowedHeader>

    </CORSRule>

</CORSConfiguration>

"""

bucket.set_cors_xml(cors_xml)

print "Current CORS:\n" + bucket.get_cors_xml()

This is the same CORS configuration used on AWS without issue. Below is the output from the script confirming it has been set:

$ python script.py

Current CORS:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><CORSRule><AllowedMethod>GET</AllowedMethod><AllowedMethod>PUT</AllowedMethod><AllowedMethod>POST</AllowedMethod><AllowedMethod>HEAD</AllowedMethod><AllowedOrigin>https://[our_domain]</AllowedOrigin><AllowedHeader>*</AllowedHeader><ExposeHeader>Accept-Ranges</ExposeHeader><ExposeHeader>Content-Range</ExposeHeader><ExposeHeader>Content-Encoding</ExposeHeader><ExposeHeader>Content-Length</ExposeHeader></CORSRule></CORSConfiguration>

The "Origin" is being properly set in the request and matches the CORS config. I am using the AWS SDK for Javascript aws-sdk-js/2.2.30. Below are the console errors in the browser:

[Error] Failed to load resource: the server responded with a status of 400 (Bad Request) ([s3_bucket], line 0)

[Error] Failed to load resource: Origin https://[our_domain] is not allowed by Access-Control-Allow-Origin. ([s3_bucket], line 0)

[Error] XMLHttpRequest cannot load https://[s3_host]:[s3_port]/[s3_bucket]. Origin https://[our_domain] is not allowed by Access-Control-Allow-Origin.

I have even tried setting <AllowedOrigin>https://*</AllowedOrigin> with the same result. It's as if the CORS configuration is being ignored? How do I fix this?

The customer is running ECS v2.2.3 on their appliance.

0 Kudos
1 Solution

Accepted Solutions
JasonCwik
3 Argentium

Re: Re: Re: CORS Allowed Origin Issue

Jump to solution

Unfortunately, issuing the OPTIONS request yourself is not an option; the JavaScript runtime always generates its own OPTIONS request for security reasons and you have no control over that.  It appears the only solution here is to use namespace BaseURLs.

Note that for testing purposes, you can do all this through your /etc/hosts file, simply add:

namespace.ecs.yourdomain.com     xxx.xxx.xxx.xxx

And configure the BaseURL ecs.yourdomain.com inside ECS.  ECS does not need to verify this hostname with DNS; it simply uses it to parse hosts to differentiate between path-style requests and virtually-hosted requests (i.e. namespace.ecs.yourdomain.com/bucket vs. bucket.namespace.ecs.yourdomain.com).

0 Kudos
8 Replies
JasonCwik
3 Argentium

Re: CORS Allowed Origin Issue

Jump to solution

Hi Casey,

Have you configured ECS to use a "with namespace" BaseURL?  Since the OPTIONS preflight for CORS is an anonymous request, we must know the bucket name and the namespace to properly locate the bucket and parse its CORS config.

For example, you'll need to be making requests to:

https://namespace.ecs.company.com/bucket

And ECS will need to have an Object Base URL defined for ecs.company.com with the option "Use base URL with Namespace e.g. bucket.namespace.baseurl" selected.

0 Kudos
cfritz1
1 Copper

Re: Re: CORS Allowed Origin Issue

Jump to solution

Hi Jason,

Thanks for the quick response!  I have not configured the BaseURL on the ECS appliance and instead I am addressing it using an IP address. I thought it might have something to do with the namespace and so I specifically designated the namespace in a request header as seen below:

var request = self.s3.listObjects();

// SET NAMESPACE

request.on('build', function() {

     request.httpRequest.headers['x-emc-namespace'] = [ecs_namespace];

});

Accepttext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encodinggzip, deflate, br
Accept-Languageen-US,en;q=0.5
AuthorizationAWS [s3_accessKeyId]:[s3_secretKey_hash]
Connectionkeep-alive
Host[s3_host]:[s3_port]
Originhttps://[our_domain]
Refererhttps://[our_domain]/app/
User-AgentMozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:44.0) Gecko/20100101 Firefox/44.0
X-Amz-DateWed, 27 Apr 2016 15:27:03 GMT
X-Amz-User-Agentaws-sdk-js/2.2.30
x-emc-namespace[ecs_namespace]

It still returns the same error in the console unfortunately. Is the only way to add a BaseURL to ECS?

0 Kudos
JasonCwik
3 Argentium

Re: Re: CORS Allowed Origin Issue

Jump to solution

Can you see if the runtime is generating an OPTIONS request before your GET?  If it is, that request won't have any custom headers and thus, no namespace.

0 Kudos
cfritz1
1 Copper

Re: Re: Re: CORS Allowed Origin Issue

Jump to solution

Jason,

Firefox showed the OPTIONS request happening after the GET but being aborted (which is probably just a quirk of Firefox as the OPTIONS request would logically be occurring first). I switched to Chrome and see in the console that it is an OPTIONS request that is failing:

aws-sdk-2.2.30.min.js:14 OPTIONS https://[s3_host]:[s3_port]/[s3_bucket] net::ERR_INSECURE_RESPONSE

However, the error itself seems to do with the SSL cert? I will look into ignoring self-signed certs with the aws sdk as the customer hasn't replaced the default certs.

Chrome reports the following request headers on the OPTIONS request:

    1. Provisional headers are shown
    2. Access-Control-Request-Headers:authorization, x-amz-date, x-amz-user-agent, x-emc-namespace
    3. Access-Control-Request-Method:GET
    4. Origin:https://[our_domain]
    5. Referer:https://[our_domain]/app/
    6. User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36

I am not sure why it says "Provisional headers are shown". Perhaps these are the headers that would be sent dependent on the response from the OPTIONS request. I haven't been able to intercept the OPTIONS request itself with something like wireshark as traffic is encrypted. However it seems to line up with what you have said. As the OPTIONS request is generated by the client browser I guess I am unable to set a custom header. Maybe if I can manually issue an OPTIONS request with the custom header from within my code will this prevent the issue?? Otherwise it seems I will need to configure DNS and a BaseURL on the customer's ECS appliance which I was trying to avoid.


Thanks for the help!

0 Kudos
JasonCwik
3 Argentium

Re: Re: Re: CORS Allowed Origin Issue

Jump to solution

Unfortunately, issuing the OPTIONS request yourself is not an option; the JavaScript runtime always generates its own OPTIONS request for security reasons and you have no control over that.  It appears the only solution here is to use namespace BaseURLs.

Note that for testing purposes, you can do all this through your /etc/hosts file, simply add:

namespace.ecs.yourdomain.com     xxx.xxx.xxx.xxx

And configure the BaseURL ecs.yourdomain.com inside ECS.  ECS does not need to verify this hostname with DNS; it simply uses it to parse hosts to differentiate between path-style requests and virtually-hosted requests (i.e. namespace.ecs.yourdomain.com/bucket vs. bucket.namespace.ecs.yourdomain.com).

0 Kudos
cfritz1
1 Copper

Re: Re: Re: CORS Allowed Origin Issue

Jump to solution

Is this why connecting via cyberduck and python can work without specifying a namespace?

Also I assume ECS supports multiple baseURLs?

0 Kudos
JasonCwik
3 Argentium

Re: Re: Re: CORS Allowed Origin Issue

Jump to solution

No, cyberduck and python work because they don't require CORS and always use authenticated requests.  For authenticated requests, we take your username and look up the namespace that user is assigned to.  The issue is that the OPTIONS request issued by JavaScript is anonymous and thus, we don't have your username to look up the namespace.  At that point, the only way to get the namespace information is to grab it from the hostname on the URL.

PankajHCL1
1 Copper

Re: CORS Allowed Origin Issue

Jump to solution

p

0 Kudos