我有一个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 } }
}]}
我找到了aws4
library来签署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 Secret Access Key和签名方法。有关详细信息,请参阅服务文档。
我需要做些什么来正确签署请求吗?
答案 0 :(得分:2)
这实际上与两个库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",
}))
答案 1 :(得分:0)
是的,我使用相同的示例,它成功运行。但是每次它返回不同的签名。即使是相同的值。
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",
}))
答案 2 :(得分:0)
上述答案有助于将其全部引入我的解决方案,以便将 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);