TAGS

cors

How to enable CORS while accessing Object Storage Containers

If you want to access your objects in your Object Store Container from another domain, you will encounter CORS problem.

The article will show how to configure your container to enable CORS.

Let's assume, that you have already created 2 files in a container:

containers

If you make the container public by checking the "Public Access" checkbox, you can get the link to the objects by clicking on "Link".

Then you can access the objects by inserting the link (e.g. https://cf2.cloudferro.com:8080/swift/v1/AUTH_8b72c381c7724c44b971e6a5862a0b94/container-nr-1/) into your browser:

We will simulate the CORS problem by using the file from the OpenStack article: https://docs.openstack.org/swift/latest/cors.html#test-cors-page

The file is the following:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test CORS</title>
  </head>
  <body>

    Token<br><input id="token" type="text" size="64"><br><br>

    Method<br>
    <select id="method">
        <option value="GET">GET</option>
        <option value="HEAD">HEAD</option>
        <option value="POST">POST</option>
        <option value="DELETE">DELETE</option>
        <option value="PUT">PUT</option>
    </select><br><br>

    URL (Container or Object)<br><input id="url" size="64" type="text"><br><br>

    <input id="submit" type="button" value="Submit" onclick="submit(); return false;">

    <pre id="response_headers"></pre>
    <p>
    <hr>
    <pre id="response_body"></pre>

    <script type="text/javascript">
      function submit() {
          var token = document.getElementById('token').value;
          var method = document.getElementById('method').value;
          var url = document.getElementById('url').value;

          document.getElementById('response_headers').textContent = null;
          document.getElementById('response_body').textContent = null;

          var request = new XMLHttpRequest();

          request.onreadystatechange = function (oEvent) {
              if (request.readyState == 4) {
                  responseHeaders = 'Status: ' + request.status;
                  responseHeaders = responseHeaders + '\nStatus Text: ' + request.statusText;
                  responseHeaders = responseHeaders + '\n\n' + request.getAllResponseHeaders();
                  document.getElementById('response_headers').textContent = responseHeaders;
                  document.getElementById('response_body').textContent = request.responseText;
              }
          }

          request.open(method, url);
          if (token != '') {
              // custom headers always trigger a pre-flight request
              request.setRequestHeader('X-Auth-Token', token);
          }
          request.send(null);
      }
    </script>

  </body>
</html>

Please open the file in the browser:

test CORS

insert the link obtained previously: https://cf2.cloudferro.com:8080/swift/v1/AUTH_8b72c381c7724c44b971e6a5862a0b94/container-nr-1/

now click on "Submit" button:

If you open console in the browser, you will see the message informing that access was blocked.

Now prepare the Python environment according to the article:

HOW TO INSTALL OPENSTACKCLIENT (LINUX)?

and source the RC file:

$ source jdoe-test.sh
Please enter your OpenStack Password for project test_project as user john.doe@cloudferro.com:

You can check if you can see the container and objects by invoking the following commands:

$ openstack container list
+----------------+
| Name           |
+----------------+
| container-nr-1 |
+----------------+

$ openstack object list container-nr-1
+---------------+
| Name          |
+---------------+
| file-nr-1.txt |
| file-nr-2.txt |
+---------------+

Now you should generate EC2 credentials according to the article:

How to generate ec2 credentials?

$ openstack ec2 credentials create -f json
{
  "access": "<access code>",
  "access_token_id": null,
  "links": {
    "self": "https://cf2.cloudferro.com:5000/v3/users/<user id>/credentials/OS-EC2/<access code>"
  },
  "project_id": "8b72c381c7724c44b971e6a5862a0b94",
  "secret": "<secret code>",
  "trust_id": null,
  "user_id": "<user id>"
}

Now you need to configure s3cmd tool

HOW TO ACCESS PRIVATE OBJECT STORAGE USING S3CMD OR BOTO3?

 

Below is the simplified configuration:

You need to create a config file e.g. jdoe-test-s3cfg

 

with the following content:

location = RegionOne
access_key = <access code>
host_base = cf2.cloudferro.com:8080
host_bucket = cf2.cloudferro.com:8080
secret_key = <secret code>

 

Now you can check the properties of your container:

$ s3cmd -c jdoe-test-s3cfg info s3://container-nr-1
s3://container-nr-1/ (bucket):
   Location:  dias_default
   Payer:     BucketOwner
   Expiration Rule: none
   Policy:    none
   CORS:      none
   ACL:       test_project: FULL_CONTROL

Now prepare another file: cors.xml

<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

 

and invoke the following command:

$ s3cmd -c jdoe-test-s3cfg setcors cors.xml s3://container-nr-1

Now check the properties of the container:

$ s3cmd -c jdoe-test-s3cfg info s3://container-nr-1
s3://container-nr-1/ (bucket):
   Location:  dias_default
   Payer:     BucketOwner
   Expiration Rule: none
   Policy:    none
   CORS:      <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><CORSRule><AllowedMethod>GET</AllowedMethod><AllowedOrigin>*</AllowedOrigin><AllowedHeader>*</AllowedHeader></CORSRule></CORSConfiguration>
   ACL:       test_project: FULL_CONTROL

and test the cors-test.html file again

The screen above shows that CORS has been enabled.