Amazon Elasticsearch 集群的正确访问策略

Posted

技术标签:

【中文标题】Amazon Elasticsearch 集群的正确访问策略【英文标题】:Proper access policy for Amazon Elastic Search Cluster 【发布时间】:2016-01-03 20:19:00 【问题描述】:

我最近开始使用新的 Amazon Elasticsearch Service,但我似乎无法弄清楚我需要的访问策略,因此我只能从分配了特定 IAM 角色的 EC2 实例访问这些服务。

这是我目前为 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":"用户:anonymous 无权执行:es:ESHttpGet on resource:arn:aws:es:us-east-1:[ACCOUNT_ID]:domain/[ES_DOMAIN]/“

有谁知道我必须在访问策略中进行哪些更改才能使其正常工作?

【问题讨论】:

请注意,ElasticSearch 访问策略更改需要很长时间才能应用,这与其他几乎是即时的 IAM 更改不同。只需单击“应用”并切换选项卡即可很容易,而不会注意到“正在处理...” 【参考方案1】:

您可以将访问权限锁定为仅限 IAM,但您将如何在浏览器中查看 Kibana?您可以setup a proxy(see Gist 和/或NPM module)或同时启用 IAM 和基于 IP 的访问以查看结果。

我能够通过以下访问策略获得 IAM 访问 IP 限制访问。请注意顺序很重要:我无法在 IAM 语句之前使用基于 IP 的语句。


  "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"
          ]
        
      
    
  ]

我的 EC2 实例有一个实例配置文件,其中包含 arn:aws:iam::aws:policy/AmazonESFullAccess 政策。 Logstash 应该使用logstash-output-amazon-es output plugin 对请求进行签名。在我的 EC2 实例上运行的 Logstash 包含如下输出部分:

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

我可以从访问策略中的两个 IP(192.168.1.0 和 192.168.1.1)访问 Kibana。

【讨论】:

您好,只有在使用基于 IAM 的策略时才需要使用插件。如果您的访问策略基于 IP 地址,您可以在 Logstash 中使用标准的 elasticsearch 插件。在这种情况下,您也不需要实例配置文件。此外,ES 服务在 VPC 中不可用。您必须使用公共 IP 地址进行连接。不确定您对 192.168 地址的引用是否是对其他内容的替代,但可能会产生误导。 在我的示例中,aws:SourceIp 旨在作为您的个人工作站 IP,以便您可以使用 Kibana。 IAM 限制访问使一个或多个 EC2 实例能够写入 Elasticsearch,而无需担心哪些 IP 属于特定实例或 CIDR 块。 值得注意的是,限制您的 VPC 的 private IP CIDR 范围似乎不起作用。 ES 不在 VPC 内运行。 感谢您在回答中提供示例政策;在我将 aws:SourceIp 从标量值切换到数组之前,我一直无法让 Kibana 摆脱可怕的“用户:匿名”错误,如您给出的示例所示。 (我是 CIDR 表示法,如果这对其他人有帮助的话。)如果每一次策略更改都没有使集群进入神秘的“处理”状态 20 分钟,那么为 AWS ES 设置策略的整个过程就不会那么令人沮丧了。该政策被仔细地铭刻在石碑上,或者他们正在做的任何事情上。【参考方案2】:

根据 AWS 文档,正如您(和我)刚刚测试的那样,您不能将对 AWS ES 域的访问限制为角色/帐户/用户/...,而只是 cURL !

标准客户端(例如 curl)无法执行基于身份的访问策略所需的请求签名。您必须使用允许匿名访问的基于 IP 地址的访问策略才能成功执行此步骤的说明。 (http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg-search.html)

所以你基本上有两种解决方案:

更改您的访问策略并将其限制为 IP,我认为您不能使用私有 IP,因为您的 ES 集群似乎不属于您的 VPC(无论是否默认)。请使用公网IP 签署您的请求:http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-managedomains.html#es-managedomains-signing-service-requests

如果您想保持访问策略不变(这比限制 IP 更灵活),签署您的请求可能是最好的解决方案,但它似乎有点复杂。到目前为止我还没有尝试过,我找不到任何文档来帮助。

【讨论】:

我使用了笔记本电脑的公共 IP 地址并尝试使用 curl/浏览器访问端点,但我仍然收到 User:anonymous 错误。 我正在处理同样的问题。我注意到通过 aws elasticsearch 处理更改需要很长时间。 使用两个语句设置访问策略:一个用于 IAM 访问以写入日志,另一个具有 IP 限制访问以查看 KIbana。 See my answer for details 我想知道“loooong”是指几分钟、几小时还是几天。看起来10-15分钟。您可以在检查 ES 的状态时看到这一点(如果更新完成,则为绿色的“活动”,否则,类似于橙色的“准备中”。 我遇到了同样的问题,搜索后发现这个很方便library。【参考方案3】:

聚会有点晚了,但我能够通过在我的请求中添加签名来处理完全相同的问题。

如果你使用 Python(像我一样),你可以使用下面的库让它特别容易实现: https://github.com/DavidMuller/aws-requests-auth

它对我来说非常有效。

【讨论】:

【参考方案4】:

您只需要在弹性搜索策略中输入完整的用户名。

在这种情况下,您可以从错误消息中获取完整的用户名。 就我而言: “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]/*"
        
      ]

    

【讨论】:

【参考方案5】:

您可以使用基于资源的策略或基于身份的策略,而不是使用类似于硬编码 IP 地址的基于 IP 的策略。

但您需要使用 Signature 版本 4 来签署请求

Java实现请参考http://mytechbites.blogspot.in/2017/04/secure-amazon-elastic-search-service.html

【讨论】:

【参考方案6】:

角色 ARN 需要更改。它看起来像“arn:aws:iam::[ACCOUNT_ID]:role/service-role/my_es_role”

【讨论】:

【参考方案7】:

我也在尝试这样做,并且我使用Allow access to the domain from specific IP(s) 选项和我的 EC2 实例的弹性 IP 使其工作(也可以使用实例的私有 IP,但我不太确定)

【讨论】:

以上是关于Amazon Elasticsearch 集群的正确访问策略的主要内容,如果未能解决你的问题,请参考以下文章

将 AWS Kinesis Firehose 回填到 Elasticsearch Service 失败记录

将AWS Kinesis Firehose回填到Elasticsearch Service失败的记录

如何使用 CloudFormation 为 Amazon OpenSearch 设置兼容模式?

如何从 Amazon elasticsearch 服务访问 Kibana?

Django-Haystack 使用带有 IAM 凭证的 Amazon Elasticsearch 托管

ruby 在Heroku上使用Rails&searchkick gem安全地使用Amazon Elasticsearch(签名请求)。