4、跨集群搜索的权限控制:跨集群搜索的用户权限、角色配置、安全最佳实践
跨集群搜索这个功能,说白了就是把多个 Elasticsearch 集群的数据拉到一起查。但问题来了——你总不能让人随便查吧?权限控制搞不好,数据泄露就是分分钟的事。我刚开始做跨集群搜索时,就吃过这个亏,后面慢慢摸索出一套比较稳妥的做法。
4.1 跨集群搜索的权限模型
先理清一个概念。跨集群搜索涉及两个角色:
- 本地集群:你发起查询的那个集群
- 远程集群:被查询的那个集群
权限控制要管两头。本地集群要控制「谁能发起跨集群查询」,远程集群要控制「允许谁查哪些索引」。嗯,这里要注意,两个集群的安全配置是独立的,但必须协同工作。
核心原则:最小权限原则。只给查询所需的索引权限,不要给全部。
4.2 用户权限配置实战
假设我有两个集群:cluster-a(本地)和 cluster-b(远程)。我想让 cluster-a 上的用户 search_user 能查询 cluster-b 的 logs-* 索引。
4.2.1 远程集群(cluster-b)的配置
首先,在 cluster-b 上创建一个角色,专门给跨集群搜索用:
PUT /_security/role/remote_search_role
{
"cluster": ["cross_cluster_search"],
"indices": [
{
"names": ["logs-*"],
"privileges": ["read", "read_cross_cluster"]
}
]
}
然后创建用户并分配这个角色:
POST /_security/user/remote_search_user
{
"password": "StrongPassword123!",
"roles": ["remote_search_role"],
"full_name": "Remote Search User"
}
我个人习惯把这种专用用户的名字起得明确一点,比如 ccs_user_prod,一看就知道是干跨集群搜索用的。
4.2.2 本地集群(cluster-a)的配置
在 cluster-a 上,你需要配置远程集群的连接信息,并且给本地用户分配相应的权限:
PUT /_cluster/settings
{
"persistent": {
"search.remote": {
"cluster-b": {
"seeds": ["cluster-b-node1:9300", "cluster-b-node2:9300"]
}
}
}
}
然后创建本地用户,并赋予它使用远程集群的权限:
PUT /_security/role/local_search_role
{
"indices": [
{
"names": ["*"],
"privileges": ["read"]
}
],
"cluster": [
"cross_cluster_search"
]
}
POST /_security/user/search_user
{
"password": "AnotherStrongPass!",
"roles": ["local_search_role"]
}
小技巧:本地集群的 cross_cluster_search 集群权限是必须的,否则用户连发起跨集群查询的资格都没有。
4.3 角色配置的进阶玩法
你想想看,如果远程集群有几十个索引,难道每个都要列出来?当然不是。Elasticsearch 支持通配符和索引模板,可以批量控制。
4.3.1 使用索引模板控制权限
PUT /_security/role/advanced_remote_role
{
"indices": [
{
"names": ["logs-*", "metrics-*", "app-*-prod"],
"privileges": ["read", "read_cross_cluster"]
}
],
"run_as": ["ccs_user_prod"]
}
这里我用了 run_as 功能。什么意思呢?就是本地用户可以用 ccs_user_prod 的身份去查询远程集群。我在项目中遇到过一种场景:多个团队共享一个远程集群,每个团队只能查自己的索引。用 run_as 就能做到精细隔离。
4.3.2 限制查询范围
有时候你不想让用户查全部字段,可以这样:
PUT /_security/role/restricted_remote_role
{
"indices": [
{
"names": ["logs-*"],
"privileges": ["read", "read_cross_cluster"],
"field_security": {
"grant": ["@timestamp", "level", "message", "service.name"],
"except": ["password", "token", "secret"]
}
}
]
}
说白了,就是只让用户看到业务需要的字段,敏感字段直接屏蔽掉。我曾经因为没做字段级权限控制,导致一个测试账号查到了生产环境的密钥——嗯,那次之后我就再也不敢偷懒了。
4.4 安全最佳实践
光配置权限还不够,运维层面也得跟上。我总结了几条经验:
| 实践项 | 说明 | 我的建议 |
|---|---|---|
| 使用 TLS 加密 | 跨集群通信必须加密 | 别用明文传输,哪怕在内网 |
| 专用用户 | 不要用 admin 账号做跨集群搜索 | 创建只读专用用户,权限最小化 |
| 审计日志 | 记录谁在什么时候查了什么 | 开启 audit log,出事好追溯 |
| 定期轮换密码 | 远程用户的密码要定期更换 | 配合密钥管理工具自动轮换 |
| 网络隔离 | 只开放必要的端口和 IP | 用防火墙限制远程集群的访问来源 |
警告:千万不要把远程集群的 elastic 超级用户密码写在本地集群的配置文件中。我见过有人这么干,结果本地集群被攻破后,远程集群也跟着沦陷了。
4.5 避坑指南
最后分享几个我踩过的坑:
- 证书过期:跨集群搜索用 TLS 时,证书过期会导致查询失败。我曾经半夜被叫起来处理过这事。建议设置证书过期告警。
- 角色缓存:修改角色后,有时不会立即生效。可以调用
POST /_security/role/{name}/_clear_cache手动清除缓存。 - 版本兼容:跨集群搜索要求两个集群的主版本号一致。比如 7.x 可以查 7.x,但 7.x 查 6.x 就不行。升级前一定要确认。
- 索引名冲突:如果本地和远程都有同名的索引,查询时要用
cluster-b:logs-2024这种格式指定集群。否则可能查到本地数据。
嗯,权限控制这块其实不难,但细节很多。你只要记住一个原则:给最少的权限,做最全的审计。这样即使出了问题,也能快速定位和修复。
总结:跨集群搜索的权限控制,核心是「本地控制发起权,远程控制查询范围」。配合 TLS、专用用户、审计日志,基本就能做到安全可控。