ELK生成PEM格式的ca证书、设置Https并使用Elasticsearch Java Client连接
文章目录前提条件生成CA证书根据CA证书生成用于各个节点通信加密的证书为其他组件Kibana、Logstash生成证书配置elasticsearch.yml配置kibana.yml配置logstash.confJava代码使用HTTPS连接ES为什么使用ca.crt而不是官方推荐的ca.p12?官方文档前提条件本地下载安装好Elasticsearch、Kibana、Logstash,并可以正常启动
文章目录
前提条件
-
本地下载安装好Elasticsearch、Kibana、Logstash,并可以正常启动
-
本文所使用的ELK的版本为8.2.0
-
Elasticsearch 8.2.0 版本,安装好之后会默认生成对应的http_ca.cert、transport.p12、http.12文件
生成CA证书
为什么这里是生成ca.crt而不是官方文档中的ca.p12文件呢?(此问题已更新,请参照Java代码那一节最新说明)
./bin/elasticsearch-certutil ca --days 3650 --pem --out ./tls/ca/ca.zip
unzip tls/ca/ca.zip
在ca目录下生成了ca.crt和ca.key文件
根据CA证书生成用于各个节点通信加密的证书
instances.yml文件
instances:
- name: elasticsearch
dns:
- localhost # local connections
ip:
- 127.0.0.1 # local connections
执行命令
./bin/elasticsearch-certutil cert --ca-cert tls/ca/ca/ca.crt --ca-key tls/ca/ca/ca.key --in tls/instances.yml --days 3650 --out tls/certificate.zip
解压文件
unzip certificate.zip
解压成功之后会有一个elasticsearch.p12文件
为其他组件Kibana、Logstash生成证书
./bin/elasticsearch-certutil http
根据提示输入第一步生成的ca.crt和ca.key,可以选择设置密码或者不设置密码
最终会生成一个elasticsearch-ssl-http.zip压缩文件
unzip elasticsearch-ssl-http.zip
解压之后为两个文件夹,分别有
elasticsearch-ca.pem和http.p12文件
elasticsearch和kibana,里面分别有一个README.txt告诉怎么用
配置elasticsearch.yml
注意 上述所有生成过程的密码都是空
将上述生成的所有文件放到一个目录下,通常是$ES_INSTALL_HOME/config/certs,以下为elasticsearch.yml文件
# http mode下生成的文件
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: http.p12
# cert mode下生成的文件
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: elasticsearch.p12
xpack.security.transport.ssl.truststore.path: elasticsearch.p12
执行下列命令,具体命令的文档
# 密码问第三步生成http.p12时设置的密码
./bin/elasticsearch-keystore add xpack.security.http.ssl.truststore.secure_password
./bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password
# 密码为第二步生成elasticsearch.p12文件时的设置的密码
./bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
./bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
每个命令都会让你输入密码,如果没有密码直接回车即可
注意 这里也可以将上述配置写到elasticsearch.yml文件里。但是由于elasticsearch刚安装的时候已经设置了password而不是secure_password。所以会启动不起来。
用命令行的方式应该会把password给覆盖掉
所有配置配置完毕之后,启动elasticsearch,观察是否正常启动
配置kibana.yml
将第三步生成的elasticsearch-ca.pem拷贝到$KIBANA_INSTALL_HOME/config文件夹下
# 将http 改为 https
elasticsearch.hosts: [ "https://localhost:9200" ]
elasticsearch.ssl.certificateAuthorities: [ "config/elasticsearch-ca.pem" ]
启动Kibana,观察是否正常启动
配置logstash.conf
将第三步生成的elasticsearch-ca.pem拷贝到$Logstash_INSTALL_HOME/config文件夹下
在具体的logstash配置文件中的output部分增加最后两行配置
output {
elasticsearch {
hosts => "localhost:9200"
user => "elastic"
password => "password"
# 添加ssl配置
ssl => true
cacert => "config/elasticsearch-ca.pem"
}
}
启动logstash,观察是否正常启动
Elasticsearch Java Client使用HTTPS连接ES
截止到这部分,ELK能正常启动不全部配置了TLS。现在在Java代码里使用HTTPS连接ES.
为什么使用ca.crt而不是官方推荐的ca.p12?
因为JDK8对于.p12文件的解析存在问题。据我Google,如果要使用.p12文件进行连接,JDK版本至少是11才可以,不过我没试过,所以在JDK8的环境里,我推荐使用ca.crt文件
2022年9月22日更新
Oracle JDK8版本只有大于8u301的才没问题,具体bug连接见Oracle Bug 8267837
但是由于Oracle JDK 8u202以上版本是收费的.可以使用Adoptium Temurin OpenJDK来代替,Adoptium OpenJDK对应的JDK8截止今天为止,最后一个版本是8u345-b01
同时ES中TLSV1.3也需要JDK版本高于8u261,所以个人建议,如果不是特别麻烦(考虑到线上所有项目需要升级JDK并完整测试),可将JDK升级到8u345
如果本机切换到高级版本则可以使用.p12文件进行连接,官方.p12文件连接示例,文档中的keyStorePass为密码
示例代码如下
@Configuration
public class ElasticSearchConfiguration {
@Bean
@SneakyThrows
public ElasticsearchClient elasticsearchClient() {
CredentialsProvider credentialsProvider =
new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("elastic", "password"));
// 第一步生成的证书所在的位置
Path caCertificatePath = Paths.get("/elastic_install_home/config/ca.crt");
CertificateFactory factory =
CertificateFactory.getInstance("X.509");
Certificate trustedCa;
try (InputStream is = Files.newInputStream(caCertificatePath)) {
trustedCa = factory.generateCertificate(is);
}
KeyStore trustStore = KeyStore.getInstance("pkcs12");
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", trustedCa);
SSLContextBuilder sslContextBuilder = SSLContexts.custom()
.loadTrustMaterial(trustStore, null);
SSLContext sslContext = sslContextBuilder.build();
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "https"))
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
// 设置ssl
.setSSLContext(sslContext)
.setDefaultCredentialsProvider(credentialsProvider));
RestClient restClient = builder.build();
ElasticsearchTransport elasticsearchTransport = new RestClientTransport(restClient, new JacksonJsonpMapper());
return new ElasticsearchClient(elasticsearchTransport);
}
}
写一个Test Case验证下即可。
上述代码中,只有一个节点,如果是多个节点的话,不需要我们在自己的代码里做负载均衡,Elasticsearch Java Client负责
The client sends each request to one of the configured nodes in round-robin fashion
到此为止,为Elasticsearch启动TLS并使用Java代码连接就完毕了。
另一种终极解决方案
如果你不想上面这么麻烦,想直接用HTTP,但是又是生产环境。一个比较省时又省力的方式是利用各种代理或者负载均衡。
将暴露出的域名最终映射到后端的http上面.虽然实际上还是http,不过在表面上看来是HTTPS了
2022年9月22日更新
此解决方案只适合单节点的Elasticsearch,集群环境下此方案失效,必须为各节点配置证书,下文引自官方文档
To secure your cluster, you must ensure that internode communications are encrypted and verified, which is achieved with mutual TLS.
流程总结
以下流程可在官方文档这里找到
生成证书使用的elasticesearch-certutil命令
- 生成ca证书,此证书可以是PEM文件或PCKS#12格式的;PEM文件会生成两个文件ca.crt和ca.key;而PCKS#12会生成一个文件ca.p12
- 基于第一步的证书,为集群各个节点之间通信生成证书,使用cert mode
- 基于第一步的证书,为Kibana、Logstash、Java Client与Elasticsearch之间通信生成证书,使用http mode
本文只提供了基于PEM文件的示例,读者可根据上述流程总结与文末给出的文档,生成PCKS#12的证书,再配置即可。
个人建议使用PCKS#12格式的证书文件,同时使用Adopt OpenJDK各版本(8、11、17)最新的版本
直接使用Elasticsearch官方脚本
如果只是本地学习使用,想要快速在本地大家一个三节点的集群。 可以直接使用官方提供的docker-compose.yml文件。只需要改动几个配置,即可快速启动一个集群,非常方便。
在官方文档里,提供了具有三个节点的集群的docker-compose.yml文件,本地可直接使用官方脚本。
官方文档地址
注意:官方文档中,docker-compose.yml中只有es01的9200端口暴露了出来
示例代码仓库
官方文档
强烈建议把下面的官方文档通读一边,尤其是第一次配置的同学,里面的步骤基本很详细了。而且也更详细介绍了各个配置的作用、目的。
更多推荐
所有评论(0)