Skip to content

Commit 5c537de

Browse files
authored
Merge pull request elastic#635 from fxdgear/nick/ssl_context
Nick/ssl context
2 parents 9790b85 + 7339a27 commit 5c537de

File tree

5 files changed

+88
-25
lines changed

5 files changed

+88
-25
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ before_install:
2424
- java -version
2525

2626
install:
27-
- curl -L -o /tmp/es-snap.zip https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.0.0-beta2.zip
27+
- curl -L -o /tmp/es-snap.zip https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.0.0-rc1.zip
2828
- unzip /tmp/es-snap.zip -d /tmp/
29-
- /tmp/elasticsearch-*/bin/elasticsearch -E script.inline=true -E path.repo=/tmp -E repositories.url.allowed_urls='http://*' -E node.attr.testattr=test -d
29+
- /tmp/elasticsearch-*/bin/elasticsearch -E path.repo=/tmp -E repositories.url.allowed_urls='http://*' -E node.attr.testattr=test -d
3030
- git clone https://github.com/elastic/elasticsearch.git ../elasticsearch
3131
- pip install .
3232

docs/connection.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,15 @@ Connection Selector
4545
Urllib3HttpConnection (default connection_class)
4646
------------------------------------------------
4747

48+
Deprecation Notice: `use_ssl`, `verify_certs`, `ca_certs` and `ssl_version` are being
49+
deprecated in favor of using a `SSLContext` (https://docs.python.org/3/library/ssl.html#ssl.SSLContext) object.
50+
51+
You can continue to use the deprecated parameters and an `SSLContext` will be created for you.
52+
53+
If you want to create your own `SSLContext` object you can create one natively using the
54+
python SSL library with the `create_default_context` (https://docs.python.org/3/library/ssl.html#ssl.create_default_context) method
55+
or you can use the wrapper function :function:`~elasticsearch.connection.http_urllib3.create_ssl_context`.
56+
57+
4858
.. autoclass:: Urllib3HttpConnection
4959
:members:

elasticsearch/connection/http_urllib3.py

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import time
2+
import ssl
23
import urllib3
34
from urllib3.exceptions import ReadTimeoutError, SSLError as UrllibSSLError
45
import warnings
@@ -15,6 +16,19 @@
1516
from ..exceptions import ConnectionError, ImproperlyConfigured, ConnectionTimeout, SSLError
1617
from ..compat import urlencode
1718

19+
20+
def create_ssl_context(**kwargs):
21+
"""
22+
A helper function around creating an SSL context
23+
24+
https://docs.python.org/3/library/ssl.html#context-creation
25+
26+
Accepts kwargs in the same manner as `create_default_context`.
27+
"""
28+
ctx = ssl.create_default_context(**kwargs)
29+
return ctx
30+
31+
1832
class Urllib3HttpConnection(Connection):
1933
"""
2034
Default connection class using the `urllib3` library and the http protocol.
@@ -47,7 +61,7 @@ class Urllib3HttpConnection(Connection):
4761
def __init__(self, host='localhost', port=9200, http_auth=None,
4862
use_ssl=False, verify_certs=True, ca_certs=None, client_cert=None,
4963
client_key=None, ssl_version=None, ssl_assert_hostname=None,
50-
ssl_assert_fingerprint=None, maxsize=10, headers=None, **kwargs):
64+
ssl_assert_fingerprint=None, maxsize=10, headers=None, ssl_context=None, **kwargs):
5165

5266
super(Urllib3HttpConnection, self).__init__(host=host, port=port, use_ssl=use_ssl, **kwargs)
5367
self.headers = urllib3.make_headers(keep_alive=True)
@@ -62,33 +76,49 @@ def __init__(self, host='localhost', port=9200, http_auth=None,
6276
self.headers[k.lower()] = headers[k]
6377

6478
self.headers.setdefault('content-type', 'application/json')
65-
ca_certs = CA_CERTS if ca_certs is None else ca_certs
6679
pool_class = urllib3.HTTPConnectionPool
6780
kw = {}
68-
if use_ssl:
81+
82+
# if providing an SSL context, raise error if any other SSL related flag is used
83+
if ssl_context and (verify_certs or ca_certs or ssl_version):
84+
raise ImproperlyConfigured("When using `ssl_context`, `use_ssl`, `verify_certs`, `ca_certs` and `ssl_version` are not permitted")
85+
86+
# if ssl_context provided use SSL by default
87+
if use_ssl or ssl_context:
88+
if not ca_certs and not ssl_context and verify_certs:
89+
# If no ca_certs and no sslcontext passed and asking to verify certs
90+
# raise error
91+
raise ImproperlyConfigured("Root certificates are missing for certificate "
92+
"validation. Either pass them in using the ca_certs parameter or "
93+
"install certifi to use it automatically.")
94+
if verify_certs or ca_certs or ssl_version:
95+
warnings.warn('Use of `verify_certs`, `ca_certs`, `ssl_version` have been deprecated in favor of using SSLContext`', DeprecationWarning)
6996
pool_class = urllib3.HTTPSConnectionPool
97+
98+
if not ssl_context:
99+
# if SSLContext hasn't been passed in, create one.
100+
cafile = CA_CERTS if ca_certs is None else ca_certs
101+
# need to skip if sslContext isn't avail
102+
try:
103+
ssl_context = create_ssl_context(cafile=cafile)
104+
except AttributeError:
105+
ssl_context = None
106+
107+
if not verify_certs and ssl_context is not None:
108+
ssl_context.check_hostname = False
109+
ssl_context.verify_mode = ssl.CERT_NONE
110+
warnings.warn(
111+
'Connecting to %s using SSL with verify_certs=False is insecure.' % host)
112+
70113
kw.update({
71114
'ssl_version': ssl_version,
72115
'assert_hostname': ssl_assert_hostname,
73116
'assert_fingerprint': ssl_assert_fingerprint,
117+
'ssl_context': ssl_context,
118+
'cert_file': client_cert,
119+
'ca_certs': ca_certs,
120+
'key_file': client_key,
74121
})
75-
76-
if verify_certs:
77-
if not ca_certs:
78-
raise ImproperlyConfigured("Root certificates are missing for certificate "
79-
"validation. Either pass them in using the ca_certs parameter or "
80-
"install certifi to use it automatically.")
81-
82-
kw.update({
83-
'cert_reqs': 'CERT_REQUIRED',
84-
'ca_certs': ca_certs,
85-
'cert_file': client_cert,
86-
'key_file': client_key,
87-
})
88-
else:
89-
warnings.warn(
90-
'Connecting to %s using SSL with verify_certs=False is insecure.' % host)
91-
92122
self.pool = pool_class(host, port=port, timeout=self.timeout, maxsize=maxsize, **kw)
93123

94124
def perform_request(self, method, url, params=None, body=None, timeout=None, ignore=(), headers=None):

test_elasticsearch/test_connection.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import sys
12
import re
3+
import ssl
24
from mock import Mock, patch
35
import urllib3
46
import warnings
@@ -7,8 +9,9 @@
79
from elasticsearch.exceptions import TransportError, ConflictError, RequestError, NotFoundError
810
from elasticsearch.connection import RequestsHttpConnection, \
911
Urllib3HttpConnection
10-
11-
from .test_cases import TestCase
12+
from elasticsearch.exceptions import ImproperlyConfigured
13+
from elasticsearch.connection.http_urllib3 import create_ssl_context
14+
from .test_cases import TestCase, SkipTest
1215

1316

1417
class TestUrllib3Connection(TestCase):
@@ -42,6 +45,12 @@ def test_http_auth_list(self):
4245
'connection': 'keep-alive'}, con.headers)
4346

4447
def test_uses_https_if_verify_certs_is_off(self):
48+
if (
49+
sys.version_info >= (3,0) and sys.version_info <= (3,4)
50+
) or (
51+
sys.version_info >= (2,6) and sys.version_info <= (2,7)
52+
):
53+
raise SkipTest("SSL Context not supported in this version of python")
4554
with warnings.catch_warnings(record=True) as w:
4655
con = Urllib3HttpConnection(use_ssl=True, verify_certs=False)
4756
self.assertEquals(1, len(w))
@@ -53,6 +62,16 @@ def test_doesnt_use_https_if_not_specified(self):
5362
con = Urllib3HttpConnection()
5463
self.assertIsInstance(con.pool, urllib3.HTTPConnectionPool)
5564

65+
def test_ssl_context_and_depreicated_values(self):
66+
try:
67+
ctx = create_ssl_context()
68+
except AttributeError:
69+
raise SkipTest("SSL Context not supported in this version of python")
70+
self.assertRaises(ImproperlyConfigured, Urllib3HttpConnection, ssl_context=ctx, use_ssl=True)
71+
self.assertRaises(ImproperlyConfigured, Urllib3HttpConnection, ssl_context=ctx, verify_certs=True)
72+
self.assertRaises(ImproperlyConfigured, Urllib3HttpConnection, ssl_context=ctx, ca_certs="/some/path/to/cert.crt")
73+
self.assertRaises(ImproperlyConfigured, Urllib3HttpConnection, ssl_context=ctx, ssl_version=ssl.PROTOCOL_SSLv23)
74+
5675
class TestRequestsConnection(TestCase):
5776
def _get_mock_connection(self, connection_params={}, status_code=200, response_body='{}'):
5877
con = RequestsHttpConnection(**connection_params)

test_elasticsearch/test_server/test_common.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@
4040
'*': set(('TestBulk10Basic', 'TestCatSnapshots10Basic',
4141
'TestClusterPutSettings10Basic', 'TestIndex10WithId',
4242
'TestClusterPutScript10Basic', 'TestIndicesPutMapping10Basic',
43-
'TestIndicesPutTemplate10Basic', 'TestMsearch10Basic'))
43+
'TestIndicesPutTemplate10Basic', 'TestMsearch10Basic',
44+
# skip these two till https://github.com/elastic/elasticsearch/pull/26905 has been merged
45+
'TestSearchAggregation190PercentilesHdrMetric',
46+
'TestSearchAggregation180PercentilesTdigestMetric',
47+
))
4448

4549
}
4650

0 commit comments

Comments
 (0)