elasticsearch,aws-sdk,aws-lambda,Node.js,Amazon Web Services,elasticsearch,Aws Sdk,Aws Lambda" /> elasticsearch,aws-sdk,aws-lambda,Node.js,Amazon Web Services,elasticsearch,Aws Sdk,Aws Lambda" />

Node.js 通过http对aws资源的请求进行正确签名

Node.js 通过http对aws资源的请求进行正确签名,node.js,amazon-web-services,elasticsearch,aws-sdk,aws-lambda,Node.js,Amazon Web Services,elasticsearch,Aws Sdk,Aws Lambda,我有一个lambda函数,它将一些数据写入我也通过AWS设置的Elasticsearch域。目前,我的域上的访问策略只是允许我自己的IP地址与域一起工作 {"Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"AWS": "*"}, "Action": "es:*", "Resource": "arn:aws:es:us-east-1:$ACCOUNT:domain/DOMAIN/*", "C

我有一个lambda函数,它将一些数据写入我也通过AWS设置的Elasticsearch域。目前,我的域上的访问策略只是允许我自己的IP地址与域一起工作

{"Version": "2012-10-17", "Statement": [{
 "Effect": "Allow", "Principal": {"AWS": "*"},
 "Action": "es:*",
 "Resource": "arn:aws:es:us-east-1:$ACCOUNT:domain/DOMAIN/*",
 "Condition": { "IpAddress": { "aws:SourceIp": $MYIP } }
}]}
我找到了对http请求进行签名的方法。我是这样使用它的:

axios(aws4.sign({
    host: process.env.ES_ENDPOINT,
    method: "post",
    url: `https://${process.env.ES_ENDPOINT}/foobot/foobot`,
    data,
}))
在没有aws4.sign的情况下,这实际上是可行的,因为我已经完全打开了ES域,但是现在我已经应用了上面的IP地址策略

现在,我不断收到这样的错误响应:

我们计算的请求签名与您提供的签名不匹配。检查您的AWS秘密访问密钥和签名方法。有关详细信息,请参阅维修文档


我还需要做些什么来正确签署请求?

这实际上与两个库有关,
axios
aws4
aws4
将基于正常NodeJS
http
请求进行注销,并且在具有主体的POST请求中,主体需要正确地对请求进行签名

只需传入
body
path

axios(aws4.sign({
    host: process.env.ES_ENDPOINT,
    method: "POST",
    url: `https://${process.env.ES_ENDPOINT}/foobot/foobot`,
    data,
    body: JSON.stringify(data),
    path: "/foobot/foobot",
}))

是的,我使用了相同的示例,它成功运行。但每次它返回不同的签名。即使是相同的值

axios(aws4.sign({
    host: process.env.ES_ENDPOINT,
    method: "POST",
    url: `https://${process.env.ES_ENDPOINT}/foobot/foobot`,
    data,
    body: JSON.stringify(data),
    path: "/foobot/foobot",
}))

上面的回答有助于将所有这些都带到我的解决方案中,以便将WS消息从lambda发布到API网关中的Websocket API

这样做的原因是为了避免使用aws sdk,后者在第一次运行(预热)时至少会再增加约2500毫秒

这是我的代码,希望它能帮助其他人:

const data = {'success': true};
const request = {
    host: process.env.AWS_API_GATEWAY_ENDPOINT,
    method: 'POST',
    url: `https://${process.env.AWS_API_GATEWAY_ENDPOINT}/wss/@connections/${connectionId}`, // this is for axios
    path: `/wss/@connections/${connectionId}`,
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(data),
    data, // this is needed for axios
}

const signedRequest = aws4.sign(request,
    {
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
        accessKeyId: process.env.AWS_ACCESS_KEY_ID,
        sessionToken: process.env.AWS_SESSION_TOKEN // needed when sending from a lambda
    });

    delete signedRequest.headers['Host']; // delete Host to not potentially mess with axios
    const response = await axios(signedRequest);

您能告诉我如何发送已签名的GET请求吗?我是这样做的,但得到了相同的错误“我们计算的请求签名与您提供的签名不匹配。请检查您的AWS秘密访问密钥和签名方法。有关详细信息,请参阅服务文档。”这是我的代码:axios(aws4.sign({host:env('ES_URI'),方法:“GET”,url:
${url}
,查询:JSON.stringify(查询),路径:
/${ES_INDEX}
})<代码>路径需要包含查询字符串。当我使用此url时,我面临一个非常愚蠢的问题:我没有得到错误:403,但当我使用此url时:它给了我403错误。你能帮我一下吗?你的请求中仍然有
数据
是打字错误吗?看起来像是无效的对象notation@MatthewWoo这是速记属性语法。它相当于
data:data
,这不是因为它也用时间戳签名。所以根据时间的不同。。。