版本:
spark 2.2.1
ElasticSearch 5.4.3
SearchGuard 5.4.3
hadoop 2.6.0
坑爹的认证,踏进千万坑!
我们首先看下SearchGuard官网的配置简介
首推的pkcskey文件认证好不好,感觉从这里被坑了下,我们生产顺势用了这个认证。从javaapi到head再到kibana以及配置x-pack势不可挡,业务完成的嘎嘎的。
但是ES在关联上很吃力,我们一开始的模型没有设计好。所以只能基于spark读出来写sparksql去统计业务,但是ES-hadoop的官网并不支持此类的认证。
背景:生产20个节点已经用了PEM和KEY文件的认证,再去替换需要重新配置以及重启集群,还要承担配置文件修改,生产出现问题的风险。所以我们使用PEM文件认证。
接下来就是去看官网配置sparkConf。
有点坑的是只支持http的auth或者TrustStore的认证。
撸起袖子改源码,由于本人对认证一知半解,并没有成功。所以选择了在证书上进行改动:
- 官网不支持PEM证书认证,但是好在是同样支持X.509,由于我们的证书是pem、key文件以及root的ca。理论上来讲将证书转换为truststore以及keystore也是可以认证成功的(下面只提供步骤,具体原理自己研究)。
- 把CA证书文件转换成truststore.jks文件,执行命令:keytool -import -noprompt -file root-ca.pem -keystore truststore.jks -storepass <自己制定的密码>
- 把用户证书文件转换成keystore.jks文件,执行命令:openssl pkcs12 -export -in client1.pem -inkey client1.key -out keystore.p12 -passout pass:<自己制定的密码>
- 把p12格式文件加入到JKS格式,执行命令:keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -destkeystore keystore.jks
-srcstorepass <自己制定的密码> -deststorepass <自己制定的密码>
通过上述过程就将我们的pem、key以及ca文件转换成了truststore以及keystore文件,我们尝试着用这些文件进行集群的认证。
Java版:
Settings settings = Settings.builder()
.put("searchguard.ssl.transport.enabled", true)
.put("searchguard.ssl.transport.keystore_filepath",System.getProperty("user.dir")+"/src/main/resources/ca/keystore.jks")
.put("searchguard.ssl.transport.truststore_filepath",System.getProperty("user.dir")+"/src/main/resources/ca/truststore.jks")
//这里的password去生成的证书文件 readme中找
.put("searchguard.ssl.transport.keystore_password", "自己制定的密码")
.put("searchguard.ssl.transport.truststore_password", "自己制定的密码")
.put("searchguard.ssl.http.keystore_password", "自己制定的密码")
.put("searchguard.ssl.http.truststore_password", "自己制定的密码")
.put("searchguard.ssl.transport.enforce_hostname_verification", false) //这里指定不做主机名称校检
.put("client.transport.ignore_cluster_name", true)
.build();
TransportClient client = new PreBuiltTransportClient(settings, SearchGuardSSLPlugin.class)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("ip"), 9300));
获取到对应的TransPortClient实例,可以成功获取集群数据。
Spark版:
val spark: SparkSession = SparkSession
.builder()
.appName("esmodle")
.config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
.config(ConfigurationOptions.ES_NET_USE_SSL,"true")
.config(ConfigurationOptions.ES_NET_HTTP_AUTH_USER,"admin")//访问es的用户名
.config(ConfigurationOptions.ES_NET_HTTP_AUTH_PASS, "admin")//访问es的密码
.config(ConfigurationOptions.ES_NODES, "ip")
.config(ConfigurationOptions.ES_NET_SSL_PROTOCOL, "ssl")
.config(ConfigurationOptions.ES_NET_SSL_CERT_ALLOW_SELF_SIGNED, "false")
.config(ConfigurationOptions.ES_NET_SSL_KEYSTORE_LOCATION, System.getProperty("user.dir")+"/src/main/resources/jks/keystore.jks")
.config(ConfigurationOptions.ES_NET_SSL_KEYSTORE_PASS, "自己制定的密码 ")
.config(ConfigurationOptions.ES_NET_SSL_KEYSTORE_TYPE, ConfigurationOptions.ES_NET_SSL_KEYSTORE_TYPE_DEFAULT)
.config(ConfigurationOptions.ES_NET_SSL_TRUST_STORE_LOCATION, System.getProperty("user.dir")+"/src/main/resources/jks/truststore.jks")
.config(ConfigurationOptions.ES_NET_SSL_TRUST_STORE_PASS, "自己制定的密码")
.config("es.net.ssl.cert.allow.self.signed", "false")
.master("local")
.getOrCreate()
但是spark在本地调试的时候出了很多问题,简单挑两个来说下:
Cannot open stream (inlined queries need to be marked as such through
?
and{}
) for resource
这个错误看起来是打不开truststore的文件流,异常追踪进来发现用的URL类打开本地文件导致的报错。由于我们业务的证书都是本地刷出来的,所以不需要URL,下载源码改为maven格式直接通过File的流打开文件即可。更改为: return new FileInputStream(resource);
编译的过程中出现了几个问题:
org.elasticsearch.hadoop.serialization.json.BackportedObjectReader类的_createDeserializationContext和_provider.findTypedValueDeserializer方法报错,主要是方法入参不对,自己根据方法提示实现下就行。具体源码自己如何能打包成功,不在深究,源码原生使用的Grandle打包方式,不太熟悉。
还有在打包过程中的一些错误,就不一一赘述了,遇到问题解决就是了。编译成功后,使用maven打包,成功后直接引入项目中
虽然报无法找到版本但是不影响使用。可以看下,新的更改已经引入了包中。
直接运行spark程序查询ElasticSearch集群中的数据
认证通过,报错原因是该索引在测试集群中不存在,到此解决了spark在集成PEM认证的ElasticSearch集群上的认证问题。
注:上述es-spark的代码更改是为了在windows环境下调试使用,linux环境下直接使用原生es-spark即可,但是证书路径前要加file:///,否则路径识别不到。