为什么会提示“我们计算的请求签名与您提供的签名不匹配”。对于 GET 但不是 PUT 对于 OpenSearch?

我正在关注 this guide 使用 Node.js(适用于 JavaScript 的 AWS 开发工具包的第 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/*"
    },

如何更正我的签名?

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

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)
  })
}
stack overflow Why do I get "The request signature we calculated does not match the signature you provided." for GET but not PUT for OpenSearch?
原文答案
author avatar

接受的答案

我也使用了同一教程

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

请注意,_search API接受HTTP GET并发布请求的主体搜索,但并非所有HTTP客户端都支持将请求主体添加到GET请求中。帖子是更普遍的选择。

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


答案:

相关问题