All Products
Search
Document Center

OpenSearch:Signature method of OpenSearch API V3

Last Updated:Mar 08, 2023

OpenSearch authenticates each access request. The service implements symmetric encryption based on AccessKey pairs to verify the identity of users. Each AccessKey pair consists of an AccessKey ID and an AccessKey secret.

AccessKey IDs and AccessKey secrets are officially issued by Alibaba Cloud to users. You can request and manage an AccessKey pair on the Alibaba Cloud International site (alibabacloud.com). The AccessKey ID is used to verify the user identity.

The AccessKey secret is used to encrypt a signature string and verify the signature string on the server. You must keep your AccessKey secret strictly confidential.

Supported applications

  • Advanced applications

  • Standard applications

Protocols

OpenSearch API V3 supports only the HTTP protocol.

Request methods

  • You must send HTTP GET requests to search for data.

  • You must send HTTP POST requests to push data.

Calculate the value of the Authorization header

You must add a signature string to the Authorization header in an HTTP request. This indicates that the request is authenticated. The HTTP request must also contain other required headers. The "Examples" section in this topic provides an example of the headers.

All request headers, such as Content-Md5, Content-Type, Date, and OpenSearch-specific HTTP headers, must be used for signature calculation. A space must be added after OPENSEARCH in "Authorization:OPENSEARCH " in the following string-to-sign:

"Authorization: OPENSEARCH " + AccessKeyId + ":" + Signature
Signature = base64(hmac-sha1(AccessKeySecret,
            VERB + "\n"
            + Content-Md5 + "\n"
            + Content-Type + "\n"
            + Date + "\n"
            + CanonicalizedOpenSearchHeaders
            + CanonicalizedResource))

Calculate the HMAC value of the string-to-sign as defined in RFC 2104

  • The HMAC-SHA1 method defined in RFC 2104 is used to calculate the signature string.

  • A signature string must be encoded in UTF-8.

  • A signature string that contains Chinese characters must be first encoded in UTF-8. The encoded signature string is used together with the AccessKeySecret parameter to calculate the final signature string.

  • Parameters that are used to calculate the signature string must be sorted in the same way as those in the preceding sample code.

Parameter

Description

AccessKeyId

Required. The AccessKey ID of the user who sends the request. This parameter must be specified for the Authorization header.

AccessKeySecret

Required. The AccessKey secret of the user who sends the request. The AccessKey secret is used to encrypt and verify the signature string.

VERB

Required. The request method. Supported methods for HTTP requests include PUT, GET, POST, HEAD, and DELETE. Different request methods are required by different API operations.

\n

The line feed.

Content-MD5

The MD5 value of the HTTP request body. This parameter is required if the request has a body. This parameter is used to check whether the content of the request received is the same as that of the request sent. This ensures the validity of the request. Example: 4991ef0788236a8f280fed0db928e74e.

For requests that do not have a body, such as requests to search for data, do not specify this parameter. For more information, see RFC 2616 Content-MD5.

Content-Type

Example: application/json.

Date

Required. The time when the request is sent. Specify the time in the ISO 8601 standard in the YYYY-MM-DDThh:mm:ssZ format. The time must be in UTC. Example: 2019-02-25T10:09:57Z. If the interval between the time when the request is sent and the time when the OpenSearch server receives the request exceeds 15 minutes, the server rejects the request and returns the HTTP error code 403.

CanonicalizedOpenSearchHeaders

Required. The OpenSearch-specific HTTP headers that are used to distinguish between requests. All HTTP request headers that are prefixed with X-Opensearch-, such as X-Opensearch-Nonce, are OpenSearch-specific HTTP headers. During signature calculation, the names of these headers must be in lowercase, such as x-opensearch-nonce. If these headers are used as request headers, specify the header names in the original format. If these headers are not used as request headers, they are not used for signature calculation. In this case, delete the CanonicalizedOpenSearchHeaders parameter from the string-to-sign.

CanonicalizedResource

Required. The path of the request. Example: /v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson.

Requests to search for data

Request signature parameter

Required

Request header

Required

AccessKeySecret

Yes

Date

Yes

VERB

Yes

X-Opensearch-Nonce

Yes

Date

Yes

Authorization

Yes

x-opensearch-nonce

Yes

canonicalized_resource

Yes

  • The values of the request headers must be the same as those specified for signature calculation.

  • We recommend that you add the Content-Md5, Content-Type, Date, CanonicalizedOpenSearchHeaders, and Authorization parameters as request headers. If you specify only the required request headers, an error may occur.

  • All request headers must be used for signature calculation.

Requests to push data

Request signature parameter

Required

Request header

Required

AccessKeySecret

Yes

Content-MD5

Yes

VERB

Yes

Date

Yes

Content-MD5

Yes

Authorization

Yes

Date

Yes

canonicalized_resource

Yes

  • The values of the request headers must be the same as those specified for signature calculation.

  • We recommend that you add the Content-Md5, Content-Type, Date, CanonicalizedOpenSearchHeaders, and Authorization parameters as request headers. If you specify only the required request headers, an error may occur.

  • All request headers must be used for signature calculation.

Construct a CanonicalizedOpenSearchHeaders string

The CanonicalizedOpenSearchHeaders parameter contains all OpenSearch-specific HTTP headers that are prefixed with X-Opensearch-. Other HTTP headers are not involved in this section.

  1. Specify the values of the OpenSearch-specific HTTP headers that are prefixed with X-Opensearch-. For example, a complete HTTP header is X-Opensearch-Nonce : 1551089397451704. The value of the header, such as 1551089397451704, consists of a 10-digit timestamp and a 6-digit random value that ranges from 100000 to 999999. Then, omit all the OpenSearch-specific HTTP headers whose values are empty.

  2. Sort all the remaining OpenSearch-specific HTTP headers in alphabetical order.

  3. Convert the uppercase letters in the names of the sorted HTTP headers into lowercase letters. For example, convert X-Opensearch-Nonce : 1551089397451704 into x-opensearch-nonce : 1551089397451704.

  4. Delete all spaces on each side of the delimiter between each header and its value. For example, an original HTTP header is x-opensearch-nonce : 1551089397451704. After spaces are deleted, the HTTP header becomes x-opensearch-nonce:1551089397451704.

  5. Regard each header-value pair as an item. Connect all the items with the \n delimiter to form the final CanonicalizedOpenSearchHeaders string. The \n delimiter must also be added to the last item.

Note

  1. An HTTP request to search for data may not contain OpenSearch-specific HTTP headers. These headers are not used for signature calculation. In this case, the "\n" delimiter is not required and you do not need to construct a CanonicalizedOpenSearchHeaders string. Delete the CanonicalizedOpenSearchHeaders parameter from the string-to-sign.

  2. When you add OpenSearch-specific HTTP headers to the headers of a request, do not specify the header names in the converted format that consists of lowercase letters. You must use the original format.

Construct a CanonicalizedResource string

  • A signature string must be encoded in UTF-8. A signature string that contains Chinese characters must be first encoded in UTF-8. The encoded signature string is used together with the AccessKeySecret parameter to calculate the final signature string.

  • The CanonicalizedResource string for requests to search for data is in the following format: path + ? + query.

  • The CanonicalizedResource string for requests to push data is in the following format: path.

Construct a path string

To construct a path string, encode the original string, replace %2F with a forward slash (/), and then replace app_schema_demo with the name of your application. The following list shows four common path strings:

  • Path string for requests to search for data: /v3/openapi/apps/app_schema_demo/search.

  • Path string for requests to search for data based on suggestions: /v3/openapi/suggestions/suggestion_name/actions/search.

  • Path string for requests to search for data by using an application: /v3/openapi/apps/appid. In this case, you must replace appid with the ID of your application that is used for searches and specify the Authorization header for authentication. You do not need to specify request parameters.

  • Path string for requests to push data: /v3/openapi/apps/app_schema_demo/tab/actions/bulk. In this case, you must replace tab with the name of the table that is used to receive data in your application.

Construct a query string

A query string consists of request parameters. The parameters are specified in the form of key-value pairs. To construct a query string for a CanonicalizedResource string, perform the following steps:

  1. Assign a value to each request parameter to be used and omit the request parameters whose values are empty. Request parameters that have empty values are not used for signature calculation.

  2. Sort the request parameters in alphabetical order first by key and then by value.

  3. Encode the keys and values of the request parameters based on the RFC 3986 standard. Then, use an equal sign (=) to concatenate the key and value of each encoded request parameter.

  4. Use an ampersand (&) to concatenate the encoded request parameters and save the value as the query string.

  5. Use the path string and query string to form the final CanonicalizedResource string in the format of path + ? + query. Sample CanonicalizedResource string: /v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson.

    • The sample CanonicalizedResource string contains the following request parameter and its value:

      • fetch_fields=name

    • The sample CanonicalizedResource string contains the following query parameter and clauses. The first part indicates the query parameter and the second part indicates the query clause and other relevant clauses.

      • query=query=name:'document'&&sort=id&&config=format:fulljson

Note

Before you encode a string for the query parameter, you must concatenate the clauses with double ampersands (&&). If you want to send a request to push data, you need to only use the path string as the CanonicalizedResource string.

Construct the Authorization header

For information about how to construct the Authorization header, see the "Calculate the value of the Authorization header" section in this topic. For example, the AccessKey ID of the user is LTAItQcybixt**** and the signature string is 1P7tfEh+CU5kFYRXzZ14kkJU****. The following sample Python 3 code constructs the Authorization header:

headers['Authorization'] = 'OPENSEARCH ' + 'LTAIt****xt****' + ':' + '1P7tf*******4kkJU****'

Examples

For example, the headers and parameters of a request and the request method are configured in the following way:

  • Authorization: OPENSEARCH LTAItQ****R9A0:1P7tfEh+CU******14kkJ****.

  • AccessKeySecret: R0OGKs*******khMqHXBfKG.

  • Request method: GET.

  • Content-MD5: This parameter is left empty because the sample request is used to search for data.

  • Content-Type: application/json.

  • Date: 2019-02-25T10:09:57Z.

  • CanonicalizedOpenSearchHeaders: x-opensearch-nonce:15510****1704.

  • CanonicalizedResource: /v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson.

Request header

Calculation formula of the signature string

Signature string

'Content-MD5': '','Content-Type': 'application/json','Authorization': 'OPENSEARCH LTA****tR9A0:1P7tfEh+CU****RXzZ14kkJUAMc=','X-Opensearch-Nonce': '1551089397451704','Date': '2019-02-25T10:09:57Z'

Signature = base64(hmac-sha1(AccessKeySecret,VERB + "\n"+ Content-Md5 + "\n"+ Content-Type + "\n"+ Date + "\n"+ CanonicalizedOpenSearchHeaders+ CanonicalizedResource))

1P7tfEh+CU5k******4kkJUAMc= ,GET\n\napplication/json\n2019-02-25T10:09:57Z\nx-opensearch-nonce:1551089397451704\n/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson

Note

The values of the request headers must be the same as those specified for signature calculation.

Calculation example of the signature string

  • In this example, an HMAC value and the Base64 encoding format are used to calculate the signature string.

Sample Python 3 code:

import hmac
import base64
signature_string = '\n'.join(['GET',
                              '',
                              'application/json',
                              '2019-02-25T10:09:57Z',
                              'x-opensearch-nonce:1551089397451704',
                              '/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson'])
signature_hmac = hmac.new('R0OGKsMj******khMqHXBfKG'.encode('utf-8'), signature_string.encode('utf-8'), 'sha1')
signature = base64.b64encode(signature_hmac.digest())

For example, the AccessKey secret of the user is R0OGKsMj0*********HXBfKG. The final signature string that is calculated by using the preceding calculation method is 1P7tfEh+CU5*******kkJUAMc=.

Construct a request string

A request string is in the following format: host + CanonicalizedResource string.

You must add a signature string to the Authorization header in an HTTP request. This indicates that the request is authenticated. The HTTP request must also contain other required headers that are described in the preceding sections. In a request string, host specifies the endpoint of OpenSearch API.

  • Request string for requests to search for data: http://host/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=query%3Dname%3A%27%E6%96%87%E6%A1%A3%27%26%26sort%3Did%26%26config%3Dformat%3Afulljson.

  • Request string for requests to search for data based on suggestions: http://host/v3/openapi/apps/{appName}/suggest/{suggestName}/search?hits=10&query=%E6%A0%87%E9%A2%98.

  • Request string for requests to search for data by using an application: http://host/v3/openapi/apps/120001234. In this case, you must replace appid with the ID of your application, such as 120001234, which is used for searches, and specify the Authorization header for authentication. You do not need to specify request parameters.

  • Request string for requests to push data: http://host/v3/openapi/apps/app_schema_demo/tab/actions/bulk. The data to be pushed must be specified in the request body.

Note

  • OpenSearch provides the SDK for Java, SDK for PHP, SDK for Python, and SDK for C# based on OpenSearch API V3. The SDK for PHP, SDK for Python, and SDK for C# have implemented the methods of OpenSearch API V3 to calculate signatures. You can directly use these methods. You can also refer to the source code for signature calculation in the SDK for PHP, SDK for Python, and SDK for C# to implement SDKs in other languages.

  • OpenSearch does not maintain the SDKs that are implemented based on this topic and the source code of official SDKs. Users should maintain these SDKs by themselves.

Application schema template

{
  "name": "app_schema_demo",
  "type": "standard",
  "schema": {
    "indexes": {
      "search_fields": {
        "id": {
          "fields": [
            "id"
          ]
        },
        "name": {
          "fields": [
            "name"
          ],
          "analyzer": "chn_standard"
        },
        "phone": {
          "fields": [
            "phone"
          ],
          "analyzer": "fuzzy"
        },
        "int_arr": {
          "fields": [
            "int_arr"
          ]
        },
        "literal_arr": {
          "fields": [
            "literal_arr"
          ]
        },
        "cate_id": {
          "fields": [
            "cate_id"
          ]
        }
      },
      "filter_fields": [
        "id",
        "int_arr",
        "literal_arr",
        "float_arr",
        "cate_id"
      ]
    },
    "tables": {
      "tab": {
        "name": "tab",
        "fields": {
          "id": {
            "name": "id",
            "type": "INT",
            "primary_key": true
          },
          "name": {
            "name": "name",
            "type": "TEXT",
            "primary_key": false
          },
          "phone": {
            "name": "phone",
            "type": "SHORT_TEXT",
            "primary_key": false
          },
          "int_arr": {
            "name": "int_arr",
            "type": "INT_ARRAY",
            "primary_key": false
          },
          "literal_arr": {
            "name": "literal_arr",
            "type": "LITERAL_ARRAY",
            "primary_key": false
          },
          "float_arr": {
            "name": "float_arr",
            "type": "FLOAT_ARRAY",
            "primary_key": false
          },
          "cate_id": {
            "name": "cate_id",
            "type": "INT",
            "primary_key": false
          }
        },
        "primary_table": true
      }
    },
    "route_field": null
  },
  "data_sources": [],
  "first_ranks": {},
  "second_ranks": {},
  "summary": [],
  "fetch_fields": [
    "id",
    "name",
    "phone",
    "int_arr",
    "literal_arr",
    "float_arr",
    "cate_id"
  ],
  "quota": {
    "qps": 6,
    "doc_size": 0.3
  }
}