【问题标题】:Permissions to access ElasticSearch from Lambda?从 Lambda 访问 ElasticSearch 的权限?
【发布时间】:2016-10-08 01:13:37
【问题描述】:

我正在尝试使用 Elasticsearch 为连接到 Alexa Skills Kit 的 Lambda 函数存储数据。 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"
        }
      }
    }
  ]
}

这个forum post 提出了同样的问题,但没有得到回答。

【问题讨论】:

    标签: amazon-web-services aws-lambda amazon-elasticsearch


    【解决方案1】:

    我知道的唯一方法是在您的 ES 域上使用基于资源的策略或基于 IAM 的策略。这将限制对特定 IAM 用户或角色的访问。但是,要完成这项工作,您还需要使用 SigV4 对 ES 的请求进行签名。

    有些库会为您执行此签名,例如 this one 扩展了流行的 Python 请求库以通过 SigV4 对 ElasticSearch 请求进行签名。我相信其他语言也存在类似的库。

    【讨论】:

    • 你说的是this这个模块吗?另外,我的设置是否适合尝试混合使用 IAM 和 IP?
    • 我用指向我所指项目的链接更新了答案。
    • 好的,现在大部分工作正常。我想不出用 Lambda 角色进行身份验证的方法,而是使用了专用用户。唯一的问题是我无法再从浏览器访问 Kibana,但这没什么大不了的。
    • 这里是来自 AWS 的指南,描述了如何使用不同的语言签署请求:docs.aws.amazon.com/elasticsearch-service/latest/developerguide/…
    • 是否有更详尽的指南来说明如何执行此操作?我在管理角色方面还是有些新手。
    【解决方案2】:

    现在可以从您的代码中使用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({...})
    

    当然,在使用之前,先配置对elasticsearch域的访问:

    【讨论】:

      【解决方案3】:

      对于对 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 函数,使用以下策略 sn-p 创建 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>>/*"
        ]
      }
      

      我设法从以下来源拼凑出上述内容:

      https://aws.amazon.com/blogs/security/how-to-control-access-to-your-amazon-elasticsearch-service-domain/

      How to access Kibana from Amazon elasticsearch service?

      https://forums.aws.amazon.com/thread.jspa?threadID=217149

      【讨论】:

        【解决方案4】:

        【讨论】:

        • 对于 ElasticSearch 文档 API 的查询,这不会“开箱即用”。使用您的语言的 HTTP 客户端模块发出的 HTTP(s) 请求将没有 AWS V4 请求签名,并将被视为来自匿名用户。您需要使用 AWS 签名明确签署您的 HTTP 请求,以使预期的角色得以执行。
        【解决方案5】:

        AWS Lambda 在公共 EC2 实例上运行。因此,简单地将 IP 地址白名单添加到 Elasticsearch 访问策略是行不通的。一种方法是为 Lambda 执行角色授予对 Elasticsearch 域的适当权限。确保 Lambda 执行角色对 ES 域具有权限,并且 ES 域访问策略具有允许此 Lambda 角色 ARN 执行适当操作的语句。完成此操作后,您只需在访问 ES 端点时通过 SigV4 签署您的请求

        希望对您有所帮助!

        【讨论】:

        • 我实际上正在尝试实施您建议的策略,但在创建 ElasticSearch 内联策略以允许我的 lambda 函数时遇到问题。您有示例政策吗?
        猜你喜欢
        • 2020-08-27
        • 2021-04-02
        • 2020-08-01
        • 2016-05-27
        • 1970-01-01
        • 2020-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多