ES 安全三件套
ES 安全三件套
Elasticsearch 在 6.8/7.1 版本之前,安全功能是 X-Pack 付费版专属。但从 6.8 和 7.1 开始,基础安全功能免费开放,包括认证(Authentication)、授权(Authorization)和 TLS 加密。本文将逐一拆解这"安全三件套"的配置与实战。
1. 认证(Authentication)
ES 支持多种认证后端,按使用频率排序:
| Realm 类型 | 适用场景 | 复杂度 |
|---|---|---|
| Native Realm | 内置用户,小规模部署 | 低 |
| File Realm | 静态用户列表,无网络依赖 | 低 |
| LDAP | 企业 AD 域 | 中 |
| SAML | 单点登录(SSO) | 高 |
| OIDC | 对接 Okta/Keycloak 等 | 高 |
| PKI | 证书认证 | 高 |
Native Realm 配置
# elasticsearch.yml
xpack.security.enabled: true
xpack.security.authc.realms.native.native1:
order: 0
设置密码:
# 交互式设置内置用户密码
bin/elasticsearch-setup-passwords interactive
# 或者分别设置
bin/elasticsearch-reset-password -u elastic
创建自定义用户
# 通过 API 创建用户
POST /_security/user/logstash_writer
{
"password": "changeme123",
"roles": ["logstash_writer_role"],
"full_name": "Logstash Writer"
}
LDAP 配置示例
xpack.security.authc.realms.ldap.ldap1:
order: 0
url: "ldaps://ldap.example.com:636"
bind_dn: "cn=admin,dc=example,dc=com"
bind_password: "admin_password"
user_search:
base_dn: "ou=users,dc=example,dc=com"
filter: "(uid={0})"
group_search:
base_dn: "ou=groups,dc=example,dc=com"
unmapped_groups_as_roles: false
2. 授权(Authorization):RBAC 模型
ES 的权限模型是标准的 RBAC:Role → Privilege → Resource。
权限层级
| 层级 | 资源范围 | 示例 |
|---|---|---|
| Cluster | 集群级别 | monitor、manage、all |
| Index | 索引级别 | read、write、create_index、delete |
| Document | 文档级别 | 配合 query 做字段级过滤 |
| Field | 字段级别 | {"field_security": {"grant": ["title", "price"]}} |
实战:最小权限原则
场景 1:给 Logstash 只分配写入权限
POST /_security/role/logstash_writer_role
{
"cluster": ["monitor", "manage_ilm"],
"indices": [
{
"names": ["logs-*", "metrics-*"],
"privileges": ["create_index", "index", "auto_configure"],
"field_security": {
"grant": ["*"]
}
}
]
}
注意:Logstash 不需要
read权限,也不需要delete权限。权限越少越好。
场景 2:给 Kibana 只分配读取权限
POST /_security/role/kibana_readonly_role
{
"cluster": ["monitor"],
"indices": [
{
"names": ["logs-*", "product_*", "order_*"],
"privileges": ["read", "view_index_metadata"],
"field_security": {
"grant": ["message", "timestamp", "level", "service"]
},
"query": {
"bool": {
"must_not": [
{ "term": { "sensitive": true } }
]
}
}
}
]
}
这个例子展示了两个高级特性:
- 字段级安全(Field Security):Kibana 用户只能看到
message、timestamp、level、service四个字段。 - 文档级安全(Document Security):通过
query过滤掉sensitive: true的文档。
场景 3:给开发者分配只读 + Dev Tools 权限
POST /_security/role/dev_role
{
"cluster": ["monitor"],
"indices": [
{
"names": ["dev-*"],
"privileges": ["all"],
"allow_restricted_indices": false
}
]
}
权限速查表
| 操作 | 需要的索引权限 |
|---|---|
GET /index/_search |
read |
POST /index/_doc |
create_doc 或 index |
PUT /index |
create_index |
DELETE /index |
delete_index |
GET /_cat/indices |
monitor(注意是 cluster 级别) |
3. TLS 加密
TLS 分两层:
| 层级 | 配置项 | 用途 |
|---|---|---|
| Transport TLS | xpack.security.transport.ssl |
节点间通信加密 |
| HTTP TLS | xpack.security.http.ssl |
客户端到 ES 的通信加密 |
用 elasticsearch-certutil 生成证书
# Step 1: 生成 CA 证书
bin/elasticsearch-certutil ca
# 输出 elastic-stack-ca.p12
# Step 2: 用 CA 签发节点证书
bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12
# 输出 elastic-certificates.p12
# Step 3: 把 elastic-certificates.p12 复制到每个节点的 config 目录
配置 TLS
# elasticsearch.yml(每个节点都需配置)
xpack.security.enabled: true
# Transport 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-certificates.p12
# HTTP TLS(客户端通信)
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: elastic-certificates.p12
xpack.security.http.ssl.truststore.path: elastic-certificates.p12
踩坑提醒:如果
verification_mode设为full(严格验证),证书中的 SAN(Subject Alternative Name)必须包含节点的主机名或 IP,否则节点无法通信。调试阶段可以先设certificate,生产环境务必改为full。
客户端连接 HTTPS
# curl 连接 HTTPS 需要 -k(测试用)或 --cacert(生产用)
curl --cacert ca.crt -u elastic:password "https://localhost:9200/_cat/health?v"
# 也可以把用户名密码放到 Authorization header
curl --cacert ca.crt -H "Authorization: Basic $(echo -n 'elastic:password' | base64)" \
"https://localhost:9200/_cat/indices?v"
4. API Key 替代密码认证
API Key 比密码更安全:可以限时、限权、单独吊销。
创建 API Key
POST /_security/api_key
{
"name": "logstash_api_key",
"role_descriptors": {
"logstash_writer": {
"cluster": ["monitor", "manage_ilm"],
"indices": [
{
"names": ["logs-*"],
"privileges": ["create_index", "index"]
}
]
}
},
"expiration": "30d"
}
返回:
{
"id": "VuaCfGcBC9d6NxQfLhJy",
"name": "logstash_api_key",
"api_key": "kL4aPfTQShu1j3dGz8Kx8w",
"encoded": "VuaCfGcBC9d6NxQfLhJy:azNkY2Rm..." // Base64 编码后用于 Authorization header
}
使用 API Key
# Logstash 配置中使用 api_key
output {
elasticsearch {
hosts => ["https://es-node:9200"]
api_key => "VuaCfGcBC9d6NxQfLhJy:kL4aPfTQShu1j3dGz8Kx8w"
ssl => true
cacert => "/etc/logstash/ca.crt"
}
}
吊销 API Key
DELETE /_security/api_key
{
"name": "logstash_api_key"
}
5. 安全配置检查清单
| 检查项 | 要求 | 命令 |
|---|---|---|
| 密码是否修改 | 默认密码 changeme 必须改 |
elasticsearch-setup-passwords |
| HTTPS 是否开启 | 生产必须开启 | 检查 elasticsearch.yml |
| transport TLS 是否开启 | 节点间通信必须加密 | 检查 elasticsearch.yml |
| 是否禁用通配符 delete | 生产禁 DELETE /* |
PUT /_cluster/settings {"persistent":{"action.destructive_requires_name":true}} |
| 是否用最小权限 | 每个账户只给必要权限 | 审查 _security/role |
| API Key 是否设过期 | 长期 Key 需设 expiration |
审查 _security/api_key |
总结
ES 安全三件套的落地顺序建议是:
- 先开 TLS——加密所有通信,防止中间人攻击
- 再设认证——至少用 native realm,修改所有默认密码
- 最后细化授权——按最小权限原则创建角色、分配用户
安全不是"加完就忘"的一次性工作。定期审查用户权限、吊销不再使用的 API Key、审计慢查询中的敏感字段访问——这些才是安全运维的日常。