使用 Cloudfront 以只读方式公开 ElasticSearch REST API (GET/HEAD)
Posted
技术标签:
【中文标题】使用 Cloudfront 以只读方式公开 ElasticSearch REST API (GET/HEAD)【英文标题】:Using Cloudfront to expose ElasticSearch REST API in read only (GET/HEAD) 【发布时间】:2013-12-22 18:56:54 【问题描述】:我想让我的客户直接与 ElasticSearch REST API 对话,显然阻止他们执行任何数据或配置更改。
我查看了 ElasticSearch REST 接口,发现了以下模式:HTTP GET requests 非常安全(无害的查询和集群状态)。
所以我想我可以将 Cloudfront 用作 CDN/代理,它只允许 GET/HEAD 方法(您可以在主配置中施加这样的限制)。
到目前为止一切顺利,一切就绪。但是事情不起作用,因为我需要向全世界开放我的 EC2 安全组才能从 Cloudfront 访问!我不想要这个,真的!
当我将 EC2 与 RDS 一起使用时,我可以简单地允许访问我在 RDS 安全组中的 EC2 安全组。为什么我不能使用 CloudFront 执行此操作?或者我可以吗?
想法?
edit:没有文档记录,但是 ES 接受 facets 查询,它涉及一个 (JSON) 主体,不仅使用 POST,还使用 GET。这只是通过不忽略 GET 请求 (source) 的正文来破坏 HTTP 建议(对于 RFC3616)。 这是因为,正如所指出的,直接暴露 ES REST 接口可能会导致使用复杂查询的简单 DOS 攻击。尽管如此,我仍然坚信,少一个代理仍然是值得的。
编辑:我的其他选择是跳过 CloudFront 并添加一个安全层作为 ElasticSearch 插件,如图所示 here
【问题讨论】:
【参考方案1】:我用自己的插件结束了编码。令人惊讶的是,周围没有这样的东西。 没有代理,没有 Jetty,没有 Tomcat。
只是一个原始的 ES rest 模块和我的 RestFilter。使用最少的反射来获取请求的远程地址。
享受:
https://github.com/sscarduzio/elasticsearch-readonlyrest-plugin
【讨论】:
谢谢伙计,我在官方 ES 文档中引用了该插件,但后来他们重新组织了,我再也找不到它了。我应该提出一个拉取请求。 @sscarduzio ,还在那里,我就是这样找到这个天才插件的!非常好的工作!总共 20 分钟,我设置并运行 :) elastic.co/guide/en/elasticsearch/plugins/2.3/security.html 嗯,很高兴听到,pandaadb!顺便说一句,非常欢迎贡献!从文档到 LDAP 连接器、测试等。github.com/sscarduzio/elasticsearch-readonlyrest-plugin/… @sscarduzio,我很快就安装了它。我试图让它与 Kibana 一起运行,但面临一些问题。我一定错过了什么。你介意看看吗? ***.com/questions/40193459/… @sscarduzio 你能看看我的问题***.com/questions/41910625/…【参考方案2】:请注意,即使是 GET 请求,在 Elasticsearch 中也可能是有害的。一个简单地占用过多资源来计算的查询将导致您的集群崩溃。分面是实现此目的的好方法。
我建议您在 ES 前面编写一个简单的 REST API,这样您就可以更好地控制搜索集群的内容。如果这不是一个选项,您可以考虑在您的 ES 机器上运行 nginx 以充当本地反向代理,这将为您提供与 CloudFront 相同的控制(以及更多)。然后你只需要向世界开放 Nginx,而不是 ES。
【讨论】:
谢谢 Victor,这正是我的 B 计划。无论是 Nginx 还是 Varnish。我不愿意这样做,因为它会增加一个移动部分来扩展技术堆栈。 另一个移动部分始终是一个合理的问题,但您确实需要您真正控制的一些东西来调解这些请求并将健全规则应用于这些请求。我会添加 haproxy 作为 nginx 或 varnish 的潜在替代品……它可以根据内容匹配进行拒绝,还可以做一些简单的速率限制和并发限制。 NGINX 从 v0.7.21 开始也支持rate limiting。可能更多的是您已经知道哪种工具。【参考方案3】:在 AWS 中执行此操作的方法是:
在您的 ES 集群前设置应用程序负载均衡器。为 ALB 创建 TLS 证书并提供 https。将 ES 安全组打开到 ALB。
设置 CloudFront 并将 ALB 用作源。传递带有秘密值的自定义标头(对于 WAF,请参阅下一点)。
在 ALB 上设置 WAF 以仅允许包含具有密钥值的自定义标头的请求。现在所有请求都必须通过 CloudFront。
在您的 CloudFront 分配上设置 Lambda@Edge 函数,以从 GET 请求中删除正文,或拒绝此类请求。
这是一项相当多的工作,但比插件有优势,例如:
CloudFront 自带免费网络 DDOS 防护
由于快速的 CloudFront 网络和全球 PoP,CloudFront 为您的用户提供更低的 ES 延迟。
打开许多选项以使用 CloudFront、WAF 和 Lamba@Edge 进一步保护您的 ES 集群。
我正在编写 CDK 中的示例代码来设置所有这些。准备好后会报告。
【讨论】:
好东西@Otto 期待看到这个:)以上是关于使用 Cloudfront 以只读方式公开 ElasticSearch REST API (GET/HEAD)的主要内容,如果未能解决你的问题,请参考以下文章
使用 AWS CloudFront 时,如何向公众隐藏自定义源服务器?