为什么 GET 得到 "The request signature we calculated does not match the signature you provided." 而 OpenSearch 没有得到 PUT?

Why do I get "The request signature we calculated does not match the signature you provided." for GET but not PUT for OpenSearch?

我正在关注 this guide 使用 Node.js(适用于 JavaScript 的 AWS SDK 版本 3)签署对 Amazon OpenSearch 服务的 HTTP 请求。

当我复制确切的示例代码并导出我的授权用户的 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 时,添加项目的 PUT index/type/id 请求成功:

201 Created
Response body: {"_index":"products","_type":"_doc","_id":"2","_version":1,"result":"created","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":0,"_primary_term":1}

但是,当我将请求更改为 GET /_search 端点时,我得到:

403 Forbidden
Response body: {"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details."}

用户已完全授权索引:

    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::**:user/aws-elasticbeanstalk-ec2-user"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:ap-southeast-2:**:domain/mydomain/*"
    },

如何修改我的签名?

这是我从上面修改的代码 link:

const { HttpRequest } = require('@aws-sdk/protocol-http')
const { defaultProvider } = require('@aws-sdk/credential-provider-node')
const { SignatureV4 } = require('@aws-sdk/signature-v4')
const { NodeHttpHandler } = require('@aws-sdk/node-http-handler')
const { Sha256 } = require('@aws-crypto/sha256-browser')

const region = ''
const domain = ''
const index = 'products'
const type = '_search'
const createBody = (query) => ({
  query: {
    multi_match: {
      query,
      type: 'phrase',
      fields: [
        'tags',
        'name',
        'category',
        'maker'
      ]
    }
  },
  highlight: {
    pre_tags: [''],
    post_tags: [''],
    fields: {
      tags: {},
      name: {},
      category: {},
      maker: {}
    }
  }
})

searchIndex('sh').then(() => process.exit())

async function searchIndex (query) {
  const request = new HttpRequest({
    body: JSON.stringify(createBody(query)),
    headers: {
      'Content-Type': 'application/json',
      host: domain
    },
    hostname: domain,
    method: 'GET',
    path: index + '/' + type
  })

  const signer = new SignatureV4({
    credentials: defaultProvider(),
    region: region,
    service: 'es',
    sha256: Sha256
  })

  const signedRequest = await signer.sign(request)

  const client = new NodeHttpHandler()
  const { response } = await client.handle(signedRequest)
  console.log(response.statusCode + ' ' + response.body.statusMessage)

  let responseBody = ''
  return new Promise((resolve) => {
    response.body.on('data', (chunk) => {
      responseBody += chunk
    })
    response.body.on('end', () => {
      console.log('Response body: ' + responseBody)
      resolve(responseBody)
    })
  }, (error) => {
    console.log('Error: ' + error)
  })
}

我也有这个问题,使用相同的教程

阅读 docs on request body searches,我发现它说了以下内容:

Note The _search API accepts HTTP GET and POST for request body searches, but not all HTTP clients support adding a request body to a GET request. POST is the more universal choice.

将我的方法更改为 POST 解决了我的问题