Elasticsearch权限管理:从裸奔集群到安全加固的完整实践 不少做 Elasticsearch 的同学最开始对权限管理的态度都是先跑起来再说。我在早期接手的集群里也见过生产环境裸奔很久、靠内网隔离当安全措施、所有客户端共用elastic超级账号的情况。这类集群表面看着正常实际上只要有一次误删索引、一个告警收紧、或者有一次排查任务需要临时开放人员访问你就会发现权限体系崩得比谁都干脆。这篇文章不打算从零讲 Elasticsearch 基础而是直接讲清楚权限管理到底在管什么、怎么从裸奔集群平稳切换到安全加固状态、以及切换之后那些文档里查不到、不踩一遍根本不会知道的坑。1. 为什么说权限管理不是锦上添花而是集群的底层基础设施先讲一个我实际遇到过的场景。某个内部日志分析集群总共有十多个业务团队在用最初大家默认走同一个用户读写索引。某次一个团队做数据清洗脚本里写错了索引名把另一个团队的索引整批删掉了。数据是从上游 Kafka 同步来的恢复花了整整一天最终定性原因是权限没有隔离。这个事故不是安全事件不是外部攻击纯粹是内部操作边界不清导致的但它的后果一点都不比安全事件轻。所以权限管理在 Elasticsearch 里的第一个作用是给不同的人/系统划定明确的操作边界。它管的不只是谁能登录更关键的是谁能对哪些索引做什么操作。这个边界不建立起来集群越是活跃、接入方越多失控的概率就越大。第二个作用是合规与审计需求。很多企业内部审计要求记录谁在什么时间对什么索引做了删除、修改、读取ES 的审计日志Audit Log和权限配置天然就是这套体系的基础没有权限管理的话审计无从谈起。第三个作用才是传统意义上的防攻击和防泄露。说它是底层基础设施还有一个现实原因Elasticsearch 从较新的大版本开始权限管理Security不再是收费功能基础级别的认证、授权、TLS 加密都已经随发行版提供。现在决定权完全在你手里——用不用是一回事懂不懂是另一回事。很多人在搭建阶段下意识忽略了这套东西等到需要补的时候才发现补权限比首次装的时候难受得多因为此时集群里已经有大量历史数据、多个客户端、各种内部脚本每一个都可能因为权限变更而突然连不上。我记得接手某个集群时它的elasticsearch.yml里连xpack.security.enabled这个配置都没有出现过所有节点裸奔Kibana 只用elastic登录所有索引权限全开放。问我能不能直接开启安全的负责人不在少数。答案是可以但要对后续影响有充分预期——改完以后集群里的服务账号、脚本、采集器、报表任务都需要跟着调整而不是只改一个开关。2. Security 机制的主角认证、授权、加密传输三者缺一不可很多人以为 ES 权限管理就是设置用户名密码这样理解就太窄了。真正的 ES Security 体系是三件事同时运转的认证负责回答你是谁常见的认证方式包括内置用户名密码、LDAP/AD 认证、SAML 单点登录、基于证书的 PKI 认证。内部节点之间通信也要互相认证这就用到了证书。授权负责回答你能做什么核心是角色Role和权限Privilege的匹配。加密传输负责回答你的数据在网络上传输时是不是安全的包括节点之间的 Transport 通信和客户端到节点之间的 HTTP 通信。只有三层同时落地才算一个完整的闭环。2.1 内置用户体系每个系统账号的用途别搞混ES 开启安全之后默认会有一批内置用户最核心的几个如下内置用户主要用途权限说明elastic超级管理员拥有所有集群/索引权限仅用于初始化配置和应急kibana_systemKibana 连接 ES 使用用于保存仪表盘、索引模式、告警配置等logstash_systemLogstash 采集监控信息用于上报监控指标beats_systemBeats 采集器监控信息用于上报监控指标remote_monitoring_userMetricbeat 远程监控用于采集集群指标写入监控索引这些内置用户各自有固定的用途分工实际使用中最容易出问题的是把elastic账号直接写进应用配置、日志采集配置、甚至报表任务里。这样做对运维人员是方便但对安全是灾难——一旦某个应用出现日志注入或者配置泄露等同于把整个集群的钥匙交了出去。正确的做法是坚持一个业务一个专用账号或专用角色。比如日志采集系统用一个logstash_writer角色它只能写logstash-*和filebeat-*索引不能删除、不能关闭索引报表系统用另一个角色只能读reports-*索引业务团队每个项目组单独账号权限严格限定到自己的索引前缀。2.2 权限的最小单元与组合方式了解 Action 才能理解授权ES 授权体系里权限的最底层是action 级别类似indices:data/read/search、indices:data/write/index、indices:admin/delete这些细粒度的 API 动作权限。直接给用户配置 action 是反人类的所以 ES 封装成了常用的索引权限和集群权限比如索引权限read读文档、write写文档、delete删文档、manage管理索引映射和设置、view_index_metadata查看索引元数据、all全部。集群权限monitor查看集群健康、manage管理索引模板、管道等、manage_ilm管理生命周期、manage_security管理用户和角色、all全部。角色Role就是一组这样的权限集合。用户User可以绑定多个角色最终生效权限是所有角色权限的并集。这个模型跟 Linux 的 group 有点像——你不直接给账号堆权限而是给角色设计语义清晰的权限包再把账号归类到角色。部分读者可能会想那我直接把所有权限都all不就行了——可以但这样权限管理的意义就只剩审计了。生产环境里更推荐的思路是最小权限原则某个业务只需要read和view_index_metadata就不给它write只需要写入采集索引就不给它集群的manage_ilm。原因很简单一个权限过于宽泛的账号一旦被滥用造成的损伤可能是指数级的。2.3 传输层的 TLS 加密不加密的认证等于裸奔开启认证后如果不启用传输层加密有一个容易被忽略的风险认证过程中的用户名密码可能通过明文传输被抓包。因此 ES 安全体系要求传输层也加密这就要用到节点间证书。我这里说的节点间证书不是指那种由权威 CA 签发的公网证书虽然也不排斥而是可以用 ES 自带的elasticsearch-certutil工具生成的一套内部 CA 和节点证书。这套证书的逻辑类似内部加解密密钥节点之间用它来互相确认身份确保数据在 Transport 链路上不泄露、不篡改。注意证书分为 CA 证书签发机构、节点证书每个节点一个和客户端证书供 HTTP 客户端使用。在内部集群场景里信任链是最重要的——节点之间验证的是对方证书是否由同一个 CA 签发而不是域名的公网可信度。3. 从裸奔集群切换到安全模式一次完整的加固操作记录这部分我以自己的实战操作过程为例给出一个可直接复现的加固链路。假定环境是常见的自建多节点集群版本为 8.x目前没有启用任何安全特性。3.1 第一步规划账号模型与索引空间动手之前不要直接去敲命令。先把谁要用集群列清楚。我习惯列一个简单的矩阵包含四列使用方类型Kibana 用户、应用服务、日志采集器、监控系统需要访问的索引前缀需要的操作类型读、写、管理索引还是只能看 Dashboard网络来源哪些 IP/网段这个矩阵是后续角色设计的依据。别小看这一步很多集群在加固后频繁出现某个团队看不到数据某个采集器写不了索引的问题根子往往就是规划阶段没有把账号和索引空间的对应关系理清楚。3.2 第二步生成并分发 CA 证书与节点证书先切换到一个专门存放证书的目录然后依次执行# 生成私有 CA bin/elasticsearch-certutil ca --pem --out /srv/elasticsearch/config/tls/ca.pem # 为每个节点生成证书以 node1 为例其他节点重复执行改实例名称和节点 IP bin/elasticsearch-certutil cert \ --pem \ --ca-cert /srv/elasticsearch/config/tls/ca.pem \ --ca-key /srv/elasticsearch/config/tls/ca.key \ --name node1 \ --dns localhost \ --ip 192.168.1.11,127.0.0.1 \ --out /srv/elasticsearch/config/tls/node1.pem生成后目录下会有node1.pem和node1.key两个文件。给每个节点分发对应的证书与私钥同时把ca.pem分发到所有节点。如果节点数量多这一步建议写成脚本统一执行避免手工复制出错。这里有个容易搞错的点--ip参数里最好同时包含本机回环地址127.0.0.1。如果漏了节点之间用本地地址做 Transport 通信时证书主机名/IP 校验会失败。3.3 第三步修改各节点配置并滚动重启在每个节点的elasticsearch.yml里追加如下内容xpack.security.enabled: true xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.verification_mode: certificate xpack.security.transport.ssl.keystore.path: tls/node1.p12 xpack.security.transport.ssl.truststore.path: tls/ca.p12如果用了.pem格式需要把证书和私钥路径分别写成xpack.security.transport.ssl.certificate: tls/node1.pem xpack.security.transport.ssl.key: tls/node1.key xpack.security.transport.ssl.certificate_authorities: tls/ca.pem关于修改配置有两个细节很重要因为 ES 的Transport 层通信是所有节点互相连通的所以任何一个节点的 TLS 配置不对称都会导致部分节点之间握手失败、集群状态变红。这就是为什么所有节点一起改、滚动重启要比一两个节点先试更稳当。如果你打算做滚动重启请先停掉写入方或者至少观察几分钟确认每个节点重启后都能重新加入集群再进行下一个。否则你很有可能重启到一半发现集群 split brain。3.4 第四步设置内置用户密码Transport 加密生效之后进入设置密码环节。在初始节点上执行bin/elasticsearch-setup-passwords interactive这个命令会要求你为elastic、kibana_system、logstash_system等内置用户设置密码。生产环境尤其强调为elastic设置一个强密码并保存到密码管理器中因为后续几乎所有管理员级别的操作都要用到它。设置完密码后原先不带认证的客户端请求比如curl http://localhost:9200会返回 401这是正常的。此时可以验证一下curl -u elastic:你的密码 https://localhost:9200/_cluster/health加-k或者配置 ca 证书是因为默认用的自签 CA 不被系统信任这是本地验证时的正常行为不是配置错了。3.5 第五步配置 Kibana让仪表盘恢复可用Kibana 需要单独配置内置账号kibana_system。在kibana.yml中加上elasticsearch.hosts: [https://node1:9200] elasticsearch.username: kibana_system elasticsearch.password: 你设置的kibana密码 elasticsearch.ssl.certificateAuthorities: [/srv/kibana/config/tls/ca.pem]改动这一段之后重启 Kibana确认它能正常连到 ES。如果配置正确Kibana 登录页会出现用户可以用自己的账号登录并查看各自的仪表盘权限。4. 生产环境的角色建模内置角色远远不够实际案例才是最有参考价值的提高安全等级只是第一步权限管理的真正难点是角色建模。在内置角色之上生产环境基本都需要自定义角色。下面我给两个真实生产中高频出现的角色配置示例供直接参考。4.1 示例一日志采集用的只写可管理自身索引角色这是最典型的场景Logstash/Filebeat 往logs-*索引写数据对索引模板和生命周期有管理权但不需要读权更不能删除其他索引。{ role_name: log_writer, cluster_permissions: [manage_index_templates, manage_ilm, monitor], index_permissions: [ { indices: [logs-*], privileges: [write, create_index, manage, view_index_metadata] } ] }manage在这里是用来处理索引别名、滚动和关闭等操作create_index允许采集器在索引不存在时自动创建。如果缺了这一条采集器很可能会因为索引不存在、没有权限创建而直接丢数据。这也是我在实践中遇到的最常见采集失败原因之一。4.2 示例二数据报表团队用的只读角色报表团队只需要查询 Dashboard 和读取分析数据任何写权限都不给。此时角色设计为{ role_name: report_reader, cluster_permissions: [monitor], index_permissions: [ { indices: [reports-*, analytics-*], privileges: [read, view_index_metadata] } ], application_permissions: [ { application: kibana-.kibana, privileges: [read], resources: [space:default] } ] }这个配置有意思的部分在application_permissions。Kibana 的仪表盘、索引模式本身也是存放在 ES 的.kibana索引里的所以用户想在 Kibana 里看面板还需要对 Kibana 应用有read权限。只配置索引权限而忽略 application 权限会出现用户登录成功但看不到任何面板/数据的诡异问题。角色创建之后再用内置用户elastic去创建用户、绑定角色bin/elasticsearch-users useradd report_user1 -p 你的密码 -r report_reader或者通过 API 创建curl -u elastic:密码 -X POST https://localhost:9200/_security/role/report_reader -H Content-Type: application/json -d { ... 角色配置 ... }使用 API 的好处是角色配置会进入集群状态而使用roles.yml文件的方式在节点间分发上更麻烦也不易被 API 读取和管理。我个人建议有能力用 API 的尽量用 API把角色配置纳入代码仓库做版本管理。4.3 多团队索引空间隔离设计当多个团队共用一个集群时我建议在索引命名上就做好隔离——每个团队一个索引前缀比如team-a-*、team-b-*。然后分别为每个团队建一个角色将权限限定到对应的前缀team_a_roleindices: [team-a-*]privileges:[read, write, manage]team_b_roleindices: [team-b-*]privileges:[read, view_index_metadata]这样做的好处是即便某个团队拿到账号密码也无法访问其他团队的索引。对空间隔离有限制需求的场景甚至可以更进一步使用 Elasticsearch 的空间Space功能把 Kibana 面板、索引模式按空间隔离但那是另一个课题本文不再展开。5. 权限管理落地后的高频故障这些坑我基本都踩过安全配置启用之后的头一两个月往往是故障高发期。这里整理几个我实际遇到过的、具备很强代表性的问题希望能帮你少走弯路。5.1 改密后客户端集体 401排查链路的完整复盘某次给一个大版本升级后的集群做安全加固改完密码之后第二天收到大量 401 告警。我第一时间想到的是哪些客户端还用了旧密码但逐个排查太慢。更高效的方式是在 ES 的审计日志里按时间区间过滤未授权访问的来源 IP再用来源 IP 反查客户端配置。如果你还没有开启审计日志建议在加固后第一时间开启xpack.security.audit.enabled: true xpack.security.audit.logfile.events: [access_denied, access_granted, authentication_failed, authentication_success]有了审计日志排查 401 就等于按图索骥而不必去猜哪个服务用错了密码。5.2 只开 HTTP 认证没开 Transport TLS导致节点间通信裸奔严格来说这不是故障但是个安全盲区。有些管理员为了省事只设置了xpack.security.enabled和 HTTP 层的 TLS没有配置xpack.security.transport.ssl。结果看起来集群一切正常然而节点之间 Transport 通信并未加密。此时集群内部数据流实际上是以明文传输的这跟不加密没有任何本质区别。我建议至少将verification_mode设置为certificate并强制分发 CA 证书到所有节点。这样节点之间会校验证书链但又不需要指定严格的主机名列表避免后续节点扩容时证书与主机名不匹配的问题。5.3 索引权限给了 read 但忘了给 view_index_metadata导致看不到索引列表另外一个容易隐形踩坑的地方是用户能读数据但看不到索引。比如有些工具在展示可访问索引时需要view_index_metadata权限才能列出索引元数据。如果只给了read没有给view_index_metadata用户可能不报错但界面里什么都看不到。这个问题在 Kibana 的索引模式里尤为明显。给只读用户建角色时直接把这两个权限一起给上是标准做法因为view_index_metadata本身不暴露文档内容仅暴露索引结构信息对大多数只读场景是非常安全的。5.4 默认证书和自定义 CA 混用导致重启后集群恢复困难还有一次某同学自己生成了一整套证书但其中两个节点配置错了truststore路径重启后出现节点间握手失败。这是典型的手工配置错误。排查方式主要是看节点日志里的异常堆栈检索关键词如unable to establish TLS、PKIX path building failed然后逐一比对节点间的证书与 CA 路径。为了避免这类问题强烈建议把证书路径、证书指纹统一整理成表格再逐节点核对。下面是我常用的核对表头节点证书路径私钥路径CA 路径指纹是否一致用脚本跑一遍openssl x509 -fingerprint -noout -in cert把输出和配置比对能快速定位到到底哪个节点的证书不对。6. 权限管理上线后的可持续运营定期审查比一次性配置更重要权限管理不是一次性配置完就结束了。至少每个季度做一次权限审查重点检查以下几项过期账号清理有没有离职员工或者已经停用的服务账号还留在用户表里。权限收敛检查有没有账号实际只需要read却被赋予了manage或all。超级管理员使用记录elastic账号是否只出现在初始化配置中日常操作是否都通过个人账号完成。密钥轮换内置账号的密码是否长时间未更新证书的到期时间是否足够靠前建议提前至少一个月安排证书轮换。这些检查不一定要用很复杂的工具通过 Kibana 的现有 API 就能查询角色和用户列表再配合审计日志定期抽查即可。哪怕只是写成一个每月定时脚本跑一遍也能大幅降低权限逐渐膨胀带来的风险。以我个人的实际经验来说把 ES 集群的权限管理做好之后运维日常的一大块隐性焦虑会消失。以前担心某天误操作删库业务账号被泄露导致集群被拖垮现在都有了明确的边界和审计手段。它可能不会让你的查询变快、不会让你的集群更稳定但它能让你在问题发生时有一个可以冷静分析而不是疲于救火的底子。最后分享一个实用的小技巧在没把握的情况下改任何安全相关配置之前先做一个全量配置备份。ES 的 Security 配置虽然可以通过 API 查询但节点上的配置文件最好也保留一份快照。我每次做安全相关变更都会先在本地目录保存elasticsearch.yml和证书压缩包并记录变更时间点和原因。这个习惯看着笨但真的每次出问题时都能大幅缩短排查时间。毕竟权限管理这件事最怕的不是配置复杂而是出了问题连之前是什么状态都没法回溯。