Elasticsearch集群安全加固实战:TLS加密与Kibana RBAC权限配置指南
1. 项目概述与核心价值最近在帮一个客户做内部日志分析平台的加固他们之前用的Elastic Stack也就是大家常说的ELK集群是裸奔的节点间通信明文传输Kibana谁都能登录权限管理基本靠自觉。这显然不符合安全合规的要求。客户的需求很明确一是要加密不能让数据在网络上裸奔二是要管权限不同团队的人只能看到自己负责的业务日志。这不就是典型的ES集群加密和Kibana RBAC基于角色的访问控制实战场景吗Elastic Stack从6.8和7.1版本开始在默认发行版中就免费提供了TLS加密和RBAC等核心安全功能这大大降低了我们实施安全加固的门槛和成本。但官方文档往往侧重于“怎么做”对于“为什么这么做”以及“踩坑了怎么办”讲得不够细。今天我就结合这次实战把从零开始为一个已有集群或新集群启用加密和配置精细化权限的完整过程、背后的原理以及我趟过的那些坑一次性讲透。无论你是运维工程师、DevOps还是安全负责人这篇文章都能给你一份可以直接“抄作业”的实操指南。2. 安全架构设计与核心组件解析在动手之前我们必须先理解Elastic Stack的安全体系是如何构建的。它不是一个孤立的开关而是一套由多个层次、相互关联的组件构成的完整方案。盲目开启配置很容易导致集群无法启动或者功能异常。2.1 安全功能的三层架构Elastic Stack的安全体系可以粗略分为三层传输层安全、认证与授权、以及审计。传输层安全TLS/SSL是基石它确保了数据在Elasticsearch节点之间、以及客户端如Kibana、Logstash、Beats与Elasticsearch集群之间传输时的机密性和完整性。想象一下你的应用日志、用户行为数据在服务器间以明文传输任何能抓到网络包的人都能一览无余这是极其危险的。TLS通过加密通道解决了这个问题。认证与授权是访问控制的核心。认证解决“你是谁”的问题Elasticsearch内置了native用户名/密码、LDAP、Active Directory、PKI等多种认证方式。授权解决“你能干什么”的问题这就是RBAC发挥作用的地方。它通过“用户 - 角色 - 权限”的模型进行控制。权限可以细粒度地分配到索引级别例如只能读app-logs-*索引、文档级别通过Document Level Security甚至字段级别通过Field Level Security。审计日志是事后追溯和合规性的保障。它会记录所有成功和失败的安全事件比如谁在什么时候尝试访问了什么数据结果如何。这对于满足等保、GDPR等合规要求至关重要。2.2 核心安全组件交互关系很多人在配置时搞不清elasticsearch.yml、kibana.yml以及各种用户、角色之间的关系。我们来理清它们的交互链路Elasticsearch节点间通过配置xpack.security.transport.ssl.*节点使用共享的证书或CA签发的证书建立TLS连接相互认证。Kibana连接ElasticsearchKibana作为一个客户端需要用一个专门的“服务账号”通常是kibana_system用户去连接启用了安全的Elasticsearch。这个连接本身也需要TLS加密elasticsearch.ssl.*配置并且Kibana需要知道这个服务账号的密码。最终用户登录Kibana用户打开浏览器访问KibanaKibana将用户的登录凭证用户名/密码转发给Elasticsearch进行认证。认证成功后Elasticsearch会返回该用户所拥有的角色列表。Kibana界面渲染Kibana根据Elasticsearch返回的用户角色动态决定在界面上展示哪些功能空间、仪表板、管理菜单等和数据。注意这里有一个关键点Kibana本身不存储用户和权限它只是一个“代理”和“呈现器”。所有的认证和授权逻辑都发生在Elasticsearch端。这就是为什么我们必须先在Elasticsearch中配置好用户和角色。2.3 证书体系的选择自签名 vs 私有CA vs 公共CA为TLS加密准备证书是第一步也是第一个决策点。主要有三种方案自签名证书elasticsearch-certutil生成这是最快、最简单的入门方式适合测试、开发或内部非生产环境。它生成的.p12或.jks文件包含了证书和私钥所有节点共用同一份。缺点是缺乏真正的信任链在添加新节点或客户端时需要手动分发证书管理麻烦。私有CA签发这是生产环境的推荐做法。你可以使用OpenSSL、CFSSL等工具搭建自己的私有证书颁发机构CA然后为每个Elasticsearch节点、每个客户端签发独一无二的证书。这样你只需要在所有节点和客户端信任你的私有CA根证书即可扩展性更好也更安全。公共CA签发如果你的Elasticsearch集群需要被互联网上的服务访问通常不推荐可以考虑购买公共CA签发的证书。但这在集群内部通信中很少使用因为成本高且没必要。对于本次实战和大多数内部场景我们将从最简单的自签名证书开始但我会详细说明如何过渡到私有CA方案因为这是你迟早要面对的。3. 实战为现有ES集群启用TLS加密假设我们有一个正在运行的、未加密的两节点Elasticsearch集群节点名es-node-01, es-node-02版本为7.17.x。我们的目标是在不影响现有数据的情况下平滑地启用节点间传输加密。3.1 第一阶段生成与部署证书首先我们需要生成证书。在生产中我强烈建议使用私有CA。但为了流程完整我们先演示自签名证书再说明私有CA的步骤。方案A使用elasticsearch-certutil生成自签名证书快速入门选择一个节点作为操作机例如es-node-01进入Elasticsearch安装目录。生成PKCS#12格式的证书库# 交互式生成会提示输入密码 ./bin/elasticsearch-certutil ca ./bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12 # 或者非交互式生成一个无密码的证书仅用于测试 ./bin/elasticsearch-certutil cert -out config/elastic-certificates.p12 -pass 执行第一条命令会生成一个CA证书elastic-stack-ca.p12第二条命令用这个CA签发一个节点证书。或者直接用第二条非交互命令生成一个自签名的节点证书包。生成的.p12文件包含了证书和私钥。分发证书将生成的elastic-certificates.p12文件或CA证书节点证书安全地拷贝到所有Elasticsearch节点的config/目录下。确保文件权限是安全的如600。方案B使用OpenSSL搭建私有CA生产推荐创建私有CA# 1. 生成CA私钥 openssl genrsa -out ca.key 2048 # 2. 生成CA自签名根证书 openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj /CCN/STBeijing/LBeijing/OYourCompany/CNElasticStack Internal CA为每个节点生成证书签名请求CSR和私钥# 为es-node-01生成 openssl genrsa -out es-node-01.key 2048 openssl req -new -key es-node-01.key -out es-node-01.csr -subj /CCN/STBeijing/LBeijing/OYourCompany/CNes-node-01.yourdomain.com注意CN字段通常使用节点的主机名或FQDN这在证书验证时会用到。用CA签发节点证书openssl x509 -req -in es-node-01.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out es-node-01.crt -days 365将证书转换为Java KeystoreJKS或PKCS#12格式Elasticsearch原生支持.p12和.jks。# 将证书和私钥打包为PKCS#12格式 openssl pkcs12 -export -in es-node-01.crt -inkey es-node-01.key -out es-node-01.p12 -name es-node-01 -passout pass:YourKeystorePassword将生成的es-node-01.p12和ca.crt分发到对应节点。3.2 第二阶段配置Elasticsearch节点证书准备好后需要修改每个节点的elasticsearch.yml配置文件。关键配置如下# 启用安全模块包含认证、授权、TLS等 xpack.security.enabled: true # ---------- 节点间传输加密 (Transport TLS) ---------- # 启用传输层TLS xpack.security.transport.ssl.enabled: true # 验证模式。生产环境建议用full验证主机名测试可用certificate只验证证书有效性 xpack.security.transport.ssl.verification_mode: certificate # 指向节点的证书库包含节点自己的证书和私钥 xpack.security.transport.ssl.keystore.path: /path/to/elastic-certificates.p12 # 如果证书库有密码需要配置 xpack.security.transport.ssl.keystore.password: xpack.security.transport.ssl.keystore.type: PKCS12 # 信任库用于验证其他节点的证书。自签名证书场景下通常和keystore是同一个文件。 xpack.security.transport.ssl.truststore.path: /path/to/elastic-certificates.p12 xpack.security.transport.ssl.truststore.password: xpack.security.transport.ssl.truststore.type: PKCS12 # 如果使用私有CA且keystore只包含节点证书truststore只包含CA证书则配置如下 # xpack.security.transport.ssl.keystore.path: /path/to/es-node-01.p12 # xpack.security.transport.ssl.truststore.path: /path/to/truststore.jks # 一个包含ca.crt的JKS文件 # xpack.security.transport.ssl.truststore.password: TruststorePass # ---------- 可选HTTP层加密 (REST API TLS) ---------- # 如果你希望通过HTTPS访问Elasticsearch的9200端口也需要启用这个。 # 通常Kibana和ES在同一内网可以不用。但若ES API需对外则必须启用。 xpack.security.http.ssl.enabled: true xpack.security.http.ssl.keystore.path: /path/to/http-certificates.p12 # ... 其他类似配置实操心得配置变更后不要同时重启所有节点应该逐个节点滚动重启。先重启一个节点等它成功加入集群日志显示cluster health status changed from [RED] to [YELLOW]再到[GREEN]后再重启下一个。同时重启所有节点可能导致它们因无法建立安全连接而各自形成孤岛。3.3 第三阶段初始化内置用户密码当所有节点都配置好并重启成功后集群的安全功能已启用但默认的内置用户如elastic,kibana_system,logstash_system等还没有密码。我们需要在一个节点上初始化这些密码。# 进入任一Elasticsearch节点的bin目录 cd /usr/share/elasticsearch/bin # 使用交互模式设置密码会提示你为每个内置用户输入密码 ./elasticsearch-setup-passwords interactive # 或者使用自动生成随机密码的模式务必保存好输出的密码 ./elasticsearch-setup-passwords autointeractive模式更安全你可以设置自己熟悉的强密码。auto模式会生成随机密码你必须立即妥善保存输出结果。其中elastic是超级用户kibana_system是Kibana连接ES用的服务账号。完成这一步后你的Elasticsearch集群就已经处于加密和密码保护状态了。尝试用curl访问一下# 未认证的请求会被拒绝 curl https://localhost:9200 # 使用elastic用户认证 curl -u elastic:YourPassword https://localhost:92004. 配置Kibana连接安全集群并启用登录Elasticsearch安全了Kibana也需要相应调整才能连接上它。4.1 修改Kibana配置编辑kibana.yml配置文件关键修改如下# Kibana服务端口 server.port: 5601 server.host: 0.0.0.0 # 按需修改 # 指向安全的Elasticsearch集群 elasticsearch.hosts: [https://es-node-01:9200, https://es-node-02:9200] # 配置连接Elasticsearch的用户名和密码使用kibana_system用户 elasticsearch.username: kibana_system elasticsearch.password: YourKibanaSystemPassword # 上一步设置的密码 # 如果Elasticsearch的HTTP层启用了TLS即配置了xpack.security.http.ssl这里必须对应 elasticsearch.ssl.verificationMode: certificate # 与ES配置匹配生产建议用full # 如果ES使用的是私有CA签发的证书Kibana需要信任该CA # elasticsearch.ssl.certificateAuthorities: [ /path/to/ca.crt ] # 启用Kibana自身的登录界面 xpack.security.enabled: true4.2 启动Kibana并验证启动Kibana服务systemctl start kibana # 或使用 ./bin/kibana访问http://your-kibana-host:5601现在你会看到一个登录界面。使用elastic超级用户和其密码登录。如果成功进入说明Kibana到Elasticsearch的安全连接已配置正确。5. Kibana RBAC精细权限配置实战登录成功后作为管理员我们的核心任务就是创建角色和用户实现权限隔离。Kibana的权限管理主要在Stack Management Security下进行。5.1 理解内置角色与权限Elasticsearch自带一系列内置角色如superuser,kibana_admin,kibana_user,logstash_admin,beats_admin等。kibana_user是一个基础角色允许用户登录Kibana并使用其功能但不包含任何索引数据权限。我们通常需要创建自定义角色来组合索引权限和Kibana功能权限。5.2 场景为运维和开发团队配置权限假设我们有两个索引infra-logs-*基础设施日志由运维团队管理。app-logs-*应用业务日志由开发团队查看。目标创建ops_team和dev_team两个角色并分别分配给运维和开发人员。步骤1创建自定义角色ops_team_role进入Stack Management Security Roles。点击Create role。Cluster Privileges集群权限对于普通查看者这里通常留空。如果运维需要监控集群状态可以赋予monitor或viewer权限。切勿随意赋予all或manage权限。Index Privileges索引权限这是核心。在Indices输入框中填入infra-logs-*。使用通配符可以匹配未来创建的符合模式的索引。在Privileges下拉框中选择read可读、view_index_metadata可查看索引元信息。如果运维人员需要清理或管理这些索引可以额外添加delete_index,create_index,manage等权限但需谨慎。Kibana PrivilegesKibana权限在Spaces中选择Default默认空间。在Privileges中至少选择All下的read。这允许用户访问Kibana功能。如果需要他们创建仪表板可以赋予All下的all权限但更细粒度的做法是单独赋予Dashboard下的all权限。点击Create role。步骤2创建自定义角色dev_team_role重复上述步骤但在Index Privileges中将索引模式改为app-logs-*权限同样设置为read和view_index_metadata。Kibana权限根据开发团队需求设定。步骤3创建对应用户并分配角色进入Stack Management Security Users。点击Create user。填写用户名如zhangsan_ops、全名、邮箱和密码。在Roles部分至少分配两个角色我们刚创建的自定义角色ops_team_role。内置的基础角色kibana_user。这是关键没有这个角色用户即使有数据权限也无法登录Kibana界面。点击Create user。用同样的方法创建开发用户lisi_dev为其分配dev_team_role和kibana_user角色。5.3 使用Kibana Spaces进行物理隔离上述基于索引的权限控制是逻辑隔离。Kibana Spaces提供了更强的物理隔离。你可以为不同团队创建不同的Space如ops-space,dev-space在每个Space里独立配置仪表板、可视化、索引模式等。然后通过角色控制用户能访问哪些Space。进入Stack Management Kibana Spaces。创建Spaceops-space关联索引模式infra-logs-*。创建Spacedev-space关联索引模式app-logs-*。修改角色权限在角色的Kibana Privileges中不再选择Defaultspace而是分别指定ops-space或dev-space并赋予相应权限如read或all。这样zhangsan_ops登录后通过页面左上角的空间切换器只能看到并进入ops-space完全感知不到dev-space的存在实现了完美的租户隔离。6. 常见问题、故障排查与进阶技巧在实际操作中你几乎一定会遇到下面这些问题。我把它们和解决方案整理成了速查表。6.1 集群启动与加密相关故障问题现象可能原因排查步骤与解决方案节点启动失败报错SSLHandshakeException或failed to bind service1. 证书路径或密码错误。2. 证书格式不正确。3. 防火墙阻止了节点间9300端口通信。4.verification_mode配置不一致。1. 检查elasticsearch.yml中keystore.path和truststore.path的路径和文件名是否正确权限是否为600。2. 使用keytool -list -v -keystore file.p12 -storepass pass验证证书库是否能正常打开。3. 使用telnet或nc命令测试节点间9300端口连通性。4. 确保所有节点的xpack.security.transport.ssl.verification_mode值相同。测试环境可先用certificate。节点无法加入集群日志显示master not discovered1. 第一个启动的节点masterTLS配置错误其他节点无法与其建立安全连接。2. 集群名称(cluster.name)不一致。3. 网络发现配置如discovery.seed_hosts未包含正确的主机名和端口。1.滚动重启先确保一个节点最好是原master以安全模式正常启动。查看其日志确认传输地址如[192.168.1.10:9300]。2. 核对所有节点的cluster.name。3. 在其他节点的discovery.seed_hosts中使用安全传输地址即master节点日志中打印的地址。例如discovery.seed_hosts: [es-node-01:9300, es-node-02:9300]。Kibana启动失败报错[statusCode401]1.kibana_system用户密码错误。2.kibana_system用户角色权限不足。1. 用curl -u elastic命令验证kibana_system用户的密码curl -u kibana_system:YourPassword https://localhost:9200。2.kibana_system用户需要kibana_system内置角色该角色在密码初始化时已自动关联。可通过ES API检查GET /_security/user/kibana_system。6.2 RBAC权限配置不生效问题现象可能原因排查步骤与解决方案用户登录Kibana后看不到数据1. 自定义角色未分配索引权限。2. 索引模式拼写错误或用户无权访问该索引模式关联的索引。3. 用户缺少kibana_user角色。1. 在Roles页面检查该角色的Index Privileges确认索引模式是否正确是否包含read权限。2. 让用户尝试在Kibana的Discover中直接输入索引名如infra-logs-2024.06看能否查询。这可以排除索引模式问题。3.务必确保用户同时拥有kibana_user角色。用户无法在Kibana中创建/保存仪表板1. 角色在对应Kibana Space或Default Space的权限不足。2. 索引权限只有read没有create_index或index权限保存对象到.kibana索引需要。1. 检查角色在Kibana Privileges中对目标Space是否赋予了All下的all权限或至少Dashboard和Visualization下的all权限。2. Kibana会将仪表板等对象存储在以.kibana开头的索引中。确保角色对该索引模式如.kibana_*有read,write,create_index权限。一个简单的方法是赋予kibana_admin角色但这会赋予过多权限。更安全的是创建专门管理Kibana对象的角色。权限变更后用户需要重新登录才生效这是预期行为。Elasticsearch的安全令牌Token有缓存时间。告知用户退出Kibana重新登录即可使新权限生效。6.3 性能与运维进阶技巧启用HTTP层TLS的取舍启用xpack.security.http.ssl会增加REST API调用的开销。如果Kibana和ES部署在同一私有网络且没有其他客户端直接调用9200端口可以暂时不启用以简化配置和提升少许性能。但任何跨网络或公网的访问都必须启用。使用Service Token代替密码对于程序如Logstash、Filebeat、自定义应用连接ES使用用户名密码硬编码在配置文件中不安全。可以创建Service Account并生成Service Token这是一个长时效的Bearer Token更安全。# 创建服务账号令牌 POST /_security/service/elastic/kibana/credential/token在配置文件中使用elasticsearch.api_key: base64encoded_token。定期轮转证书自签名或私有CA证书都有有效期。建立证书到期监控和轮转流程。对于私有CA可以使用类似cert-manager的工具自动化管理。审计日志分析启用审计日志(xpack.security.audit.enabled: true)并定期将审计索引如.security-audit-log-*导入SIEM或日志平台进行分析可以及时发现异常访问行为。权限最小化原则创建角色时始终坚持“最小必要权限”原则。先给read确实需要写权限时再添加write。避免直接使用all或*这样的通配符权限。这次从零到一构建安全Elastic Stack集群的过程让我再次深刻体会到安全不是一蹴而就的功能开关而是一个贯穿设计、实施和运维的持续过程。尤其是RBAC的配置前期多花半小时思考清楚权限模型后期能省去无数“为什么我看不到数据”的运维工单。最后一个小建议所有安全相关的配置变更一定要在测试环境充分验证并准备好回滚方案毕竟重启一个生产ES集群可不是闹着玩的。