前文分别介绍了滴滴自研的ES强一致性多活是如何实现的、以及如何提升ES的性能潜力。由于ES具有强大的搜索和分析功能,同时也因其开源和易于使用而成为黑客攻击的目标。近些年,业界ES数据泄露事件频发, 以下是一些比较严重的数据泄露案件:
2021年12月,Socialarks泄露了400GB数据,由于ElasticSearch数据库设置错误,泄露了超过3.18亿条用户记录,涉及到Instagram、领英、Facebook等多个社交平台的用户信息。[1]
2022年6月,美的(midea.com) 某分站存在Elasticsearch未授权访问漏洞。[2]
2022年8月, 超过2.8亿条印度公民记录在网上泄露,包括用户账户信息、银行账户信息和个人身份信息。[3]
滴滴引入 ES 时,也存在ES http 9200端口未授权访问和 Kibana http 5601端口未授权访问问题,为了保障数据安全,滴滴ES团队决定尽快修复这些问题。
1
问题描述
先简单介绍下滴滴ES架构,包含如下五个部分:
1. ES集群:提供数据存储、分词、检索等服务
2. GateWay集群:ES集群代理,提供认证、鉴权、限流、路由、指标统计功能,用户通过GateWay集群读写ES集群索引
3. ES Admin管控平台:提供元数据展示,索引定时创建清理、DCDR主从切换校验等功能
4. 用户控制台:用户操作索引、展示索引信息的平台
5. 用户端:用户通过ES client访问GateWay集群
问题在于ES整个服务具备认证和鉴权能力,但ES集群单独对外时不具备安全认证能力。ES服务通过 Gateway 对外提供安全认证和鉴权服务,但 ES 集群本身并没有安全认证能力,任何人只要获取到 ES 集群 IP、端口就可以对ES集群进行任何操作。因此,我们需要对 ES 集群增加安全认证能力,并且需要对访问ES集群的admin、gateway、客户端进行安全适配工作。
2
解决方案
方案一:ES X-Pack 插件
1、ES X-Pack 插件简介
ES X-Pack是Elasticsearch的官方插件,提供了一系列的功能,包括安全性、警报、监视、报告和图形可视化等方面的支持。其中安全特性提供了身份验证、授权和加密功能,可以确保只有授权的用户才能够访问集群。
开启 X-Pack 安全特性,通过HTTP请求创建账号密码并将账号密码信息存储在ES索引中。ES集群接收HTTP请求并处理,处理过程中会调用AuthenticationService进行安全认证(通过解析请求头中的账号密码和索引账号密码对比是否一致)。HTTP认证通过后会将认证用户信息写入线程上下文,并会在TCP层执行相关操作前进行授权检查,检查该认证用户是否拥有对应操作权限,授权通过后方可执行真正的业务逻辑。
2、优势
Kibana不需要进行代码改造。Kibana 本身支持 X-Pack 插件,并在页面提供账号密码登录页面。
原生支持完整的认证、授权、审计逻辑。
3、 缺点
无法支持集群滚动重启升级,插件开启后,不仅会强制开启HTTP层账号密码身份验证,并且为了确保恶意节点无法加入集群,会强制节点之间TCP层面使用SSL加密通信认证。在滚动重启升级安全认证过程中,未升级节点和已升级节点TCP无法通信导致集群不可用。
DCDR无法同步数据,如果主集群未开启安全认证,从集群开启安全认证,由于TCP层存在授权逻辑,将会导致主集群请求从集群失败。
无法快速回滚止损,ES账号密码认证机制开启后,如果第三方因为安全认证访问异常,无法及时止损,必须集群节点全量回滚方可恢复。
误删账号密码存储索引、索引别名会导致集群不可访问,并且账号密码信息不可恢复。该插件将账号密码信息存储在集群的security索引里面,并通过索引别名访问该索引,误删该索引或者索引别名都会导致账号密码信息丢失,从而无法认证请求导致请求失败。
误操作修改密码会导致访问不可用,止损时间过长。密码恢复流程复杂,需要登录到线上机器执行5个步骤方可修改为原有集群账号密码。
4、改造点
新增动态配置支持一键开关安全认证,支持一键止损。
移除节点TCP层 TLS/SSL 加密通信逻辑,支持DCDR同步数据以及集群滚动重启。
GateWay、Admin、client需要在请求头中携带账号密码信息。
方案二:自研 ES 安全插件
1、自研 ES 安全插件原理简介
通过自研插件的方式实现 http 请求拦截器,该拦截器用于获取 http请求头携带的账号密码信息,根据本地配置文件中保存的账号密码信息进行匹配认证。如果认证成功可以继续执行后续逻辑,失败则返回认证失败异常。
2、优势
架构简单,逻辑清晰,只需在HTTP请求处理环节中进行简单的字符串校验,无需涉及节点内部TCP通信验证。
支持ES集群滚动重启升级。通过增加动态集群配置能够很方便的开启关闭权限校验,对滚动升级友好。
支持一键开关安全认证能力,可以快速止损。新增集群动态配置,一键开关安全认证,用户因为安全认证访问异常时可以快速止损。
Kibana不需要进行代码改造
1) 只需要在Kibana.yml配置正确账号密码,kibana请求就会自动携带该账号密码可访问ES集群
2) 登录Kibana页面也需要输入正确的账号密码方可访问,不要额外的认证跳转页面
避免误操作修改密码导致请求不可用。账号密码配置在elasticsearch.yml 并且强制不可修改
3、缺点
只有大账号认证功能,没有鉴权、审计等其他功能
后期修改密码需要集群节点重启生效
4、改造点
方案选择
从开发量、易运维、稳定性、易用性等角度综合比较上述两个方案,我们最终决定采用了方案二。下面是采用方案二后ES生态的查询流程:
1. ES客户端向Gateway发起查询请求。
2. Gateway对该请求进行认证和鉴权,鉴权通过后会到Admin获取对应集群的访问地址以及访问ES集群的账号密码,并缓存到本地。
3. Gateway通过步骤2获取到的ES集群账号密码,将查询请求转发到对应ES集群。
4. ES执行查询逻辑将结果返回给Gateway,Gateway将该结果返回给客户端。至此查询流程结束。
3
上线保障
安全升级涉及ES集群、ES Gateway、ES Admin、ES客户端、Fastindex(Hive2ES)、DataX(Mysql2ES)、Flink2ES。以下是升级组件的规模:
ES 共有66个集群,2236个节点
Gateway 共有28个集群,492个节点
Admin 共2个集群,12个节点
Flink2ES 共有8500+任务需要重启任务升级到最新ES客户端
Fastindex 3个集群
DataX 3个集群
其中升级最为繁琐的是ES集群。ES是一个分布式引擎,它将数据分散存储在多个节点上。当 ES 集群进行滚动升级时,一个节点重启可能会导致集群状态变为 "yellow",这意味着集群中的某些分片副本未能被分配到节点上。为了保障数据的可用性,需要等待集群状态恢复为 "green",才会对下一个节点进行重启。集群从 "yellow" 恢复到 "green"的时间长短取决于集群中的数据量和节点数量,公共集群一个节点升级极端情况下会超过1小时,所以ES所有集群完成一个大版本升级往往需要3个月以上。
为了确保所有组件都稳定升级到安全版本,守住稳定性的基石和底线,避免ES开启安全特性后影响业务读写,同时在变更时发现异常问题能快速回滚,我们做了以下工作:
ES引擎支持一键开关安全特性。前文也提到,为了支持ES集群滚动重启升级、避免ES集群、ES客户端等组件升级互相影响,也为了出现访问不可用时可以秒级回滚,ES安全认证插件支持一键开启、关闭集群安全认证能力。
依照ES集群优先级依次升级、开启安全特性。优先级从低到高分别为:日志集群、公共集群、独立集群,如果中间出现问题可以及时回滚和关闭安全特性,避免带来更大的稳定性问题。
脚本定时扫描ES集群、Gateway集群。确保所有ES节点、Gateway节点都已经升级到安全认证版本。
统计Flink任务运行版本。确保Flink2ES任务都已经升级完毕
增加ES安全认证异常指标。通过指标兜底确保集群开启安全特性时影响业务时可以及时发现并关闭集群安全特性,等用户升级完毕后再重新开启。
4
总结
历时3个多月, ES RD 同学配合ES SRE同学完成了所有ES组件的升级,Flink2ES 任务也在Flink团队的大力支持下完成全量重启升级,DataX 在同步中心同学配合下完成了升级。并且在业务几乎无感情况下开启了所有集群的安全特性。至此,滴滴ES线上所有集群都支持安全认证能力,大大降低了数据泄露和数据丢失的风险。