Skip to main content
Hitachi Vantara Knowledge

Using CORS to process cross-domain requests

HCP supports Cross-Origin Resource Sharing (CORS). CORS is a mechanism that uses additional HTTP headers to allow a web application running on a browser at one origin (domain) to have permission to access restricted resources on a server at a different origin. A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own.

To use CORS with HCP, you first need to configure CORS rules for a namespace to specify the sites that are allowed cross-origin access. Then, the HCP software validates incoming requests for compliance to these rules.

CORS rules are specific to a namespace and can be configured at either the namespace level or tenant level.

CORS use cases

With a proper CORS rules configuration for a namespace, the HCP software can process CORS requests from web applications hosted in a different domain (origin).

HCP supports the following CORS use cases.

Simple request

A simple request is a request that does not trigger a CORS preflight request. A simple request meets the following conditions:

  • The method request is GET, HEAD, or POST.
  • The only headers added manually are Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width.
  • The Content-Type header value is application/x-www-form-urlencoded, multipart/form-data, or text/plain.
  • No ReadableStream object or event listeners are registered on any XMLHttpRequestUpload object that the request uses.
Preflight request

A preflight request is a CORS request that checks to see if the CORS protocol is understood. It is an OPTIONS request that uses three HTTP request headers:

  • Access-Control-Request-Method
  • Access-Control-Request-Headers
  • Origin

A web browser automatically issues a preflight request when needed. The browser determines whether it needs to send a preflight request based on the web application request parameters used in the JavaScript code. If the HCP server approves the validity of the preflight request, the server responds with an approval response header. Then, the web browser sends the actual HTTP resource request.

If any of the following conditions is true, the browser uses a preflight request before the actual resource request:

  • The request uses the Authorization header.
  • The request uses one of these methods: PUT, DELETE, OPTIONS.
  • The request uses headers and a Content-Type other than the ones used for a simple request (described above).
  • The request contains event listeners registered on an HTMLHttpRequestUpload object or a ReadableStream object.

CORS limits

The HCP implementation of CORS has several limits.

Maximum size of a CORS policy

A CORS rules configuration in HCP can have any number of CORSRule, AllowedMethod, AllowedOrigin, and AllowedHeader elements. However, the maximum size of the CORS configuration cannot exceed 2.5 MB.

Unsupported namespace names for preflighted CORS requests

To safeguard an HCP instance, HCP does not support preflighted CORS requests for namespaces with path-style and virtual-path URLs that include the following reserved keywords:

  • rest
  • webdav
  • fcfs_data
  • browser
  • hs3
  • swift
Tenant-level API calls not supported

CORS does not support tenant-level API calls (S3 compatible API, REST API, HCP management API).

CORS rules configuration

Namespaces (buckets) to which you would like to allow cross-origin access must first be configured with CORS rules.

A CORS rules configuration is an XML document with rules that describe the external origins (domains), HTTP methods (operations), and HTTP headers that are allowed access to each bucket. You add the XML document to a bucket as a CORS subresource either programmatically or by using the Tenant Management Console or System Management Console, as described next.

CORS rules can be configured at the namespace level or tenant level.

  • To configure CORS rules for a namespace, use one of these interfaces:
    • Tenant Management Console
    • S3 compatible API
    • HCP management API
  • To configure CORS rules at the tenant level to server as the default for all namespaces owned by a tenant, use one of these interfaces:
    • System Management Console
    • HCP management API

    Setting CORS rules at the tenant level supports deployments in which a large number of HCP namespaces support the same CORS configuration.

    • If a namespace managed by the tenant does not have a CORS configuration, the namespace inherits the tenant-level configuration.
    • If a namespace has its own CORS configuration, the namespace-level configuration overrides the tenant-level configuration.

HCP permissions for CORS configuration

Users with the administrator or monitor role can read CORS settings at the namespace level or tenant level. Users with the administrator role can also modify CORS settings at the namespace level or tenant level.

The HCP software makes the following distinction between system-level users and tenant-level users. Typically, system-level users do not have tenant management capabilities. However, there is a configuration that grants system-level users tenant-management capabilities. In such instances, system-level users are allowed to configure CORS rules with the Tenant Management Console or HCP management API under the same read/write permissions described above.

Hitachi API for Amazon S3

The S3 compatible API makes the following distinction. When a system-level user has the administrator role and Allow system-level users to manage this tenant and search its namespaces in the Tenant Management Console is enabled:

  • The system-level user can perform namespace-level configuration operations with the HCP Authentication header.
  • The system-level user cannot perform namespace-level configuration operations with the Amazon Web Services (AWS) Authorization header (AWS Signature Version 2 or AWS Signature Version 4).

Request header and elements

A CORS rules configuration uses the request header and elements described in the next tables. Some of the request elements are optional.

Request header for a CORS rules configuration
  • Content-MD5

    The base64-encoded 128-bit MD5 digest of the data. This header must be used as a message integrity check to verify that the request body was not corrupted in transit.

Request elements for CORS rules configuration
  • CORSConfiguration

    Container for CORSRules elements.

    Type: Container

    Children: CORSRules

    Ancestor: None

    A CORS rules configuration in HCP can have any number of CORSRule, AllowedMethod, AllowedOrigin, and AllowedHeader elements. However, the maximum size of the CORS configuration cannot exceed 2.5 MB.

  • CORSRule

    A set of origins and methods that you want to allow to access a resource.

    Type: Container

    Children: AllowedMethod, AllowedOrigin, AllowedHeader, MaxAgeSeconds, ExposeHeader

    Ancestor: CORSConfiguration

  • Id

    Optional

    A unique identifier for the rule. The Id value assists you in finding a rule in the CORS configuration.

    Type: String

    Ancestor: CORSRule

  • AllowedMethod

    HTTP methods that you want to allow the origin to execute. Each CORSRule must identify at least one origin and one method.

    Type: Enum (GET, PUT, HEAD, POST, DELETE)

    Ancestor: CORSRule

  • AllowedOrigin

    Origins that you want to allow cross-origin requests from. Each CORSRule must identify at least one origin and one method.

    The origin value can include at most one wildcard character "*", for example, http://*.example.com. Alternatively, you can specify thewildcard character by itself to enable all origins to send cross-origin requests.

    Type: String

    Ancestor: CORSRule

  • AllowedHeader

    Optional

    List of headers that are allowed in a preflight OPTIONS request through the Access-Control-Request-Headers header. This element can contain at most one wildcard character "*". Each header name in the Access-Control-Request-Headers header must have a corresponding entry in the CORSRule. The server will send only the allowed headers that were requested in a response.

    Type: String

    Ancestor: CORSRule

  • MaxAgeSeconds

    Optional

    Maximum time, in seconds, that the browser can cache a preflight OPTIONS response for a specified resource. By caching the response, the browser does not have to send preflight requests to the server within the MaxAgeSeconds time window if repeated requests (same origin, HTTP method, and resource) are issued.

    A CORSRule can have at most one MaxAgeSeconds element.

    Type: Integer (seconds)

    Ancestor: CORSRule

  • ExposeHeader

    Optional

    One or more response headers that customers can access from their applications, for example, from a JavaScript XMLHttpRequest object.

    You add one ExposeHeader element in the rule for each header. This element restricts the response headers that are accessible by the client.

    Type: String

    Ancestor: CORSRule

Example: PUT bucket request

The following PUT bucket request adds a CORS subresource to a bucket (namespace) named finance.

NoteEach S3 compatible request must be authenticated by the S3 gateway. You do this by using the HTTP Authorization request header with either a signature string, an AWS Version 2 or Version 4 authentication string, or by anonymous access.
Request headers
PUT /?cors HTTP/1.1
Host:finance.europe.hcp.example.com
x-amz-date: Tue, 14 May 2019 17:54:50 GMT
Content-MD5: 8dYiLewFWZyGgV2Q5FNI4W==
Authorization: SignatureString
Request body
<CORSConfiguration>
     <CORSRule>
          <AllowedOrigin>http://www.example.com</AllowedOrigin>
          <AllowedMethod>PUT</AllowedMethod>
          <AllowedMethod>POST</AllowedMethod>
          <AllowedMethod>DELETE</AllowedMethod>
          <AllowedHeader>*</AllowedHeader>
          <MaxAgeSeconds>3000</MaxAgeSec>
          <ExposeHeader>ETag</ExposeHeader>
     </CORSRule>
     <CORSRule>
          <AllowedOrigin>*</AllowedOrigin>
          <AllowedMethod>GET</AllowedMethod>
          <AllowedHeader>*</AllowedHeader>
          <MaxAgeSeconds>3000</MaxAgeSeconds>
     </CORSRule>
</CORSConfiguration>
Response headers
HTTP/1.1 200 OK
Date: Tue, 14 May 2019 17:54:50 GMT
Server: HCP

Example: GET bucket request

The following GET bucket request returns a CORS subresource from a bucket (namespace) named finance.

NoteEach S3 compatible request must be authenticated by the S3 gateway. You do this by using the HTTP Authorization request header with either a signature string, an AWS Version 2 or Version 4 authentication string, or by anonymous access.
Request headers
GET /?cors HTTP/1.1
Host:finance.europe.hcp.example.com
Date: Tue, 14 May 2019 2 17:54:50 GMT
Authorization: SignatureString
Response headers
HTTP/1.1 200 OK
Date: Tue, 14 May 2019 19:14:42 GMT
Server: HCP
Content-Length: 280
Response body
<CORSConfiguration>
     <CORSRule>
          <AllowedOrigin>http://www.example.com</AllowedOrigin>
          <AllowedMethod>PUT</AllowedMethod>
          <AllowedMethod>POST</AllowedMethod>
          <AllowedMethod>DELETE</AllowedMethod>
          <AllowedHeader>*</AllowedHeader>
          <MaxAgeSeconds>3000</MaxAgeSec>
          <ExposeHeader>ETag</ExposeHeader>
     </CORSRule>
     <CORSRule>
          <AllowedOrigin>*</AllowedOrigin>
          <AllowedMethod>GET</AllowedMethod>
          <AllowedHeader>*</AllowedHeader>
          <MaxAgeSeconds>3000</MaxAgeSeconds>
     </CORSRule>
</CORSConfiguration>

Example: DELETE bucket request

The following DELETE bucket request deletes a CORS subresource from a bucket (namespace) named finance.

NoteEach S3 compatible request must be authenticated by the S3 gateway. You do this by using the HTTP Authorization request header with either a signature string, an AWS Version 2 or Version 4 authentication string, or by anonymous access.
Request headers
DELETE /?cors HTTP/1.1
Host:finance.europe.hcp.example.com
Date: Tue, 14 May 2019 19:14:42 GMT
Authorization: SignatureString
Response headers
HTTP/1.1 204 No Content
Date: Tue, 14 May 2019 19:14:42 GMT
Server: HCP
Content-Length: 0

CORS request validation

After CORS rules are configured for an HCP namespace, web applications can request access to the namespace resources by using either the Hitachi API for Amazon S3 or the REST API.

The Amazon S3 and REST gateways perform CORS rules validation on incoming object requests against an HCP bucket. When a CORS compliant HCP server receives a bucket request from a browser, the server evaluates the request headers against the CORS rules configuration for the bucket. The first CORS rule for the bucket that matches the request is the rule that is applied for creating the server response headers.

For security reasons, requests that fail authentication are not validated. In the web browser, these failed authentication requests result in CORS errors.

Runtime request headers

Request headers are automatically set when a web browser issues an HTTP request to an HCP server.

The following list describes the runtime request headers sent by a browser depending on the request type (simple or preflight).

  • Origin

    Request type: Simple, Preflight

    Origin of the cross-domain request. For example, http://www.example.com

  • Access-Control-Request-Method

    Request type: Preflight

    HTTP method to be used when the request is made.

  • Access-Control-Request-Headers

    Request type: Preflight

    Headers used when the request is made. The format for the headers is a comma-separated list. If any of the headers are not contained in a CORS rule, the preflight request and CORS access to the server are denied, and the subsequent request is not issued.

Runtime response headers

In response to a CORS simple or preflighted request from the browser, the HCP server responds with the corresponding CORS headers.

The following list describes the CORS response headers.

  • Access-Control-Allow-Origin

    Request type: Simple, Preflight

    This response header indicates whether the response can be shared with the requesting code from the origin.

    If no applicable CORS rule is defined on the server, the Access-Control-Allow-Origin header is not defined in the response, which causes the browser to deny access to the resource.

    A '*' wildcard character by itself means that the resource is public and available to everyone. Using '*' as the value of this header with credentials will result in an error. For more information, see the Access-Control-Allow-Credentials response header description in this table.

  • Access-Control-Allow-Headers

    Request type: Preflight

    Returned by the server in response to a preflight request that includes the Access-Control-Request-Headers header to indicate which HTTP headers can be used during the actual request.

    Only returned for the OPTIONS request, not for the preflighted API call.

  • Access-Control-Allow-Methods

    Request type: Preflight

    Returned by the server in response to a preflight request to specify the HTTP method or methods allowed when the actual request is made.

    Only returned for the OPTIONS request, not for the preflighted API call.

  • Access-Control-Expose-Headers

    Request type: Simple, Preflight

    Optional

    Headers that browsers are allowed to access. By default, only six simple response headers are exposed:

    • cache-control
    • content-language
    • content-type
    • expires
    • last-modified
    • pragma

    Only returned for the OPTIONS request, not for the preflighted API call.

  • Access-Control-Max-Age: delta-seconds

    Request type: Preflight

    Optional

    Indicates how long the results of a preflight request can be cached in the browser.

  • Access-Control-Allow-Credentials: true

    Request type: Simple, Preflight

    Optional

    When used in a response to a preflight request, this header indicates whether the actual request can be made with credentials.

    For a simple request, if the header is true, the response is ignored by the browser and no content is returned to the web browser. This header works in conjunction with the credentials option (XHR or Fetch request).

    HCP returns the true value for this header unless the AllowedOrigin element in the CORS rules configuration is defined as "*"; in the latter case, the Access-Control-Allow-Credentials header is not returned.

    NoteA CORS compliant HCP server will not return the Access-Control-Allow-Credentials header when the wildcard character "*" is defined as Allow-Origin and the value of the Access-Control-Allow-Origin response header is "*".
  • Vary

    Request type: Simple, Preflight

    This response header determines how to match future request headers to determine whether a cached response can be used rather than requesting a new response from the server.

    If the HCP server sends a response with an Access-Control-Allow-Origin value that is an explicit origin (rather than the wildcard character "*"), the response should also include a Vary response header with the Origin value to indicate that server responses can differ based on the value of the Origin request header.

    The value of the Vary header is a comma separated list of header names that can change. For example:

    Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Example: Preflighted request

Here is an sample CORS preflighted request.

The preflighted request comprises two exchanges: an HTTP OPTIONS request (preflight request) from a web browser in one domain to a server in another domain to determine whether the actual request is safe to send, followed by the actual request.

Request headers (Preflight request)

OPTIONS rest/file.txt HTTP/1.1
Host: finance.europe.hcp.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36
Access-Control-Request-Headers: Authorization
Access-Control-Request-Method: GET
Origin: http://lgreen.example.com
Referer: http://lgreen.example.com/cors/rest.html

Response headers (Preflight request)

HTTP/1.1 200 OK
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Methods: GET, PUT, DELETE, POST, HEAD
Access-Control-Allow-Origin: *
Cache-Control: no-cache,no-store,must-revalidate
Content-Length: 0
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; connect-src 'self'; img-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'self'; frame-ancestors 'self';
Date: Tue, 07 May 2019 14:45:08 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Strict-Transport-Security: max-age=31536000; includeSubDomains
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block

In this example, the first exchange is complete. The server evaluated the preflight request against the CORS rules configuration for the resource, and responded that it is acceptable for the browser to send the actual request parameters: a GET request to a bucket named finance for an object named rest/file.txt.

Request headers (Actual request)

GET rest/file.txt HTTP/1.1
Host:finance.europe.hcp.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36
Origin:http://lgreen.example.com

Response headers (Actual request)

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://lgreen.example.com
Access-Control-Expose-Headers: ETag

Response body (Actual request)

[contents of the rest/file.txt object]

 

  • Was this article helpful?