Alexa Skills Kitに接続されたLambda関数のデータストレージにElasticsearchを使用しようとしています。 LambdaはElasticsearchなしでも問題なく動作しますが、ESは非常に必要なファジーマッチングを提供します。
Lambdaからアクセスできる唯一の方法は、Elasticsearchのグローバルアクセスを有効にすることですが、これは非常に悪い考えです。また、オープンアクセスポリシーまたはIPアドレスポリシーを使用して、コンピューターからアクセスすることもできました。 Lambda経由で読み取り専用アクセスを行い、IP経由で読み取り/書き込みを行う方法はありますか?
IAMでは、LambdaロールAmazonESReadOnlyAccessを付与しました。 ES側ではこれを試しましたが、IPアドレスでのみ機能しました:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::NUMBER:root",
"arn:aws:iam::NUMBER:role/lambda_basic_execution"
]
},
"Action": "es:*",
"Resource": "arn:aws:es:us-east-1:NUMBER:domain/NAME/*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-east-1:NUMBER:domain/NAME/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "MY IP"
}
}
}
]
}
この フォーラム投稿 は同じ質問をしますが、未回答になりました。
これを行うために知っている唯一の方法は、ESドメインでリソースベースのポリシーまたはIAMベースのポリシーを使用することです。これにより、特定のIAMユーザーまたはロールへのアクセスが制限されます。ただし、これを機能させるには、SigV4を使用してESへのリクエストに署名する必要もあります。
この署名を行うライブラリがあります。たとえば、 this one は、人気のあるPython他の言語。
これで、コードから elasticsearch.js で可能になりました。試す前に、 http-aws-es モジュールをインストールする必要があります。
const AWS = require('aws-sdk');
const httpAwsEs = require('http-aws-es');
const elasticsearch = require('elasticsearch');
const client = new elasticsearch.Client({
Host: 'YOUR_ES_Host',
connectionClass: httpAwsEs,
amazonES: {
region: 'YOUR_ES_REGION',
credentials: new AWS.EnvironmentCredentials('AWS')
}
});
// client.search({...})
Lambdaのアクセスポリシーにアクセスし、接続するAWS ARNを提供する必要があります
Elasticsearchクラスターへの外部(AWS外部)アクセスの場合、IPベースのアクセスポリシーを使用してクラスターを作成します。以下のようなもの:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"<<IP/CIDR>>"
]
}
},
"Resource": "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/*"
}
]
}
Lambda関数に対して、Lambda関数が以下のポリシースニペットで引き受けるロールを作成します。
{
"Sid": "",
"Effect": "Allow",
"Action": [
"es:DescribeElasticsearchDomain",
"es:DescribeElasticsearchDomains",
"es:DescribeElasticsearchDomainConfig",
"es:ESHttpPost",
"es:ESHttpPut"
],
"Resource": [
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>",
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/*"
]
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"es:ESHttpGet"
],
"Resource": [
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_all/_settings",
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_cluster/stats",
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/<<INDEX>>*/_mapping/<<TYPE>>",
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_nodes",
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_nodes/stats",
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_nodes/*/stats",
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_stats",
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/<<INDEX>>*/_stats"
]
}
上記の2つのポリシーステートメントをより簡単に次のように要約できると思います。
{
"Sid": "",
"Effect": "Allow",
"Action": [
"es:DescribeElasticsearchDomain",
"es:DescribeElasticsearchDomains",
"es:DescribeElasticsearchDomainConfig",
"es:ESHttpPost",
"es:ESHttpGet",
"es:ESHttpPut"
],
"Resource": [
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>",
"arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/*"
]
}
私は次のソースから上記をつなぎ合わせることができました。
AWS LambdaはパブリックEC2インスタンスで実行されます。したがって、IPアドレスのホワイトリストをElasticsearchアクセスポリシーに追加するだけでは機能しません。これを行う1つの方法は、Lambda実行ロールにElasticsearchドメインへの適切なアクセス許可を付与することです。 Lambda ExecutionロールにESドメインへのアクセス許可があり、ESドメインアクセスポリシーに、このLambda Role ARNが適切なアクションを実行できるステートメントがあることを確認してください。これが完了したら、ESエンドポイントにアクセスしながら、SigV4を介してリクエストに署名するだけで済みます。
お役に立てば幸いです!