Elasticsearch 提供了多种数据访问安全的方式,如用户名密码校验、api_key 等。但是依然无法保障数据传输过程中的安全性问题。而 HTTPS 协议,则是一种以安全为目的的 HTTP 通道,在 HTTP 的基础上通过传输加密和身份认证等机制来保障数据传输过程中的安全性。本文将基于腾讯云 ES 集群环境,演示 Beats、Logstash、Kibana 和 Java Client 等客户端访问连接开启了 HTTPS 协议的 ES 集群。
HTTPS 集群环境准备
创建 HTTPS 协议集群
首先我们在腾讯云 ES 控制台创建出一个 HTTPS 集群,在购买页这里勾选上 HTTPS 协议。目前该特性目前是通过白名单支持,可 提交工单 申请开放。
?
其中,ES 通过在 elasticsearch.yml 配置文件中设置特定参数来启用 HTTPS 协议的,参数如下所示:xpack.security.http.ssl.enabled: truexpack.security.http.ssl.keystore.path: certs/ces-certificates.p12xpack.security.http.ssl.truststore.path: certs/ces-certificates.p12
获取 pem 证书文件
?
?
?此时腾讯云 ES侧会提供如下两个证书文件:
文件名称 | 用途 |
client-certificates.pem | 用于 Beats Logstash、Java Client 连接 ES 集群 |
server-certificates.pem | 用于 Kibana 连接 ES 集群 |
下面将详细介绍 Beats、Logstash、Kibana 和 Java 等客户端连接 HTTPS 集群的配置方式。
Beats 输出到 HTTPS 集群
CVM Metricbeat 输出到 ES
我们首先在腾讯云 CVM 控制台 创建一个和 ES 集群同 VPC 下的 CVM,创建好后,将得到的 pem 鉴权文件上传到该 CVM 上,这里的存放路径为:/usr/local/service/https-certs。随后到腾讯云 ES 控制台 的 Beats 管理页,创建一个 Metricbeat。
?
其中,最核心的步骤是在 metricbeat.yml 配置文件中进行如下配置。output.elasticsearch:hosts: ["https://ES-VIP:9200"]username: "elastic"password: "changeme"ssl.certificate_authorities: ["/usr/local/service/https-certs/client-certificates.pem"]ssl.verification_mode: certificate
配置信息说明:
配置项 | 说明 |
hosts | ES 集群的 VIP,如 https://10.0.X.29:9200 ,以 https 开头 |
username/password | ES 集群的用户名密码 |
ssl.certificate_authorities | 连接 HTTPS 集群所需的 pem 鉴权证书文件路径 |
ssl.verification_mode | 服务器证书认证模式,有四种模式,分别是 full,strict,certificate 和 none。我们这里以 certificate 模式进行认证,即只认证 CA 证书,不认证主机名信息。详情可参考官方文档。 |
配置完成后,即可在 ES 集群的Cerebro或者Kibana中看到自动创建了一个 metricbeat-7.14.20-*开头的索引,到此 CVM 中 Metricbeat 连接 HTTPS 的 ES 集群配置完成。
?
?TKE Filebeat 日志采集器输出到 ES
TKE Filebeat 日志采集器输出到 HTTPS 的 ES 集群流程和 CVM 的 Metricbeat 输出一样,首先我们将 pem 文件上传到创建 TKE 集群时自动创建的 Worker 所在的 CVM 节点上,如 /var/log/https-certs 目录下。
?
?
client-certificates.pem 文件存放位置:
?
随后我们在腾讯云 ES 控制台新建 Fliebeat 采集器,这里选择 TKE 日志采集:?
?
?下面进行 Filebeat 采集器的基本信息配置,选择版本号、采集器输出 ES 集群。如下图所示:
?
?开始配置采集来源,如下图所示:
?
?
单击编辑 yaml 后,对 output.elasticsearch 配置项进行修改,如下图所示:?
?
?具体配置信息如下,配置信息说明同 Metricbeat 一致。
output.elasticsearch:hosts: ['https://ES-VIP:9200']username: "elastic"ssl.certificate_authorities: ["/var/log/https-certs/client-certificates.pem"]ssl.verification_mode: "certificate"password: "changeme"indices:- index: "filebeat-tke-%{+yyyy.MM.dd}"when.equals:tke_collector_target_name: "logs_to_https_es"
?
?
进入到 Pod 管理页,选择对应的 Pod 销毁重建。?
?
销毁重建后,Pod 的运行状态变成 Running,如下图所示。 ?
注意
如果多次对 pod 进行销毁重建,仍是红色 Running,有可能是 beats 的 yml 配置出现问题,可以在日志里面查看具体问题,或者重新检查一下 yml 配置是否错误。
?
?
随后我们到 ES 集群中,可以看到自动创建了以 filebeat-tke-*开头的索引。表明 TKE 日志顺利输出到 HTTPS 集群中了。
?
?Logstash 输出到 HTTPS 集群
?
?
?进入 Logstash 管理 > 高级配置界面,点击本地上传按钮。
?
?
随后我们在管道管理tab下,点击新建管道按钮,新建一个管道,在管道的 Config 配置编辑框里配置上 ES 的连接信息和证书路径。?
?
管道详细配置文本信息如下:output {elasticsearch {hosts => ["https://ES-VIP:9200"]user => "elastic"password => "changeme"ssl => truecacert => "/usr/local/service/logstash/extended-files/client-certificates.pem"ssl_certificate_verification => false}}
其中 cacert 即可我们上一步上传的扩展文件 pem 的路径,固定路径为:
/usr/local/service/logstash/extended-files/client-certificates.pem
。其他配置说明同 Metricbeat 一致。
点击保存并部署管道后,即可在管道列表查看我们刚新建管道信息,此时状态为运行中。?
?
??
这时候我们再到 HTTPS 集群中就可以看到有数据从 input 的集群中写入进来了。
Kibana 连接 HTTPS 集群
腾讯云 ES 集群默认自带 Kibana 访问能力,因此一般情况下,客户是不需要对 Kibana 进行任何配置的。这里介绍自建 Kibana 连接 HTTPS 集群的配置方式。和 Beats、Logstash 等使用的客户端鉴权证书不一样,Kibana 使用的是 server-certificates.pem,腾讯云 ES 侧在 CVM 中生成证书命令如下:
openssl pkcs12 -in ces-certificates.p12 -password pass:xxxxxx -nokeys -cacerts -out server-certificates.pem
由于前面我们已经拿到了 pem 证书文件。因此,我们将 server-certificates.pem 文件拷贝到 Kibana 所在节点的如下路径:
/usr/local/service/https-certs
。然后修改 kibana.yml 配置文件如下:elasticsearch.hosts: ["https://ES-VIP:9200"]elasticsearch.username: "elastic"elasticsearch.password: "changeme"elasticsearch.ssl.verificationMode: certificateelasticsearch.ssl.certificateAuthorities: ["/usr/local/service/https-certs/server-certificates.pem"]xpack.encryptedSavedObjects.encryptionKey: "dfed624ca4014135f61804440536xxxx"xpack.fleet.registryUrl: "https://epr.elastic.co"
配置项说明:
elasticsearch.ssl.certificateAuthorities: pem 文件的存放路径。
elasticsearch.ssl.verificationMode: 证书鉴权模式,certificate 采用只鉴权 CA 证书,不鉴权主机名称的模式。
xpack.fleet.registryUrl: (非必选配置)Fleet 集成模块需要访问的公网仓库,这里需要 Kibana 节点具备公网访问能力。
xpack.encryptedSavedObjects.encryptionKey: value 可以通过Kibana上执行
bin/kibana-encryption-keys generate
命令获得。
?
重新启动 Kibana 后,即可正常访问 HTTPS 的 ES 集群了。Java Client 连接 HTTPS 集群
本文档演示在 Spring 项目中访问 HTTPS 集群的配置方式,首先需要添加如下 maven 依赖:
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.10.1</version></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.10.1</version></dependency><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.10.1</version></dependency>
随后我们在 ElasticsearchConfig 自定义类中实现对 Elasticsearch 连接的配置。
@Configurationpublic class ElasticsearchConfig {@Value("${es.username}")private String userName;@Value("${es.password}")private String password;@Value("${es.scheme}")private String scheme;@Value("${es.domain}")private String domain;@Value("${es.https.cert}")private String certFile;@Value("${es.port}")private int port;private RestHighLevelClient client;@Beanpublic RestHighLevelClient EsConnectInit() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(userName,password));RestClientBuilder builder;if (scheme.equals("https")) {Path caCertificatePath = Paths.get(certFile);System.out.println(certFile);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, new TrustStrategy() {@Overridepublic boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {return true;}});final SSLContext sslContext = sslContextBuilder.build();final HostnameVerifier hostnameVerifier = new HostnameVerifier() {public boolean verify(String hostname, SSLSession session) {return true;}};builder = RestClient.builder(new HttpHost(domain, port, scheme)).setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {@Overridepublic RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {requestConfigBuilder.setConnectTimeout(-1);requestConfigBuilder.setSocketTimeout(-1);requestConfigBuilder.setConnectionRequestTimeout(-1);return requestConfigBuilder;}}).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {@Overridepublic HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {httpClientBuilder.disableAuthCaching();httpClientBuilder.setSSLHostnameVerifier(hostnameVerifier);return httpClientBuilder.setSSLContext(sslContext).setDefaultCredentialsProvider(credentialsProvider);?}});} else {builder = RestClient.builder(new HttpHost(domain, port, scheme)).setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {@Overridepublic RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {requestConfigBuilder.setConnectTimeout(-1);requestConfigBuilder.setSocketTimeout(-1);requestConfigBuilder.setConnectionRequestTimeout(-1);return requestConfigBuilder;}}).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {@Overridepublic HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { httpClientBuilder.disableAuthCaching();return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);}});}client = new RestHighLevelClient(builder);return client;}}
其中 Elasticsearch 的配置信息如下:
es.scheme=https # 协议https或者httpes.port=9200 # ES集群VIP的端口es.domain=9.10.1.X # ES集群的VIPes.username=elastic # ES集群的用户名es.password=changeme # ES集群的密码es.https.cert=/usr/local/services/certs/client-certificates.pem # 连接HTTPS集群所需的pem鉴权证书文件路径
通过如上配置后,即可在 Spring 项目中成功连接上开启了 HTTPS 协议的 ES 集群了。