pythonelasticsearchssl

Configuring ElasticSearch SSL and Python Querying, Certificates Question


I have certificates from GoDaddy for my ElasticSearch instance. I'm trying to set it up and below I have the configuration for SSL. I can hit this via the browser easily and everything is fine. If I use the Python ElasticSearch package then I start getting SSL errors where it's "unable to get local issuer certificates".

I create the ElasticSearch connection object like so:

import elasticsearch as es
obj = es.Elasticsearch('https://elasticsearch.foo.com:9200', http_auth=('elastic', 'password'))

and it throws an error unless I include ca_certs='certs/gd_bundle-g2-g1.crt' in the function call. These are the intermediate and root certificates from GoDaddy. It seems very wrong to me that I have to include a reference to these certificates on the client side in my code. Is this correct? Isn't the xpack.security.http.ssl.certificate_authorities supposed to cover this and maybe magically send them over?

elasticsearch.yml

    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"]

Without ca_certs

>>> obj = es.Elasticsearch('https://elasticsearch.foo.com:9200', verify_certs=True, http_auth=('username', 'password'))
>>> 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))
INFO

With 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')
>>> obj.ping()

INFO:elastic_transport.transport:HEAD https://elasticsearch.foo.com:9200/ [status:200 duration:0.159s]
True

Solution

  • Okay, it seems that doing it this way is the default way to do it according to elasticsearch documentation: https://www.elastic.co/guide/en/elasticsearch/client/python-api/master/connecting.html