我已经设置了一个 AWS opensearch serverless 集合并有一个索引。
在我的 opensearch 无服务器中,我有以下数据访问策略:
[
{
"Rules": [
{
"Resource": [
"collection/*"
],
"Permission": [
"aoss:CreateCollectionItems",
"aoss:DeleteCollectionItems",
"aoss:UpdateCollectionItems",
"aoss:DescribeCollectionItems"
],
"ResourceType": "collection"
},
{
"Resource": [
"index/*/*"
],
"Permission": [
"aoss:*"
],
"ResourceType": "index"
}
],
"Principal": [
"arn:aws:iam::MY_ACCOUNT:role/my_lambda_role",
]
}
]
(出于测试目的,我已授予 my_lambda_role 对所有资源的完全访问权限,包括 aoss:APIAccessAll 等)
当我运行以下 lambda 函数时(使用 my_lambda_role 作为执行角色):
const AWS = require('aws-sdk');
exports.handler = async (event) => {
const endpoint = new AWS.Endpoint('1234abcd.us-east-1.aoss.amazonaws.com');
const region = 'us-east-1';
const index = 'cats_and_dogs';
// Create the HTTP request
const request = new AWS.HttpRequest(endpoint, region);
request.method = 'POST';
request.path = `/${index}/_search`;
request.headers['host'] = endpoint.host;
request.headers['Content-Type'] = 'application/json';
request.body = JSON.stringify({
query: {
match: {
description: "farm"
}
}
});
// Sign the request using AWS Signature Version 4
const signer = new AWS.Signers.V4(request, 'aoss');
signer.addAuthorization(AWS.config.credentials, new Date());
// Send the request using AWS HttpClient
return new Promise((resolve, reject) => {
const client = new AWS.HttpClient();
client.handleRequest(
request,
null,
(response) => {
let responseBody = '';
response.on('data', (chunk) => {
responseBody += chunk;
});
response.on('end', () => {
resolve({
statusCode: response.statusCode,
body: JSON.parse(responseBody),
});
});
},
(error) => {
console.error('Request error:', error);
reject({
statusCode: 500,
body: JSON.stringify({ error: 'Failed to execute search' }),
});
}
);
});
};
我收到 403 Forbidden:
{
"statusCode": 403,
"body": {
"status": 403,
"error": {
"reason": "403 Forbidden",
"type": "Forbidden"
}
}
}
问题是 AWS.Signers.V4() 没有添加 opensearch 无服务器所需的 'X-Amz-Content-Sha256' 标头,但似乎不是 opensearch 自我管理(我在使用时从不使用它)标准开放搜索自我管理):
解决方案:
// Sign the request using AWS Signature Version 4
const signer = new AWS.Signers.V4(request, 'aoss');
signer.addAuthorization(AWS.config.credentials, new Date());
request.headers['X-Amz-Content-Sha256'] = signer.hexEncodedHash(request.body);