ゲームソリューション部の えがわ です。
LambdaからOpenSearch Serverlessへのアクセスに少し詰まってしまったので、備忘録として残しておきます。
最初に結論
以下の設定を行っていませんでした。
- Lambdaの実行ロールにOpenSearch Serverlessの権限を追加
- OpenSearch ServerlessのデータアクセスコントロールにLambdaの実行ロールを指定
事前準備
OpenSearch Serverlessのコレクションは作成済みとします。
今回はベクトル検索で試しています。
やったこと
OpenSearch Serverlessのインデックスを作成する処理を実行してみます。
エンドポイントやリージョン、インデックス名は適宜修正してください。
from opensearchpy import OpenSearch, RequestsHttpConnection, AWSV4SignerAuth
import boto3
def lambda_handler(event, context):
host = 'endpoint' #without https://
region = 'us-east-1'
service = 'aoss'
credentials = boto3.Session().get_credentials()
auth = AWSV4SignerAuth(credentials, region, service)
client = OpenSearch(
hosts=[{'host': host, 'port': 443}],
http_auth=auth,
use_ssl=True,
verify_certs=True,
connection_class=RequestsHttpConnection
)
index_name = 'index-name'
client.indices.create(index_name,
body={
"settings":{
"index.knn": True
},
"mappings":{
"properties": {
"values": {
"type": "knn_vector",
"dimension": 1024
},
"title": {
"type": "text"
}
}
}
}
)
AWS SDK for Pandas
のレイヤー追加しておくとopensearch-py
も使用できます。
Lambdaをそのまま実行してみると以下のエラーが発生します。
{
"errorMessage": "AuthorizationException(403, 'Forbidden')",
"errorType": "AuthorizationException",
"requestId": "fe4c4987-3ab5-4264-b317-b06249d1c11b",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 22, in lambda_handler\n client.indices.create(index_name,\n",
" File \"/opt/python/opensearchpy/client/utils.py\", line 180, in _wrapped\n return func(*args, params=params, headers=headers, **kwargs)\n",
" File \"/opt/python/opensearchpy/client/indices.py\", line 164, in create\n return self.transport.perform_request(\n",
" File \"/opt/python/opensearchpy/transport.py\", line 447, in perform_request\n raise e\n",
" File \"/opt/python/opensearchpy/transport.py\", line 408, in perform_request\n status, headers_response, data = connection.perform_request(\n",
" File \"/opt/python/opensearchpy/connection/http_requests.py\", line 231, in perform_request\n self._raise_error(\n",
" File \"/opt/python/opensearchpy/connection/base.py\", line 315, in _raise_error\n raise HTTP_EXCEPTIONS.get(status_code, TransportError)(\n"
]
}
ははーん、このエラーはLambdaの実行ロールのポリシーですね!?
ということで、実行ロールにポリシーを追加します。
↓のポリシー追加は後に分かりますが間違った手順です。
実行ロールを選択し
OpenSearchServiceのポリシーを追加します。
とりあえず困ったときのFullAccessを追加しています。
再度Lambdaを実行します。
{
"errorMessage": "AuthorizationException(403, 'Forbidden')",
"errorType": "AuthorizationException",
"requestId": "a3bb8f14-5e71-49d1-9f67-f9e341a97393",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 22, in lambda_handler\n client.indices.create(index_name,\n",
" File \"/opt/python/opensearchpy/client/utils.py\", line 180, in _wrapped\n return func(*args, params=params, headers=headers, **kwargs)\n",
" File \"/opt/python/opensearchpy/client/indices.py\", line 164, in create\n return self.transport.perform_request(\n",
" File \"/opt/python/opensearchpy/transport.py\", line 447, in perform_request\n raise e\n",
" File \"/opt/python/opensearchpy/transport.py\", line 408, in perform_request\n status, headers_response, data = connection.perform_request(\n",
" File \"/opt/python/opensearchpy/connection/http_requests.py\", line 231, in perform_request\n self._raise_error(\n",
" File \"/opt/python/opensearchpy/connection/base.py\", line 315, in _raise_error\n raise HTTP_EXCEPTIONS.get(status_code, TransportError)(\n"
]
}
なにも変わらない...
先ほど追加したポリシーを確認すると"es"
のFullAccessを付与していますが、今回はServerlessなので"aoss"
の付与を行う必要がありそうです。
AWSは提供してなさそうにみえるので、インラインポリシーを作成
からポリシーを作成していきます。
OpenSearch Serverlessのポリシーを検索し、またまた困ったときのFullAccessを追加してみます。
再度Lambdaを実行します。
{
"errorMessage": "AuthorizationException(403, 'security_exception', 'OpenSearch exception [type=authorization_exception, reason=User does not have permissions for the requested resource]')",
"errorType": "AuthorizationException",
"requestId": "be8f0954-a261-4b0b-acbd-704863c54860",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 22, in lambda_handler\n client.indices.create(index_name,\n",
" File \"/opt/python/opensearchpy/client/utils.py\", line 180, in _wrapped\n return func(*args, params=params, headers=headers, **kwargs)\n",
" File \"/opt/python/opensearchpy/client/indices.py\", line 164, in create\n return self.transport.perform_request(\n",
" File \"/opt/python/opensearchpy/transport.py\", line 447, in perform_request\n raise e\n",
" File \"/opt/python/opensearchpy/transport.py\", line 408, in perform_request\n status, headers_response, data = connection.perform_request(\n",
" File \"/opt/python/opensearchpy/connection/http_requests.py\", line 231, in perform_request\n self._raise_error(\n",
" File \"/opt/python/opensearchpy/connection/base.py\", line 315, in _raise_error\n raise HTTP_EXCEPTIONS.get(status_code, TransportError)(\n"
]
}
403は継続して発生していますが、エラーは変わりました!
OpenSearch Serverlessへ近づいているように見えます!
コレクションの権限周りに問題がありそうなので、マネジメントコンソールを眺めてみます。
セキュリティのデータアクセスポリシーが怪しそうな気がするので、ポリシーを確認してみます。
選択されたプリンシパル
にコレクションを作成したロールが設定されています。
ここにLambdaの実行ロールを設定すればうまく動きそうな予感がしています。
再度Lambdaを実行します。
成功しました!
インデックスも追加されています。
最後に
今回、AWS LambdaからAmazon OpenSearch Serverlessへアクセスする際の困った内容について記載しました。
この記事がどなたかの参考になれば幸いです。