这是《Elasticsearch 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Elasticsearch 常常保存搜索数据、日志、用户行为和业务分析结果,其中日志字段可能包含手机号、IP、请求头、授权 token,甚至数据库连接串。安全不是上线后补一项开关,而是从网络、传输、认证、授权、审计和数据分级六个层面同时治理。
31.1 安全边界
一个生产集群至少要明确:
谁能访问集群?
-> TLS / VPN / 网络边界
谁能调用 API?
-> 认证
能访问哪些索引?
-> index privileges
能看到哪些文档?
-> document level security
能看到哪些字段?
-> field level security
做过什么操作?
-> audit logging
数据保留多久?
-> ILM / snapshot / compliance
常见风险:
| 风险 | 后果 |
|---|---|
| 集群裸奔公网 | 全量读写、删除索引 |
| 共享超级用户 | 无法定位误操作人 |
| 日志字段全量开放 | 泄露 token、手机号、IP |
| 客户端明文传输 | 凭据和数据被窃听 |
| 任意 Dashboard 查询 | 一个大聚合拖垮集群 |
| 快照桶权限过宽 | 绕过 ES 权限读数据 |
| API key 不轮换 | 长期凭据泄露 |
31.2 传输加密 TLS
生产环境应启用:
- HTTP layer TLS:客户端到节点;
- Transport layer TLS:节点之间;
- Kibana 到 Elasticsearch TLS;
- 采集器到 Elasticsearch TLS;
- 证书有效期和轮换机制。
Elasticsearch 8.x 默认更强调安全,生产应使用受信任 CA 签发证书,而不是长期使用自动生成证书。
elasticsearch.yml 示例:
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: full
xpack.security.transport.ssl.keystore.path: certs/es01.p12
xpack.security.transport.ssl.truststore.path: certs/truststore.p12
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: certs/http.p12
xpack.security.http.ssl.truststore.path: certs/truststore.p12
把密码放入 keystore:
bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password
验证:
curl -vk https://localhost:9200
不要关闭主机名或节点证书校验。verification_mode: none 只适合临时排障,且必须在工单中记录恢复时间。
31.3 认证
常见认证方式:
| 方式 | 适合 | 注意 |
|---|---|---|
| 内置用户 | 运维和初始化 | 不用于应用共享 |
| LDAP / Active Directory | 企业统一账号 | 组映射要简洁 |
| SAML / OIDC | Kibana 登录 | 区分用户和机器 |
| API key | 服务集成 | scope、过期、轮换 |
| 服务账号 | 应用写入 | 最小索引权限 |
创建本地用户:
POST /_security/user/search_app
{
"password": "change-me",
"roles": ["products_writer"],
"full_name": "Search Application"
}
修改密码:
PUT /_security/user/search_app/_password
{
"password": "new-password"
}
生产应用更推荐使用配置中心托管的密码或 API key,并定期轮换。
31.4 API Key
API Key 适合服务与服务之间的认证。
POST /_security/api_key
{
"name": "search-app-prod",
"expiration": "30d",
"role_descriptors": {
"products_writer": {
"cluster": ["monitor"],
"indices": [
{
"names": ["products-v3", "products-write"],
"privileges": ["create_index", "write", "read"]
}
]
}
}
}
返回:
{
"id": "api_key_id",
"encoded": "base64_api_key"
}
查询:
GET /_security/api_key?name=search-app-prod
POST /_security/_query_api_key
{
"query": {
"term": { "name": "search-app-prod" }
}
}
失效:
DELETE /_security/api_key
{
"id": "api_key_id"
}
治理要求:
- 设置过期时间;
- 限制 index 和 cluster 权限;
- 不使用超级用户给应用;
- key 泄露立即 invalidate;
- 定期盘点;
- 环境之间不复用。
31.5 角色与索引权限
创建角色:
POST /_security/role/products_writer
{
"cluster": ["monitor"],
"indices": [
{
"names": ["products-v3"],
"privileges": ["write", "create_index", "view_index_metadata"]
}
]
}
只读角色:
POST /_security/role/products_reader
{
"cluster": ["monitor"],
"indices": [
{
"names": ["products-read"],
"privileges": ["read"]
}
]
}
常用权限:
| 权限 | 说明 |
|---|---|
| read | 搜索和读取文档 |
| write | 写入文档 |
| create_index | 创建索引 |
| delete_index | 删除索引 |
| manage | 管理索引 |
| view_index_metadata | 查看 Mapping、settings |
| monitor | 查看监控 |
| manage_index_templates | 管理模板 |
应用账号不应拥有:
all;manage;delete_index;manage_index_templates; -集群级变更权限。
31.6 文档级安全
Document Level Security 允许角色只看到满足查询条件的文档。
POST /_security/role/order_team_reader
{
"indices": [
{
"names": ["orders-v3"],
"privileges": ["read"],
"query": {
"term": { "team_id": "team_order" }
}
}
]
}
多租户示例:
"query": {
"term": { "tenant_id": "tenant_1001" }
}
注意:
- DLS 是安全边界,不要在业务代码里用
tenant_idfilter 替代; - 条件要简单、可索引;
- 权限变更要审计;
- 不要在高 QPS 角色上拼复杂脚本;
- 多租户更适合索引隔离加 DLS 双层防护。
31.7 字段级安全
Field Level Security 控制角色可见字段。
POST /_security/role/logs_reader
{
"indices": [
{
"names": ["logs-app-*"],
"privileges": ["read"],
"field_security": {
"grant": [
"@timestamp",
"service.name",
"log.level",
"message",
"trace.id"
],
"except": []
}
}
]
}
也可以默认允许,排除敏感字段:
"field_security": {
"grant": ["*"],
"except": ["authorization", "token", "request.headers"]
}
建议:
- 用户 ID、手机号、IP 默认不可见;
- 异常堆栈按团队授权;
authorization、cookie、token不落 ES;- 生产日志查询有审计;
- 安全团队和研发使用不同角色。
31.8 Kibana 权限
Kibana 权限应按空间和功能收敛:
| 角色 | 权限 |
|---|---|
| 普通开发 | 指定空间的 read,能看到本团队索引 |
| 值班工程师 | Discover、Dashboard、告警查看 |
| SRE | 集群监控、索引管理、有限写权限 |
| 数据分析 | 只读聚合空间 |
| 平台管理员 | 权限管理,但操作有审计 |
危险操作要分离:
- 删除索引;
- 修改 ILM;
- 修改 index template;
- 执行 reindex;
- 修改用户和角色;
- 管理快照仓库。
Kibana Dashboard 也可能因为无时间范围查询导致集群压力,应通过空间、索引权限和默认查询约束共同治理。
31.9 审计日志
审计日志可以记录:
- 请求类型;
- 来源用户;
- 来源 IP;
- 索引;
- 成功或拒绝;
- 响应状态;
- 操作时间。
启用审计需要配置安全订阅和静态设置,具体配置随版本变化。原则:
- 删除索引必须可追溯;
- 权限变更必须可追溯;
- 敏感数据查询必须可追溯;
- 审计日志独立保存;
- 普通业务角色不能删除审计日志;
- 审计日志也要设置保留周期。
即使不启用完整审计,也应至少保留:
- 管理操作工单;
- 索引删除审批;
- 角色变更记录;
- 快照仓库修改记录;
- 生产 API key 发放记录。
31.10 网络与访问控制
建议网络分层:
Internet
-> WAF / VPN / Bastion
-> Application
-> Elasticsearch private subnet
-> Data nodes
要求:
- ES 9200 不暴露公网;
- Kibana 走统一登录和访问控制;
- 采集器只访问写入端点和指定索引;
- 跨集群访问使用 remote cluster 安全配置;
- 云安全组按来源收敛;
- 快照存储桶权限单独控制;
- 监控 exporter 不能暴露敏感数据。
31.11 数据分级与脱敏
| 级别 | 示例 | 策略 |
|---|---|---|
| 公开 | 商品标题 | 常规权限 |
| 内部 | 服务日志 | 团队权限 |
| 敏感 | 用户 ID、IP | 字段授权、脱敏 |
| 高敏 | 手机号、身份证、token | 默认不落 ES |
在 Ingest Pipeline 中兜底脱敏:
PUT _ingest/pipeline/sensitive-redact
{
"processors": [
{
"script": {
"lang": "painless",
"source": """
if (ctx.message != null) {
ctx.message = ctx.message
.replaceAll(/\\b\\d{17}[0-9Xx]\\b/, '<id_card>')
.replaceAll(/\\b1[3-9]\\d{9}\\b/, '<mobile>');
}
"""
}
}
]
}
脱敏应在应用输出和采集端优先完成,ES Pipeline 只作为最后防线。
31.12 安全基线检查
xpack.security.enabled: true;- HTTP 和 Transport 均启用 TLS;
- 证书校验不是 none;
- 无匿名访问;
- 应用不使用 elastic 超级用户;
- API key 有过期和轮换;
- 角色 minimal privileges;
- 删除索引有审批;
- 敏感日志有 DLS / FLS;
- 审计日志独立保存;
- 快照仓库权限收敛;
- 集群和 Kibana 不暴露公网;
- 定期盘点用户、角色和 key;
- 定期做权限演练和证书过期监控。
本章小结
安全体系的核心是最小权限和可追溯。网络边界决定能不能进来,TLS 决定传输是否安全,认证和角色决定能做什么,DLS/FLS 决定能看哪些数据,审计决定事后能不能追责。上线前先做安全基线检查,比事故后补救便宜得多。
思考题
- 应用账号为什么不能使用超级用户?
- DLS 和业务代码里的租户过滤有什么本质区别?
- API Key 应如何设计过期和轮换?
- 哪些日志字段不应进入 Elasticsearch?
- 删除索引这类高危操作应如何治理?