ElasticSearch SSL 与 Python 查询的配置及证书问题解决方案
问题描述
在 Python 中创建 ElasticSearch 连接对象时,我的代码如下:
import elasticsearch as es
obj = es.Elasticsearch(
'https://elasticsearch.foo.com:9200',
http_auth=('elastic', 'password')
)
然而,如果没有包含 CA 证书的路径,我会遇到如下错误:
elastic_transport.TlsError: TLS error caused by: SSLError([SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1125))
这个问题主要与 GoDaddy 提供的中间证书和根证书有关。如果我在代码中手动指定证书路径,如下所示:
obj = es.Elasticsearch(
'https://elasticsearch.foo.com:9200',
http_auth=('username', 'password'),
ca_certs='certs/gd_bundle-g2-g1.crt'
)
这样可以正常连接,但总感觉把证书路径硬编码在代码里不太合适。我想知道是否有更优雅的方式,例如使用 elasticsearch.yml
中的配置来解决这个问题。
elasticsearch.yml
配置
下面是我在 ElasticSearch 实例中的配置文件内容:
xpack.security.http.ssl.verification_mode: full
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.key: /usr/share/elasticsearch/config/elasticsearch.foo.key
xpack.security.http.ssl.certificate: /usr/share/elasticsearch/config/elasticsearch.foo.crt
xpack.security.http.ssl.certificate_authorities: ["/usr/share/elasticsearch/config/gd_bundle-g2-g1.crt"]
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.key: /usr/share/elasticsearch/config/elasticsearch.foo.key
xpack.security.transport.ssl.certificate: /usr/share/elasticsearch/config/elasticsearch.foo.crt
xpack.security.transport.ssl.certificate_authorities: ["/usr/share/elasticsearch/config/gd_bundle-g2-g1.crt"]
根据配置文件,我希望通过 xpack.security.http.ssl.certificate_authorities
自动加载证书。但实际情况并非如此,除非我在 Python 代码中明确指定 ca_certs
,否则连接会失败。
代码运行结果对比
未使用 ca_certs
时:
obj = es.Elasticsearch(
'https://elasticsearch.foo.com:9200',
verify_certs=True,
http_auth=('username', 'password')
)
print(obj.ping())
错误信息:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/elastic_transport/_transport.py", line 329, in perform_request
meta, raw_data = node.perform_request(
File "/usr/local/lib/python3.8/site-packages/elastic_transport/_node/_http_urllib3.py", line 199, in perform_request
raise err from None
elastic_transport.TlsError: TLS error caused by: SSLError([SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1125))
使用 ca_certs
时:
obj = es.Elasticsearch(
'https://elasticsearch.foo.com:9200',
verify_certs=True,
http_auth=('username', 'password'),
ca_certs='certs/gd_bundle-g2-g1.crt'
)
print(obj.ping())
输出:
INFO:elastic_transport.transport:HEAD https://elasticsearch.foo.com:9200/ [status:200 duration:0.159s]
True
0