不少做 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_system | Kibana 连接 ES 使用 | 用于保存仪表盘、索引模式、告警配置等 |
logstash_system | Logstash 采集监控信息 | 用于上报监控指标 |
beats_system | Beats 采集器监控信息 | 用于上报监控指标 |
remote_monitoring_user | Metricbeat 远程监控 | 用于采集集群指标写入监控索引 |
这些内置用户各自有固定的用途分工,实际使用中最容易出问题的是:把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_role:indices: ["team-a-*"],privileges:["read", "write", "manage"]team_b_role:indices: ["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和证书压缩包,并记录变更时间点和原因。这个习惯看着笨,但真的每次出问题时都能大幅缩短排查时间。毕竟,权限管理这件事最怕的不是配置复杂,而是出了问题连"之前是什么状态"都没法回溯。