Elasticsearch 7.x 集群安全加固:从零构建企业级认证体系

在数据驱动的今天,Elasticsearch 集群承载着企业搜索、日志分析、业务监控等核心任务。一个未受保护的集群,无异于将公司数据资产暴露在公共网络之中。我见过太多因为疏忽安全配置而导致的数据泄露案例,其中不乏一些知名企业。对于中高级运维和架构师而言,仅仅搭建起集群只是第一步,为其构筑坚实的安全防线才是真正的挑战。

Elasticsearch 在 6.8 版本之后,将 X-Pack 的基础安全功能(包括 TLS 加密和用户名/密码认证)纳入了免费分发版中,这为我们构建安全的集群环境提供了官方、标准化的工具。然而,官方文档往往侧重于功能说明,而实际生产环境的部署涉及证书管理、多节点同步、权限细化、客户端适配等一系列复杂且容易出错的环节。本文将从一个实战者的视角,系统性地拆解 Elasticsearch 7.x 集群安全认证的完整流程,不仅告诉你每一步怎么做,更会深入解释其背后的原理和可能遇到的“坑”,目标是让你能构建一套健壮、可维护的企业级安全认证体系。

1. 安全架构核心:理解 TLS 与用户认证的协同

在动手修改配置文件之前,我们必须先厘清 Elasticsearch 安全功能的两大基石:传输层加密(TLS/SSL)用户身份认证与授权。很多人误以为只要设置了密码就安全了,其实不然。

传输层安全(TLS) 用于加密集群节点之间的内部通信。想象一下,你的节点分布在不同的服务器甚至不同的机房,它们之间频繁交换数据、同步状态。如果没有加密,这些网络流量可能被窃听或篡改。TLS 通过证书来验证节点身份,确保只有持有合法证书的节点才能加入集群,同时加密所有通信内容。

用户认证 则控制着谁可以访问集群的 REST API(包括 Kibana、Logstash、Beats 以及各类客户端 SDK)。它就像集群的大门守卫,验证每一个来访者的身份(用户名/密码、令牌、证书等)。

关键点:在 Elasticsearch 的安全模型中,启用用户认证通常要求先启用传输层 TLS。这是因为用户凭证等信息需要在节点间安全地同步。如果传输层不加密,密码哈希等敏感信息在节点间传输时也存在风险。因此,我们的配置顺序总是“先证书,后密码”。

那么,我们需要生成哪些证书?这里涉及两个概念:

  • CA(证书颁发机构)证书:用于签署和验证其他证书的根证书。在自签名场景下,我们通常自己充当 CA。
  • 节点证书:由 CA 签发,分配给每个 Elasticsearch 节点的证书,包含节点的身份信息(如主机名、IP)和公钥。

在接下来的实战中,我们将使用 Elasticsearch 自带的 elasticsearch-certutil 工具,一次性生成一个包含 CA 和节点证书的 PKCS#12 文件(.p12),这种方式对于中小规模集群来说最为简便。

2. 实战部署:逐步配置安全集群

假设我们有一个三节点的 Elasticsearch 7.17.x 集群,节点名称分别为 es-node-1, es-node-2, es-node-3,已完成了基础的集群搭建。现在,我们开始为其穿上“盔甲”。

2.1 第一步:统一修改集群配置文件

安全配置需要应用到集群中的每一个节点。首先,我们需要编辑每个节点 config 目录下的 elasticsearch.yml 文件。以下是需要追加的核心安全配置项及其解释:

# 启用 X-Pack 安全功能(包括认证和授权)
xpack.security.enabled: true

# 设置许可证类型为 basic(免费版),以解锁基础安全功能
xpack.license.self_generated.type: basic

# 启用传输网络层(节点间通信)的 TLS/SSL 加密
xpack.security.transport.ssl.enabled: true

# 设置证书验证模式为 `certificate`,即验证证书本身的有效性,而不强制验证主机名。
# 这在内部网络或使用IP地址时很常用。生产环境若使用DNS,可考虑更严格的 `full` 验证。
xpack.security.transport.ssl.verification_mode: certificate

# 指定包含节点证书和私钥的密钥库文件路径(相对于ES配置目录或绝对路径)
xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12
# 指定信任库文件路径,用于信任其他节点的证书。在自签名且使用相同CA的场景下,通常与密钥库是同一个文件。
xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12

操作建议

  1. 我习惯在 config 目录下创建一个 certs 子目录来专门存放证书文件,这样更整洁。因此上面的路径是 certs/elastic-certificates.p12。你需要确保这个路径在所有节点上一致。
  2. 使用配置管理工具(如 Ansible、SaltStack)或编写一个简单的同步脚本,将这段配置一次性推送到所有节点的 elasticsearch.yml 中,避免手动修改出错。

2.2 第二步:生成与分发 TLS 证书

证书只需在一个节点上生成,然后安全地分发到其他所有节点。

  1. 生成证书:在 es-node-1 上执行以下命令。-pass "" 表示不设置密钥库密码(生产环境建议设置强密码)。

    # 切换到 Elasticsearch 安装目录
    cd /usr/share/elasticsearch
    # 使用 certutil 工具生成证书
    ./bin/elasticsearch-certutil cert -out config/certs/elastic-certificates.p12 -pass ""
    

    命令执行后,你会在 config/certs/ 目录下看到生成的 elastic-certificates.p12 文件。这个文件包含了 CA 证书和节点证书。

  2. 分发证书:将生成的 .p12 文件安全地拷贝到其他所有节点的相同路径下。可以使用 scprsync

    # 从 node-1 拷贝到 node-2 和 node-3
    scp config/certs/elastic-certificates.p12 es-user@es-node-2:/usr/share/elasticsearch/config/certs/
    scp config/certs/elastic-certificates.p12 es-user@es-node-3:/usr/share/elasticsearch/config/certs/
    

    重要安全提醒:确保证书文件的权限设置正确,仅允许 Elasticsearch 进程用户读取。例如:

    chown elasticsearch:elasticsearch config/certs/elastic-certificates.p12
    chmod 600 config/certs/elastic-certificates.p12
    
  3. 关于证书的进阶考量

    • 多证书 vs 单证书:上述方法为所有节点生成了一个通用的证书。对于更高安全要求的环境,可以为每个节点生成唯一证书(使用 -multiple 参数),并在配置中指定各自的证书路径。
    • 使用已有 CA:如果公司已有内部 CA,可以使用 -ca-ca-key 参数指定你的 CA 证书和私钥来签发节点证书。
    • PEM 格式:某些外部工具或监控系统可能需要 PEM 格式的证书。可以使用 -pem 参数生成包含独立 .crt.key 文件的 ZIP 包。

2.3 第三步:重启集群并初始化用户密码

在证书分发完成后,需要逐个重启集群节点以加载新的安全配置。建议先重启所有从节点(node-2, node-3),最后重启主节点(node-1),以最小化服务中断时间。

所有节点重启并成功加入集群后,就可以设置内置用户的密码了。在任意一个节点上执行以下命令:

cd /usr/share/elasticsearch
./bin/elasticsearch-setup-passwords interactive

你会进入一个交互式命令行界面,系统会提示你为一系列内置用户设置密码:

用户名用途说明
elastic超级管理员账户,拥有所有权限。这是你管理集群的主要账户。
kibana_systemKibana 服务用于连接 Elasticsearch 和存储内部数据的系统账户。
logstash_systemLogstash 用于向 Elasticsearch 推送数据的系统账户。
beats_systemBeats 家族(Filebeat, Metricbeat等)使用的系统账户。
apm_systemAPM 服务器使用的系统账户。
remote_monitoring_user用于 Elastic Stack 监控功能收集数据的用户。

交互式 vs 自动生成interactive 模式让你为每个用户设置自定义密码。如果你希望快速生成随机密码,可以使用 auto 参数:./bin/elasticsearch-setup-passwords auto。系统会生成强随机密码并打印在屏幕上,务必立即保存

密码设置完成后,会立即生效并同步到整个集群。现在,任何未经认证的访问都将被拒绝。

3. 验证与访问:确保一切就绪

配置完成后,必须进行全面的验证,确保安全功能生效且不影响正常服务。

基础验证:尝试进行未认证的 API 调用,应该收到 401 Unauthorized 错误。

curl -X GET "http://es-node-1:9200/"

预期返回:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "security_exception",
        "reason" : "missing authentication credentials for REST request [/]",
        "header" : {
          "WWW-Authenticate" : "Basic realm=\"security\" charset=\"UTF-8\""
        }
      }
    ],
    "type" : "security_exception",
    "reason" : "missing authentication credentials for REST request [/]",
    ...,
    "status" : 401
  }
}

认证访问:使用 elastic 用户和设置的密码进行访问。

# 方式一:在命令中直接提供密码(密码会出现在进程列表,不推荐用于生产脚本)
curl -u elastic:YourStrongPassword123! -X GET "http://es-node-1:9200/"

# 方式二(推荐):命令提示输入密码,更安全
curl -u elastic -X GET "http://es-node-1:9200/"

输入密码后,你应该能看到熟悉的集群健康信息,这证明认证成功。

集群健康检查:进一步检查集群状态和节点通信。

curl -s -u elastic:YourStrongPassword123! "http://es-node-1:9200/_cluster/health?pretty"
curl -s -u elastic:YourStrongPassword123! "http://es-node-1:9200/_cat/nodes?v"

确保所有节点状态都是 greenyellow,并且都能在节点列表中看到。

4. 集成与进阶:连接你的生态系统

安全集群配置好后,所有与之交互的客户端都必须更新配置以提供凭证。

Kibana 配置:编辑 Kibana 的 kibana.yml 文件,添加 Elasticsearch 的认证信息。

elasticsearch.username: "kibana_system"
elasticsearch.password: "YourKibanaSystemPassword"

重启 Kibana 后,登录界面将出现。你需要使用 elastic 用户或其他你创建并赋予了 kibana_user 角色的用户登录。

Logstash 配置:在 Logstash 的输出插件配置中增加认证信息。

output {
  elasticsearch {
    hosts => ["http://es-node-1:9200", "http://es-node-2:9200"]
    user => "logstash_system"
    password => "YourLogstashSystemPassword"
    # 如果启用了HTTPS,还需要配置 ssl_certificate_verification 和 cacert
  }
}

Beats 配置:以 Filebeat 为例,在 filebeat.yml 中配置:

output.elasticsearch:
  hosts: ["http://es-node-1:9200"]
  username: "beats_system"
  password: "YourBeatsSystemPassword"

编程客户端(以 Python 为例)

from elasticsearch import Elasticsearch

es = Elasticsearch(
    ['http://es-node-1:9200'],
    http_auth=('elastic', 'YourStrongPassword123!')
)
# 或者使用 API Key、SSL 证书等其他认证方式

权限管理:内置用户权限是固定的。对于业务应用,最佳实践是创建专属的用户和角色。例如,为一个只需要读取特定索引的监控应用创建角色和用户:

  1. 通过 Kibana 的 Security 功能或 Elasticsearch 的 _security API 创建一个新角色 monitor_read_only,为其分配对特定索引(如 app-logs-*)的 readview_index_metadata 权限。
  2. 创建一个新用户 app_monitor,将其映射到 monitor_read_only 角色。
  3. 在监控应用中使用 app_monitor 的凭证,实现权限最小化原则。

5. 故障排查与日常维护指南

即使按照步骤操作,也可能会遇到问题。以下是一些常见故障及排查思路:

  • 节点无法加入集群:检查所有节点的 elasticsearch.yml 中 TLS 相关配置路径是否完全一致,证书文件是否已分发且权限正确。查看节点日志(logs/elasticsearch.log),通常会有明确的错误信息,如 SSLHandshakeExceptionfailed to authenticate
  • 密码设置失败:确保在执行 elasticsearch-setup-passwords 命令前,所有节点都已重启并成功运行。该命令需要与一个已启用安全功能的集群进行通信。
  • 客户端连接失败:确认客户端使用的协议(HTTP/HTTPS)、端口、用户名和密码完全正确。对于编程客户端,注意库的版本是否与 Elasticsearch 7.x 兼容。开启客户端的调试日志往往是快速定位问题的方法。
  • 性能影响:启用 TLS 加密和认证会带来轻微的性能开销,主要体现在 CPU 计算上。对于绝大多数应用,这种开销是可接受的。如果遇到性能瓶颈,可以考虑使用更高效的加密套件,或者确保使用的是原生 SSL 库(如 OpenSSL)。

在维护方面,建议:

  1. 定期轮转证书:虽然自签名证书没有过期问题,但定期更新(如每年一次)是良好的安全习惯。轮转时,采用滚动重启节点的方式,逐个更新证书和配置,避免集群中断。
  2. 密码管理:将内置系统用户(如 kibana_system, logstash_system)的密码存储在安全的密码管理器中或使用密钥管理服务。避免在配置文件中以明文形式硬编码。
  3. 审计日志:启用 X-Pack 的审计日志功能,记录所有的认证成功/失败事件和特权操作,便于事后追溯和安全分析。
  4. 网络层加固:不要仅仅依赖应用层认证。结合防火墙规则,严格限制可以访问 Elasticsearch 端口(9200, 9300)的源 IP 地址。

安全是一个持续的过程,而非一次性的配置。为 Elasticsearch 集群启用认证和加密,是构建可信数据平台不可或缺的第一步。这套基于证书和密码的机制,为后续引入更复杂的认证方式(如 LDAP、SAML、OIDC)或细粒度的基于角色的访问控制(RBAC)奠定了坚实的基础。在实际操作中,最深的体会是“细节决定成败”——一个错误的文件权限、一处配置的拼写错误,都可能导致整个集群无法启动或节点间失联。因此,在预发布环境中进行充分的测试,并形成可重复、可回滚的自动化部署脚本,是保障生产环境平稳上线的关键。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐