Support SSL URL parameters correctly for rediss protocol (#1002)

* fixed rediss url parsing

* added ssl parameter test

* added ssl parameter test

* added ssl parameter test

* added ssl parameter test

* added ssl parameter test

* added no ssl module parse_url test

* added no ssl module parse_url test

* added no ssl module parse_url test

* convert to list comprehension

* simulate no ssl in test

* add missing logger
This commit is contained in:
Paul Bailey 2019-02-21 07:38:03 +00:00 committed by Omer Katz
parent 844d8d0673
commit 30f52ad329
2 changed files with 55 additions and 0 deletions

View File

@ -15,12 +15,19 @@ try:
except ImportError:
from urllib import quote, unquote # noqa
from urlparse import urlparse, parse_qsl # noqa
try:
import ssl
ssl_available = True
except ImportError: # pragma: no cover
ssl_available = False
from kombu.five import bytes_if_py2, string_t
from .compat import NamedTuple
from ..log import get_logger
safequote = partial(quote, safe=bytes_if_py2(''))
logger = get_logger(__name__)
urlparts = NamedTuple('urlparts', [
@ -38,6 +45,22 @@ def parse_url(url):
# type: (str) -> Dict
"""Parse URL into mapping of components."""
scheme, host, port, user, password, path, query = _parse_url(url)
if query:
keys = [key for key in query.keys() if key.startswith('ssl_')]
for key in keys:
if key == 'ssl_cert_reqs':
if ssl_available:
query[key] = getattr(ssl, query[key])
else:
query[key] = None
logger.warn('Defaulting to insecure SSL behaviour.')
if 'ssl' not in query:
query['ssl'] = {}
query['ssl'][key] = query[key]
del query[key]
return dict(transport=scheme, hostname=host,
port=port, userid=user,
password=password, virtual_host=path, **query)

View File

@ -1,7 +1,16 @@
from __future__ import absolute_import, unicode_literals
try:
from urllib.parse import urlencode
except ImportError:
from urllib import urlencode
import ssl
import pytest
import kombu.utils.url
from kombu.utils.url import as_url, parse_url, maybe_sanitize_url
@ -37,3 +46,26 @@ def test_maybe_sanitize_url(url, expected):
assert maybe_sanitize_url(url) == expected
assert (maybe_sanitize_url('http://u:p@e.com//foo') ==
'http://u:**@e.com//foo')
def test_ssl_parameters():
url = 'rediss://user:password@host:6379/0?'
querystring = urlencode({
'ssl_cert_reqs': 'CERT_REQUIRED',
'ssl_ca_certs': '/var/ssl/myca.pem',
'ssl_certfile': '/var/ssl/server-cert.pem',
'ssl_keyfile': '/var/ssl/priv/worker-key.pem',
})
kwargs = parse_url(url + querystring)
assert kwargs['transport'] == 'rediss'
assert kwargs['ssl']['ssl_cert_reqs'] == ssl.CERT_REQUIRED
assert kwargs['ssl']['ssl_ca_certs'] == '/var/ssl/myca.pem'
assert kwargs['ssl']['ssl_certfile'] == '/var/ssl/server-cert.pem'
assert kwargs['ssl']['ssl_keyfile'] == '/var/ssl/priv/worker-key.pem'
kombu.utils.url.ssl_available = False
kwargs = parse_url(url + querystring)
assert kwargs['ssl']['ssl_cert_reqs'] is None
kombu.utils.url.ssl_available = True