Elasticsearch 默认不设访问门槛,裸奔的 9200 端口等于把数据交给互联网。启用安全功能后,需要用户认证、角色授权、传输加密与审计四层配合。本文从用户与角色讲到 TLS 与审计日志,最后给出一份可直接对照的生产安全配置清单。
1. 安全特性概览
一句话总结: ES 安全由认证、授权、加密、审计四层构成,缺一层都不是完整的安全闭环。
1.1 四层安全模型
| 层 | 功能 | 关键组件 |
|---|---|---|
| 认证 | 确认访问者身份 | native realm、LDAP/AD |
| 授权 | 决定能做什么 | 角色、集群/索引权限 |
| 加密 | 保护传输数据 | TLS、CA、证书 |
| 审计 | 记录访问痕迹 | audit log |
ES 8 默认开启安全功能:内置 elastic 超级用户、TLS 自动配置、Kibana 安全接入。ES 7 及以下需要手动在 elasticsearch.yml 打开 xpack.security.enabled,并逐节点配置证书。
1.2 安全组件的边界
REST 请求先过认证层校验令牌与密码,再过授权层检查角色权限,传输层用 TLS 防止抓包,审计层把敏感操作落盘。业务访问走 Kibana 或 API 时各自携带凭证,所有节点共用同一套 realm 与角色配置。
1.3 常见风险面
未启用安全的集群被公网扫描即被脱库;弱密码的 elastic 账号被爆破;证书过期导致集群间通信失败。安全不是一次配置,而是证书轮换、口令周期、审计核查的持续运维。
2. 用户与认证
一句话总结: 认证确认「你是谁」,native realm 是内置的用户库,也支持对接企业目录。
2.1 内置用户
bin/elasticsearch-users useradd app_reader -p 'Str0ng#Pass' -r read
bin/elasticsearch-users list
bin/elasticsearch-users userdel app_reader
内置 realm 通过 elasticsearch-users 命令管理本地用户。生产上推荐在 Kibana Stack Management 的 Security 页面创建用户并绑定角色,密码用强口令且定期轮换,禁用裸口令出现在配置文件中。
2.2 认证 Realm 顺序
xpack.security.authc.realms:
native:
native1: { order: 0 }
ldap:
ldap1:
order: 1
url: "ldap://ldap.example.com:389"
bind_dn: "cn=es-svc,ou=apps,dc=example,dc=com"
native realm 放本地用户,ldap/active_directory realm 对接企业账号体系。realm 按 order 依次尝试认证,企业已有目录时优先对接 LDAP,本地账号只留运维应急通道。Kibana 登录界面可选择 realm 让员工用企业账号登录。
2.3 服务账号与令牌
{
"name": "logstash-writer"
}
POST /_security/service/logstash-writer/credential/token
写入型应用(Logstash、Filebeat、Beats)用服务账号 + 令牌认证,令牌可定期轮换,比把密码写进配置文件安全。ES 8 的 API Key 也可用于 REST 调用,api_key 比用户名密码更适合程序调用,支持按过期时间自动失效。
3. 角色与权限
一句话总结: 授权回答「你能做什么」,角色把集群权限与索引权限组合成可复用的最小授权单元。
3.1 内置角色
| 角色 | 权限范围 |
|---|---|
| superuser | 全部操作 |
| kibana_admin | Kibana 管理 |
| logstash_system | Logstash 系统通信 |
| beats_system | Beats 系统通信 |
| viewer | Kibana 只读 |
内置角色覆盖常见场景,但生产上必须自定义业务角色,遵循最小权限:只给需要的索引、只给需要的操作,绝不给超级用户。
3.2 创建自定义角色
{
"role": {
"name": "app_ops",
"cluster": ["monitor"],
"indices": [
{
"names": ["app-logs-*"],
"privileges": ["read", "view_index_metadata"]
},
{
"names": ["app-logs-write"],
"privileges": ["write", "create_index"]
}
],
"run_as": []
}
}
自定义角色用 PUT _security/role 创建:cluster 权限控制集群级操作(monitor/ manage /manage_index_templates),indices 按索引模式授权读写。app_ops 只读 app-logs-* 元数据、可写 app-logs-write 别名,即运维查看 + 程序写入的组合。
3.3 索引权限细分
{
"role": {
"name": "app_reader",
"indices": [
{
"names": ["app-logs-*"],
"privileges": ["read", "read_cross_cluster"],
"allow_restricted_indices": false
}
]
}
}
索引权限包括 read、write、delete、manage、view_index_metadata 等。read 细分为 read(检索+聚合)、read_cross_cluster(跨集群读)、monitor。allow_restricted_indices 控制能否访问 .security 等受限系统索引,普通角色必须为 false。
4. 字段级与文档级安全
一句话总结: FLS 隐藏敏感字段、DLS 过滤敏感文档,把行与列的权限细分到角色粒度。
4.1 字段级安全(FLS)
{
"role": {
"name": "ops_viewer",
"indices": [
{
"names": ["orders"],
"privileges": ["read"],
"field_security": {
"grant": ["order_id", "amount", "status", "create_time"],
"except": []
}
}
]
}
}
field_security 用 grant 白名单或 except 黑名单控制可见字段。ops_viewer 只能看到订单基础字段,无法读取手机号、身份证等敏感列。FLS 在查询与 _source 两个层面都生效,排序与聚合的字段也要在授权内。
4.2 文档级安全(DLS)
{
"role": {
"name": "region_manager",
"indices": [
{
"names": ["orders"],
"privileges": ["read"],
"query": {
"term": { "region": "east" }
}
}
]
}
}
DLS 用 query 定义角色可见的文档范围:region_manager 只能看到 region 为 east 的订单。DLS 把过滤条件注入每次查询,用户无法通过构造查询绕过,实现「按租户/按区域隔离数据」。
4.3 FLS 与 DLS 的配合
敏感字段多字段组合:FLS 挡列、DLS 挡行,两者可同时启用。注意 FLS 对 _source 的裁剪不改变字段值本身,授权外的字段在响应中被移除。Kibana 的 Space 与角色绑定后,不同团队看到不同的索引与字段,实现多租户隔离。
5. TLS 传输加密
一句话总结: TLS 加密节点间与客户端链路,证书由 CA 签发并纳入信任链,防止传输抓包。
5.1 节点间 TLS 配置
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-truststore.p12
transport 层是节点间内部通信,开启 TLS 后每个节点持证书与信任库。verification_mode 设为 certificate 校验证书有效性;hostname 模式还会校验主机名,更严格但需确保证书 SAN 覆盖节点名。
5.2 HTTP 客户端加密
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: http.p12
xpack.security.http.ssl.redirect: true
http 层加密客户端到节点的链路,Kibana、Logstash 与业务客户端都改用 https 访问。redirect 让明文请求自动跳转 https。证书由内部 CA 签发,所有客户端与 Kibana 需信任该 CA,自签证书要导入信任库,否则 curl 报证书错误。
5.3 证书生成与轮换
bin/elasticsearch-certutil cert --pem --ca certs/ca.p12
bin/elasticsearch-certutil http
certutil 生成 CA 与节点证书;http 子命令交互式生成节点 HTTP 证书。证书有有效期(默认 5 年),到期前要轮换:先签发新证书、分发到节点、热加载生效,再停用旧证书。证书过期是集群通信故障的高频原因,纳入监控日历。
6. 审计日志
一句话总结: 审计日志记录谁在何时做了什么,是合规与事后追溯的依据。
6.1 审计配置
xpack.security.audit.enabled: true
xpack.security.audit.logfile.events.include:
- access_denied
- authentication_success
- authentication_failure
- connection_denied
- run_as_denied
审计日志默认写审计文件,include 列表控制记录事件类型。生产建议记录认证成功/失败、访问拒绝、授权变化,放弃记录全部请求(日志量巨大)。审计日志写入独立文件或专用索引,防止与应用日志混杂。
6.2 审计事件查看
[audit] user=app_reader action=access_denied indices=[app-secret-*] reason=indices:data/read/search is unauthorized
审计行包含主体(user)、动作(access_denied)、对象(索引)与原因,排查越权与异常访问直接检索审计日志。认证失败暴增、非工作时间访问、对敏感索引的访问是审计核查的重点。
6.3 审计与合规
审计日志是等保与 SOC2 的必备材料,需保留足够周期并防篡改。可将审计日志同步到外部 SIEM(如 Elastic Security 自身),对认证失败风暴、异常权限变更配置告警。审计记录不可由被审计用户自己关闭。
7. 安全配置清单
一句话总结: 一份可对照的生产安全清单,把认证、授权、加密、审计逐项落到位。
7.1 集群层面清单
| 检查项 | 要求 |
|---|---|
| xpack.security.enabled | 开启 |
| elastic 超级用户密码 | 强口令并轮换 |
| transport TLS | 开启并校验证书 |
| http TLS | 开启并配置 CA |
| 内置账号密码 | 全部修改默认值 |
| 公网暴露 | 9200 不暴露公网 |
7.2 应用与运维清单
| 检查项 | 要求 |
|---|---|
| 最小权限角色 | 每个业务一个角色 |
| 服务账号 | Logstash/Filebeat 用令牌 |
| FLS/DLS | 敏感数据逐角色配置 |
| 审计日志 | 开启并外送 SIEM |
| 证书轮换 | 纳入日历与监控 |
| 配置密钥 | 密码不进配置文件 |
清单逐项落地后做一次安全自测:用普通账号尝试读敏感索引、尝试跨区域查询、抓包确认 TLS 生效,把「以为安全」变成「验证过安全」。
8. 总结
一句话总结: 安全加固以认证、授权、加密、审计四层闭环,用户角色最小授权、TLS 加密传输、审计日志可追溯,用清单逐项落地。
| 环节 | 要点 |
|---|---|
| 安全模型 | 认证、授权、加密、审计四层 |
| 认证 | native realm 本地、LDAP 对接企业、令牌给服务 |
| 授权 | 角色组合集群与索引权限,最小授权 |
| 行/列安全 | FLS 挡字段、DLS 挡文档 |
| 传输加密 | transport 与 http 双 TLS,证书轮换 |
| 审计 | 记录认证与拒绝事件,外送 SIEM |
| 清单 | 逐项对照、默认密码全改 |
| 红线 | 9200 不暴露公网、不给超管、证书不裸奔 |
安全加固是搜索服务上线的前置条件:先建用户与角色,再开 TLS 与审计,最后用清单自查。权限设计遵循最小授权,加密覆盖传输全链路,审计日志让每一次访问可追溯。集群运维相关可阅读《部署运维与备份恢复》《集群分片与高可用架构》,数据字段设计参考《数据建模与 Mapping 设计》。
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。