Amazon 弹性搜索集群的正确访问策略

我最近开始使用新的 Amazon Elasticsearch Service,但是我似乎不知道我需要什么样的访问策略,所以我只能从我的 EC2实例中访问那些分配给它们特定 IAM 角色的服务。

下面是我目前为 ES 域分配的访问策略的一个例子:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::[ACCOUNT_ID]:role/my_es_role",
]
},
"Action": "es:*",
"Resource": "arn:aws:es:us-east-1:[ACCOUNT_ID]:domain/[ES_DOMAIN]/*"
}
]
}

但就像我说的,这样不行。我登录到 EC2实例(其中附加了 my_es_role角色) ,并尝试在“ https://*.es.amazonaws.com”端点上运行一个简单的 curl 调用,结果得到以下错误:

{“ Message”: “ User: 际没有授权执行: ES: ESHttpGet on resource: arn: aws: ES: us-east-1: [ ACCOUNT _ ID ] : domain/[ ES _ DOMAIN ]/“}

有人知道我要修改访问策略才能正常工作吗?

65512 次浏览

I'm also trying to do this, and I got it working using the Allow access to the domain from specific IP(s) option with the Elastic IP of my EC2 instance (could also work using the instance's private IP, but I'm not too sure)

According to AWS doc and as you (and I) just tested, you cannot restrict access to an AWS ES domain to a role/account/user/... and simply cURL it!

Standard clients, such as curl, cannot perform the request signing that is required of identity-based access policies. You must use an IP address-based access policy that allows anonymous access to successfully perform the instructions for this step. (http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg-search.html)

So you have basically two solutions:

Signing your request is probably the best solution if you want to keep your access policy as is (which is more flexible than restricting to an IP), but it seems to be a bit more complex. I haven't tried so far and I cannot find any doc to help.

You can lock access down to IAM-only, but how will you view Kibana in your browser? You could setup a proxy (see Gist and/or NPM module) or enable both IAM and IP-based access for viewing results.

I was able to get both IAM access IP-restricted access with the following Access Policy. Note the order is important: I could not get it working with the IP-based statement before the IAM statement.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxxxx:root"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-west-2:xxxxxxxxxxxx:domain/my-elasticsearch-domain/*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-west-2:xxxxxxxxxxxx:domain/my-elasticsearch-domain/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"192.168.1.0",
"192.168.1.1"
]
}
}
}
]
}

My EC2 instance has an instance profile with the arn:aws:iam::aws:policy/AmazonESFullAccess policy. Logstash should sign requests using the logstash-output-amazon-es output plugin. Logstash running on my EC2 instance includes an output section like this:

output {
amazon_es {
hosts => ["ELASTICSEARCH_HOST"]
region => "AWS_REGION"
}
# If you need to do some testing & debugging, uncomment this line:
# stdout { codec => rubydebug }
}

I can access Kibana from the two IPs in the access policy (192.168.1.0 and 192.168.1.1).

A bit late to the party, but I was able to deal with the exact same issue by adding signature to my requests.

If you use Python (like I do), you can use the following library to make it particularly easy to implement: https://github.com/DavidMuller/aws-requests-auth

It worked perfectly for me.

You may either use resource based policy or identity based policy rather than IP based policy which is like hard coding the IP address.

But you need to use Signature version 4 to sign the request

For Java implementation please refer http://mytechbites.blogspot.in/2017/04/secure-amazon-elastic-search-service.html

You just need to full user name in elastic search policy.

In this case, you can get your full user name from the error message itself. In my case: "arn:aws:sts::[ACCOUNT_ID]:assumed-role/[LAMBDA_POLICY_NAME]/[LAMBDA_NAME]"

    {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:sts::xxxxxxxxxxxx:assumed-role/[lambda-role]/[full-lambda-name]"
]
},
"Action": "es:*",
"Resource": "arn:aws:es:[region]:xxxxxxxxxxxxx:domain/[elasticsearch-domain-name]/*"
}
]


}

Role ARN needs to be changed. it will be looks like "arn:aws:iam::[ACCOUNT_ID]:role/service-role/my_es_role"