从非 AWS node.js 应用程序连接到 AWS Elasticsearch

Connecting to AWS Elasticsearch from non-AWS node.js app

我正在努力解决我正在进行的项目中的基础架构问题。我正在开发的服务托管在一个短暂的容器化平台上 w/o 一个稳定的 IP — 只有一个域名 (api.example.com)。我正在使用 Elasticsearch 进行搜索,因此请求转到 /my-search-resource 之类的内容,然后使用 ES 查找 return 的结果。它是用 node 编写的,并使用支持的 elasticsearch 驱动程序连接到 ES。

我遇到的问题是尝试使用 AWS Elasticsearch 域。这个项目是自举的,所以我利用了 AWS 的免费层,即使其他服务 hosted/deployed 在另一个平台上(想想:heroku、GCP 等——容器化和瞬态资源)。

因为我不能只将特定 IP 列入白名单,所以我不确定应该怎么做才能使服务能够访问该服务。我是否需要签署发送到域的每个请求?这并不理想,因为它需要使用该功能对 ES 驱动程序库进行猴子修补。理想情况下,我只想使用用户名和密码连接到域,但我知道 IAM 并不是真正面向来自外部服务的类似内容。有任何想法吗?这甚至可能吗?

这不是问题的解决方案,而是关于如何解决问题的一些想法。我们目前处于同一个困境:我们希望使用 AWS,但我们不想与 AWS SDK 捆绑在一起。据我了解,AWS 提供了 3 个选项:

  1. 开放至 public(不可取)
  2. 固定IP地址(白名单)
  3. AWS 身份验证

选项 1 不可行。

选项 2 给我们带来了一个问题,即我们必须教导我们用来登录那里的任何内容都通过代理,以便请求看起来来自相同的 IP 地址。我们的设置是在 Heroku 上进行的,我们使用 QuotaGuard 来解决类似的问题。但是:我检查了我将要用于交互的模块(我们试图在那里登录,直接使用 winston 传输到 logstash 或 elasticsearch)并且它们不支持代理。也许这在您的情况下有所不同。

winston 传输目前也不以任何方式支持选项 3。这将使我们只能使用 aws-sdk 模块并永远与 AWS 结合或编写我们自己的模块。

在我当前的项目中,我们通过使用正常 elasticsearch NPM package, and then use http-aws-es 连接到 AWS Elastic 以在连接时创建特定的 AWS 连接 header。

例如我们有这样的东西:

const es = require( 'elasticsearch' );
const httpAwsEs = require( 'http-aws-es' );

const esClient = es.Client( { 
  hosts: 'somehostonaws',
  connectionClass: httpAwsEs,
  awsConfig: {
    region: 'some-aws-region',
    accessKey: 'some-aws-access-key',
    secretKey: 'some-aws-secret-key'
  }
} );

这不需要整个 AWS SDK,但它可以让您连接到 AWS 后面的 Elastic。这能解决您的问题吗?