宜人贷蜂巢ELK Stack之elasticsearch权限探索
前言
上文《宜人贷蜂巢API网关技术解密之Netty使用实践》提到了,API网关“承外对内”,将外部请求,转发到内部各个抓取服务。在网关中,不仅可以做鉴权、加解密、路由、限流功能;如果想了解各服务接口的调用次数、调用时间、成功次数、失败次数等接口相关的统计,都可以网关中埋点,采集相关信息,通过logstash放入elasticsearch(简称es),在kibana中或通过es的http请求获得各服务接口的统计信息。
ELK框架

前段时间有一个需求,我们的elasticsearch需要作为一个服务提供出来。考虑到elasticsearch内保存着敏感数据,需要对elasticsearch添加权限管理功能。搜寻elasticsearch权限管理,大概有三套方案:
- ELK Stack官方安全插件X-Pack Securit
- es安全插件Search Guard
- 自实现权限管理
考虑到X-Pack Security是收费软件,自开发一个权限管理模块成本比较高,最后选用了Search Guard的社区版本,其支持的功能已经满足当前需求。

Search Guard安装过程
- Stop Elasticsearch
ps -ef | grep elasticsearch | grep -v grep | awk {'print $2'} | xargs kill -9
- Install Search Guard
/opt/soft/elasticsearch-5.5.1-guard/bin/ elasticsearch-plugin install -b com.floragunn:search-guard-5:5.5.1-14
如果线上服务器不能访问外网,可以事先下载对应版本的 Search Guard,再以本地模式安装。
/opt/soft/elasticsearch-5.5.1-guard/bin/ elasticsearch-plugin install -b file:///opt/soft/search-guard-5-5.5.1-15.zip
- 产生证书及配置es
如果在测试环境安装es,可以使用软件自带的脚本,生成CA及相应证书,并自动配置了es
sh /opt/soft/elasticsearch-5.5.1-guard/plugins/search-guard-5/tools/install_demo_configuration.sh
但以上方式不适用于线上环境,我们的es希望在线上环境能提供权限访问控制,所以采用了search-guard-ssl生成线上证书
- 首先,下载了search-guard-ssl项目
git clone https://github.com/floragunncom/search-guard-ssl.git
生成证书,可以参考官方文档详细说明
- 建议修改证书信息及密码
example-pki-scripts/etc/root-ca.conf example-pki-scripts/etc/signing-ca.conf
最后,执行证书生成脚本sh ./example.sh
将相应的证书拷贝到es的config文件夹下
修改es配置
cluster.name: honeycomb-es-guard-# node to node.name: node- path.data: /data01/elasticsearch-guard path.logs: /opt/logs/elasticsearch-guard network.host: 0.0.0.0 http.cors.enabled: true http.cors.allow-origin: "*" thread_pool.bulk.queue_size: searchguard.ssl.transport.keystore_filepath: node--keystore.jks searchguard.ssl.transport.keystore_password: node_es searchguard.ssl.transport.truststore_filepath: truststore.jks searchguard.ssl.transport.truststore_password: r_ca_honeycomb searchguard.ssl.transport.enforce_hostname_verification: false searchguard.ssl.transport.enable_openssl_if_available: true searchguard.ssl.transport.resolve_hostname: false searchguard.ssl.http.enabled: true searchguard.ssl.http.keystore_filepath: node--keystore.jks searchguard.ssl.http.keystore_password: node_es searchguard.ssl.http.truststore_filepath: truststore.jks searchguard.ssl.http.truststore_password: r_ca_honeycomb searchguard.authcz.admin_dn: - CN=*,OU=client,O=client,L=test, C=de - CN=kirk,OU=client,O=client,L=test,C=DE searchguard.ssl.http.clientauth_mode: NONE
- Restart Elasticsearch.
su elk /opt/soft/elasticsearch--guard/bin/elasticsearch -d
- Initialise the Search Guard index by running sgadmin
<span style=-guard/plugins/search-guard-/tools/sgadmin.sh -cd /opt/soft/elasticsearch--guard/plugins/search-guard-/sgconfig/ -cn honeycomb-es-guard- -ks /opt/soft/elasticsearch--guard/config/kirk-keystore.jks -kspass ki_ca_1 -ts /opt/soft/elasticsearch--guard/config/truststore.jks -tspass r_ca_honeycomb –nhnv</span>
- 测试结果
curl -k -u admin:admin 'https://localhost:9200/_searchguard/authinfo?pretty'

es装上Search Guard后的ELK框架

kibana修改步骤
安装插件
/opt/soft/kibana--linux-x86_64-guard/bin/kibana-plugin install file:///opt/soft/searchguard-kibana-5.5.1-4.zip
kibana配置
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.url: "https://localhost:9200"
kibana.index: ".kibana"
elasticsearch.username: "kibanaserver"
elasticsearch.password: "kibanaserver"
elasticsearch.ssl.verificationMode: none
- start kibana
/opt/soft/kibana-5.5.1-linux-x86_64-guard/bin/kibana &
- 访问页面

logstash修改步骤
logstash在按照官方文档配置,且咨询Search Guard官方后,并没有安装成功;现列出操作过程及问题现象,如有哪位读者了解,还望不吝赐教
- Configure logstash to use HTTPS instead of HTTP. 例如,hosts => "https://..."
- If you want to verify the server’s certificate (optional, but recommended), you need to provide the path to the keystore containing your Root CA as well. logstash不需要验证es的证书,所以设置sslcertificateverification => false 如果进行证书验证,需配置CA路径及密码
- Configure the logstash username and password.
最终配置
output {
elasticsearch {
hosts => ["https://xx.xx.xx.32:9200"]
index => "%{log_project}-%{+YYYY-MM-dd}"
ssl => true
ssl_certificate_verification => false
#truststore => "/opt/soft/elasticsearch-5.5.1-guard/config/truststore.jks"
#truststore_password => r_ca_honeycomb
user => logstash
password => logstash
}
}
- start logstash
/opt/soft/logstash-2.4.1-guard/bin/logstash -f /opt/soft/logstash-2.4.1-guard/conf/honeycomb-logstash.conf
问题
1、Search Guard 建议logstash不做证书验证且不需要提供truststore和truststore_password,但按操作后,进程启动成功,但仍有fail提示
** WARNING ** Detected UNSAFE options in elasticsearch output configuration!
** WARNING ** You have enabled encryption but DISABLED certificate verification.
** WARNING ** To make sure your data is secure change :ssl_certificate_verification to true {:level=>:warn}
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target {:class=>"Manticore::ClientProtocolException", :level=>:error}
Pipeline main started
2、logstash在启动后,发送数据给es时,始终报错
Attempted to send a bulk request to Elasticsearch configured at '["https://xx.xx.xx.32:9200"]',
but an error occurred and it failed! Are you sure you can reach elasticsearch from this machine using the configuration provided?
{:error_message=>"PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested
target", :error_class=>"Manticore::ClientProtocolException", :backtrace=>["/opt/soft/logstash-
-guard/vendor/bundle/jruby/-java/lib/manticore/response.rb::in `initialize'",
"org/jruby/RubyProc.java:281:in `call'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/manticore-0.6.0-java/lib/manticore/response.rb:79:in `call'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/manticore-0.6.0-java/lib/manticore/response.rb:256:in `call_once'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/manticore-0.6.0-java/lib/manticore/response.rb:153:in `code'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-transport-1.1.0/lib/elasticsearch/transport/transport/http/manticore.rb:84:in `perform_request'",
"org/jruby/RubyProc.java:281:in `call'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-transport-1.1.0/lib/elasticsearch/transport/transport/base.rb:257:in `perform_request'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-transport-1.1.0/lib/elasticsearch/transport/transport/http/manticore.rb:67:in `perform_request'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-transport-1.1.0/lib/elasticsearch/transport/client.rb:128:in `perform_request'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-api-1.1.0/lib/elasticsearch/api/actions/bulk.rb:93:in `bulk'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/http_client.rb:53:in `non_threadsafe_bulk'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/http_client.rb:38:in `bulk'",
"org/jruby/ext/thread/Mutex.java:149:in `synchronize'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/http_client.rb:38:in `bulk'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:172:in `safe_bulk'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:101:in `submit'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:86:in `retrying_submit'", "/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:29:in `multi_receive'", "org/jruby/RubyArray.java:1653:in `each_slice'", "/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:28:in `multi_receive'", "/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/output_delegator.rb:130:in `worker_multi_receive'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/output_delegator.rb:114:in `multi_receive'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/pipeline.rb:301:in `output_batch'",
"org/jruby/RubyHash.java:1342:in `each'", "/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/pipeline.rb:301:in `output_batch'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/pipeline.rb:232:in `worker_loop'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/pipeline.rb:201:in `start_workers'"], :level=>:error}
看日志似乎是目的不可达,但在logstash机器上,通过命令测试,是可以访问的 curl -k -u logstash:logstash 'https://xx.xx.xx.32:9200/_searchguard/authinfo?pretty'

另外es有打印错误日志
[--24T10::,][ERROR][c.f.s.h.SearchGuardHttpServerTransport] [node-] SSL Problem Received fatal alert: certificate_unknown
javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
at sun.security.ssl.Alerts.getSSLException(Alerts.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:) ~[?:?]
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:) ~[?:1.8.0_131]
at io.netty.handler.ssl.SslHandler$SslEngineType$.unwrap(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:) [netty-transport-.Final.jar:.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:) [netty-transport-.Final.jar:.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$.run(SingleThreadEventExecutor.java:) [netty-common-.Final.jar:.Final]
at java.lang.Thread.run(Thread.java:) [?:1.8.0_131]
[--24T10::,][ERROR][c.f.s.h.SearchGuardHttpServerTransport] [node-] SSL Problem Received fatal alert: certificate_unknown
javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
at sun.security.ssl.Alerts.getSSLException(Alerts.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:) ~[?:?]
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:) ~[?:?]
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:) ~[?:1.8.0_131]
at io.netty.handler.ssl.SslHandler$SslEngineType$.unwrap(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
3、上文es的错误日志,显示es不知道证书(应该是客户端证书),但是已经配置了不做客户端认证,这又是为什么?
es部分配置
searchguard.ssl.http.clientauth_mode: NONE
总结
虽然logstash与es通信暂时没有成功,但是在尝试开通es权限的过程中,也积累了些经验和成果。
- 使用类似文中curl的方式(http请求),直接使用es服务。
- 添加了Search Guard的es如何对外提供域名访问,实现后端多点服务/路由。
nginx可以处理来自外部的https请求,但目前不支持https代理,即nginx不能访问后端的https服务。如果仍然使用Search Guard,可以考虑使用四层负载均衡器lvs或者硬件负载均衡器,将请求透传给后端服务器;另外知乎文章上有推荐使用Squid。
参考
https://floragunn.com/
https://github.com/floragunncom/search-guard-docs
https://github.com/floragunncom/search-guard-docs/blob/master/installation.md
https://github.com/floragunncom/search-guard-docs/blob/master/tlsgeneratedemo_certificates.md
https://github.com/floragunncom/search-guard-ssl/tree/5.5.0
https://github.com/floragunncom/search-guard-docs/blob/master/kibana.md
https://github.com/floragunncom/search-guard-docs/blob/master/logstash.md
https://forum.nginx.org/read.php?2,15124,15256
https://www.zhihu.com/question/19871146
作者:蜂巢团队
来源:宜信技术学院
宜人贷蜂巢ELK Stack之elasticsearch权限探索的更多相关文章
- 宜人贷蜂巢API网关技术解密之Netty使用实践
一.背景 宜人贷蜂巢团队,由Michael创立于2013年,通过使用互联网科技手段助力金融生态和谐健康发展.自成立起一直致力于多维度数据闭环平台建设.目前团队规模超过百人,涵盖征信.电商.金融.社交. ...
- ELK Stack总结
目录 ELK Stack 介绍 Elasticsearch 概念1(基础) CRUD基本用法 概念2(文本解析器) 查询 分析/聚合 概念3(架构原理的补充) Logstash基础 Kibana的数据 ...
- ELK Stack 笔记
ELK Stack ELK Stack ELK Stack ELK 介绍 架构 Elasticsearch 安装 常见问题 关闭 Elasticsearch Elasticsearch-head Ki ...
- 大数据日志分析产品——SaaS Cloud, e.g. Papertrail, Loggly, Sumo Logic;Open Source Frameworks, e.g. ELK stack, Graylog;Enterprise Products, e.g. TIBCO LogLogic, IBM QRadar, Splunk
Learn how you can maximize big data in the cloud with Apache Hadoop. Download this eBook now. Brough ...
- ELK stack elasticsearch/logstash/kibana 关系和介绍
ELK stack elasticsearch 后续简称ES logstack 简称LS kibana 简称K 日志分析利器 elasticsearch 是索引集群系统 logstash 是日志归集集 ...
- 快速搭建日志系统——ELK STACK
什么是ELK STACK ELK Stack是Elasticserach.Logstash.Kibana三种工具组合而成的一个日志解决方案.ELK可以将我们的系统日志.访问日志.运行日志.错误日志等进 ...
- Elastic Stack之ElasticSearch分布式集群二进制方式部署
Elastic Stack之ElasticSearch分布式集群二进制方式部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 想必大家都知道ELK其实就是Elasticsearc ...
- ELK Stack部署
部署ELK Stack 官网:https://www.elastic.co 环境准备: ip hostname 服务 用户.组 192.168.20.3 node2003 kibana6.5,file ...
- ELK Stack 企业级日志收集平台
ELK Stack介绍 大型项目,多产品线的日志收集 ,分析平台 为什么用ELK? 1.开发人员排查问题,服务器上查看权限 2.项目多,服务器多,日志类型多 ELK 架构介绍 数据源--->lo ...
随机推荐
- [POJ3974]Palindrome(后缀数组 || manacher)
传送门 求一个串的最长回文子串的长度 1.后缀数组 把这个串反转后接到原串的后面,中间连一个没有出现过的字符. 然后求这个新字符串的某两个后缀的公共前缀的最大值即可. ——代码 #include &l ...
- bzoj 1061~1065【Noi2008】解题报告
这次Noi好像格外喜欢树形DpQAQ P.S.好像这次的题都与图有关QAQ bzoj1061[Noi2008]志愿者招募:上下界可行最小费用流 bzoj1062[Noi2008]糖果雨:数形结合&am ...
- [JSOI2016] 最佳团队 (树形DP+01分数规划)
Description JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号. 每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY ...
- Python Base Five
// 8 day(2016/8/11) 38. In python , it is oop. class Baskball: def setName(self, name): ...
- OpenMP 并行编程
OpenMP 并行编程 最近开始学习并行编程,目的是为了提高图像处理的运行速度,用的是VS2012自带的OpenMP. 如何让自己的编译器支持OpenMP: 1) 点击 项目属性页 2)点击 配置 3 ...
- [AHOI2008]逆序对(dp)
小可可和小卡卡想到Y岛上旅游,但是他们不知道Y岛有多远.好在,他们找到一本古老的书,上面是这样说的: 下面是N个正整数,每个都在1~K之间.如果有两个数A和B,A在B左边且A大于B,我们就称这两个数为 ...
- python 字体颜色,背景颜色
- 从实际案例聊聊Java应用的GC优化
转自美团点评技术博客:https://tech.meituan.com/jvm_optimize.html 当Java程序性能达不到既定目标,且其他优化手段都已经穷尽时,通常需要调整垃圾回收器来进一步 ...
- codeforces 446C DZY Loves Fibonacci Numbers 数论+线段树成段更新
DZY Loves Fibonacci Numbers Time Limit:4000MS Memory Limit:262144KB 64bit IO Format:%I64d &a ...
- LA 3905 Meteor 扫描线
The famous Korean internet company nhn has provided an internet-based photo service which allows The ...