Разрешения на доступ к ElasticSearch из Lambda?
Я пытаюсь использовать Elasticsearch для хранения данных для лямбда-функции, подключенной к Alexa Skills Kit. Лямбда работает хорошо без Elasticsearch, но ES обеспечивает столь необходимое нечеткое соответствие.
Единственный способ получить доступ к нему через Lambda - это включить глобальный доступ Elasticsearch, но это действительно плохая идея. Я также смог получить доступ со своего компьютера через политику открытого доступа или политику IP-адресов. Есть ли способ сделать доступ только для чтения через Lambda и чтения-записи через IP?
На IAM я предоставил свою лямбда-роль 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"
}
}
}
]
}
Этот пост форума задает тот же вопрос, но остался без ответа.
4 ответа
Единственный известный мне способ сделать это - использовать политику на основе ресурсов или политику на основе IAM в вашем домене ES. Это ограничит доступ к определенному пользователю или роли IAM. Однако, чтобы это работало, вам также необходимо подписать свои запросы к ES с помощью SigV4.
Существуют библиотеки, которые будут выполнять эту подпись для вас, например, эта расширяет популярную библиотеку запросов Python для подписи запросов ElasticSearch через SigV4. Я считаю, что подобные библиотеки существуют для других языков.
Теперь это возможно из вашего кода с asticsearch.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({...})
Конечно, прежде чем использовать его, настройте доступ к домену asticsearch:
Для внешнего (вне AWS) доступа к вашему кластеру Elasticsearch вы хотите создать кластер с политикой доступа на основе 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"
]
}
Я думаю, что вы могли бы с лёгкостью сжать два приведенных выше политических заявления в следующее:
{
"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>>/*"
]
}
Мне удалось собрать все вышеперечисленное из следующих источников:
Вам нужно перейти к политике доступа Lambda и предоставить AWS ARN для подключения
http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-aws-integrations.html
AWS Lambda работает на общедоступных экземплярах EC2. Поэтому простое добавление белого списка IP-адресов в политику доступа Elasticsearch не будет работать. Один из способов сделать это - дать роли выполнения Lambda соответствующие разрешения для домена Elasticsearch. Убедитесь, что роль Lambda Execution имеет разрешения для домена ES, а политика доступа к домену ES имеет оператор, который позволяет этому ARN лямбда-роли выполнять соответствующие действия. Как только это будет сделано, все, что вам нужно сделать, это подписать ваш запрос через SigV4 при доступе к конечной точке ES
Надеюсь, это поможет!