当前位置: 首页 > news >正文

Elasticsearch API访问权限控制:禁用外部端点访问

背景与需求

在实际的生产环境中,我们经常遇到这样的需求:

  • Elasticsearch需要对外提供基本的API服务
  • 内部系统(如Grafana)需要完整的ES访问权限
  • 但要禁用某些敏感的API端点(如/_cat)防止信息泄露

本文记录了在Docker部署的Elasticsearch中实现这种细粒度权限控制的完整过程,包括遇到的各种坑点和解决方案。

环境信息

  • 操作系统: Ubuntu 服务器
  • Elasticsearch: 8.17.0 (Docker部署)
  • Grafana: 需要访问ES的完整功能
  • 目标: 禁用外部对/_cat API的访问,保留其他功能

方案对比

方案一:修改网络配置(不推荐)

最初尝试通过修改ES的网络配置来限制访问:

network.host: 127.0.0.1
http.host: 127.0.0.1

踩坑点:这种方案会完全禁用外部访问,包括Grafana也无法访问,不符合需求。

方案二:使用nginx代理

通过nginx反向代理实现精确的端点控制。(太麻烦不想做)

方案三:ES原生安全功能(推荐)

使用Elasticsearch的X-Pack Security功能,通过角色和权限实现细粒度控制。

经过对比,方案三最为优雅,既充分利用了ES的原生安全机制,又便于管理和维护。

实施步骤详解

第一步:确认当前ES部署方式

首先检查ES容器的部署情况:

# 查看ES容器
sudo docker ps | grep elasticsearch# 查看原始启动命令(重要!)
docker inspect es | grep -A 20 "Cmd"

踩坑点1:发现原启动命令中有 -e "xpack.security.enabled=false",这会强制禁用安全功能。

第二步:数据安全确认

在重建容器前,确认数据不会丢失:

# 检查数据挂载
ls -la /srv/elasticsearch/data/
du -sh /srv/elasticsearch/data/# 确认数据大小和内容
docker exec es curl -s http://127.0.0.1:9200/_cat/indices

踩坑点2:很多人担心重建容器会丢失数据。实际上,由于使用了数据卷挂载 (-v /srv/elasticsearch/data:/usr/share/elasticsearch/data),数据存储在主机上,重建容器不会影响数据。

第三步:配置ES安全功能

3.1 修改配置文件
vi /srv/elasticsearch/config/elasticsearch.yml
cluster.name: es-docker-cluster
node.name: single-node
path.data: /usr/share/elasticsearch/data
path.logs: /usr/share/elasticsearch/logs
discovery.type: single-node
bootstrap.memory_lock: true
network.host: 0.0.0.0
http.host: 0.0.0.0# 启用X-Pack安全功能
xpack.security.enabled: true
xpack.security.enrollment.enabled: false
xpack.security.authc.api_key.enabled: true# 禁用SSL(简化配置,生产环境建议启用)
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false
3.2 重建容器
# 停止并删除容器
docker stop es
docker rm es# 重新运行with安全功能
docker run -itd --restart always --name es \-p 9200:9200 \-p 9300:9300 \-e "ES_JAVA_OPTS=-Xms4g -Xmx4g" \-e "ELASTIC_PASSWORD=YourStrongPassword123" \-v /srv/elasticsearch/data:/usr/share/elasticsearch/data \-v /srv/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro \docker.elastic.co/elasticsearch/elasticsearch:8.17.0

踩坑点3:配置文件挂载使用了:ro(只读)模式,所以无法在容器内直接修改配置文件。必须在主机上修改。

第四步:创建角色和权限

4.1 为Grafana创建超级用户角色
curl -X POST "http://elastic:YourStrongPassword123@10.6.110.86:9200/_security/role/grafana_superuser" \
-H "Content-Type: application/json" -d'
{"cluster": ["all"],"indices": [{"names": ["*"],"privileges": ["all"]}],"applications": [{"application": "*","privileges": ["*"],"resources": ["*"]}]
}'

4.2 创建受限角色(无cat权限)
curl -X POST "http://elastic:YourStrongPassword123@10.6.110.86:9200/_security/role/external_limited" \
-H "Content-Type: application/json" -d'
{"cluster": [],"indices": [{"names": ["*"],"privileges": ["read", "view_index_metadata"]}]
}'

第五步:API Key认证尝试与踩坑

5.1 创建API Key
curl -X POST "http://elastic:YourStrongPassword123@10.6.110.86:9200/_security/api_key" \
-H "Content-Type: application/json" -d'
{"name": "grafana-full-access","expiration": "365d","role_descriptors": {"grafana_access": {"cluster": ["all"],"indices": [{"names": ["*"],"privileges": ["all"]}]}}
}'

返回结果示例:

{"id":"U6mEm5cB7ZDEudMvimns","name":"grafana-full-access","api_key":"Ik4YfdYTS1yGnidQaKXC9g","encoded":"VTZtRW01Y0I3WkRFdWRNdmltbnM6SWs0WWZkWVRTMXlHbmlkUWFLWEM5Zw=="
}

踩坑点4:很多人错误地使用api_key字段,实际应该使用encoded字段。

# 错误用法
curl -H "Authorization: ApiKey Ik4YfdYTS1yGnidQaKXC9g" http://10.6.110.86:9200/# 正确用法  
curl -H "Authorization: ApiKey VTZtRW01Y0I3WkRFdWRNdmltbnM6SWs0WWZkWVRTMXlHbmlkUWFLWEM5Zw==" http://10.6.110.86:9200/
5.2 Grafana集成踩坑

踩坑点5:发现Grafana的Basic Auth无法直接使用API Key。

# 这种方式不工作
curl -u api_key:VTZtRW01Y0I3WkRFdWRNdmltbnM6SWs0WWZkWVRTMXlHbmlkUWFLWEM5Zw== http://10.6.110.86:9200/
# 返回401错误

第六步:最终解决方案 - 用户名密码认证

由于Grafana的限制,最终采用传统的用户名密码认证:

6.1 创建Grafana专用用户
curl -X POST "http://elastic:YourStrongPassword123@10.6.110.86:9200/_security/user/grafana_user" \
-H "Content-Type: application/json" -d'
{"password": "GrafanaPassword123","roles": ["grafana_superuser"],"full_name": "Grafana Service User","metadata": {"application": "grafana"}
}'

6.2 验证用户权限
# 测试Grafana用户的完整权限
curl -u grafana_user:GrafanaPassword123 http://10.6.110.86:9200/
curl -u grafana_user:GrafanaPassword123 http://10.6.110.86:9200/_cat/health# 测试受限API Key
curl -H "Authorization: ApiKey LIMITED_API_KEY" http://10.6.110.86:9200/_cat/health
# 应该返回403权限不足

配置管理

密码修改

# 修改用户密码
curl -X POST "http://elastic:YourStrongPassword123@10.6.110.86:9200/_security/user/grafana_user/_password" \
-H "Content-Type: application/json" -d'
{"password": "NewPassword456"
}'

Grafana数据源配置

在Grafana中配置:

  • URLhttp://10.6.110.86:9200
  • Access: Server (default)
  • Auth: ✅ Basic Auth
  • Usergrafana_user
  • PasswordGrafanaPassword123

最终架构与验证

权限矩阵

用户类型基本API_cat API_search API集群管理
elastic (超级管理员)
grafana_user
受限API Key
无认证用户

完整验证脚本

#!/bin/bashecho "=== 1. 测试Grafana用户(应该全部成功) ==="
curl -u grafana_user:GrafanaPassword123 http://10.6.110.86:9200/
curl -u grafana_user:GrafanaPassword123 http://10.6.110.86:9200/_cat/healthecho "=== 2. 测试受限API Key(cat应该失败) ==="
LIMITED_KEY="VmFtSG01Y0I3WkRFdWRNdkpHbXg6NFYtSEJtdWpUTXkwQ3NDSmRPdmF0Zw=="
curl -H "Authorization: ApiKey $LIMITED_KEY" http://10.6.110.86:9200/
curl -H "Authorization: ApiKey $LIMITED_KEY" http://10.6.110.86:9200/_cat/healthecho "=== 3. 测试无认证访问(应该全部失败) ==="
curl http://10.6.110.86:9200/
curl http://10.6.110.86:9200/_cat/health

​​​​​​​

总结与最佳实践

主要踩坑点总结

  1. 容器重建数据安全性:使用数据卷挂载的容器重建不会丢失数据
  2. 配置文件只读挂载:无法在容器内修改配置,必须在主机上操作
  3. API Key使用方式:必须使用encoded字段,不是api_key字段
  4. Grafana认证限制:Basic Auth无法直接使用API Key,需要创建用户
  5. 权限配置细节:角色权限需要精确配置,避免意外的权限泄露

最佳实践建议

  1. 分层权限设计

    • 超级管理员:完全权限
    • 应用服务:必要权限
    • 外部用户:最小权限
  2. 密码安全管理

    • 使用强密码
    • 定期轮换密码
    • 考虑使用密钥管理服务
  3. 监控与审计

    • 启用ES安全日志
    • 监控异常访问模式
    • 定期审查用户权限
  4. 生产环境增强

    • 启用TLS加密
    • 使用证书认证
    • 设置IP白名单

适用场景

这个方案特别适合以下场景:

  • 需要对外提供ES服务但要保护敏感信息
  • 多系统共享ES集群但需要不同权限
  • 需要精确控制API访问权限的企业环境

通过ES原生的安全功能,我们成功实现了细粒度的权限控制,既满足了业务需求,又保证了系统安全。

相关rep:

https://github.com/TIMPICKLE/mitmproxy_log_to_EShttps://github.com/TIMPICKLE/mitmproxy_log_to_ES

http://www.lryc.cn/news/574086.html

相关文章:

  • 在Ubuntu上设置Selenium自动化测试环境:Chrome与Firefox的详细指南
  • 海拔案例分享-门店业绩管理小程序
  • 小程序 顶部栏标题栏 下拉滚动 渐显白色背景
  • Python Django全功能框架开发秘籍
  • 多模态大语言模型arxiv论文略读(133)
  • 【nvidia-H100-ib排障实战2】:服务器 InfiniBand 网络性能问题深度分析
  • 学习Linux进程冻结技术
  • 科技资讯杂志科技资讯杂志社科技资讯编辑部2025年第9期目录
  • 微算法科技(NASDAQ:MLGO)研发可信共识算法TCA,解决区块链微服务中的数据一致性与安全挑战
  • 笔试强训:Day8
  • Qt for OpenHarmony 编译鸿蒙调用的动态库
  • MCU双分区方案,如何优雅地获知当前运行分区?
  • 开发上门按摩APP应具备哪些安全保障功能?
  • 实时预警!机场机坪井室无线智能液位监测系统助力安全降本
  • 【设计模式精讲 Day 12】代理模式(Proxy Pattern)
  • WebSocket 进阶全攻略:心跳机制、断线重连、socket.io、鉴权与WSS配置
  • LeetCode热题100—— 160. 相交链表
  • 拼多多API限流机制破解:分布式IP池搭建与流量伪装方案
  • Re:从零开始的地址映射基本分页存储管理方式(考研向)
  • 京东金融API支付链路剖析:白条分期接口的安全加固方案
  • ​​FFmpeg命令全解析:三步完成视频合并、精准裁剪​​、英伟达显卡加速
  • 飞往大厂梦之算法提升-7
  • vue | vue-macros 插件升级以及配置
  • OSC靶机练习 PG ZenPhoto
  • 华为HN8145V光猫改华为蓝色公版界面,三网通用,xgpon公版光猫
  • redis如何使用IO多路复用
  • 深入理解PHP中的面向对象编程
  • 医疗B端系统布局创新:医护操作界面与患者数据的差异化呈现
  • 347. 前 K 个高频元素
  • 洛谷P1217 [USACO1.5] 回文质数 Prime Palindromes