Kaydet (Commit) 116d1370 authored tarafından Joffrey F's avatar Joffrey F

* Merge branch 'tls' of github.com:momer/docker-py into momer-tls

* Exported TLS configuration in tls.TLSConfig
* Merged exceptions packagee into pre-existing errors module
* Flake8 fixes
* Bug fixes
......@@ -24,8 +24,10 @@ import six
from .auth import auth
from .unixconn import unixconn
from .ssladapter import ssladapter
from .utils import utils
from . import errors
from .tls import TLSConfig
if not six.PY3:
import websocket
......@@ -37,10 +39,15 @@ STREAM_HEADER_SIZE_BYTES = 8
class Client(requests.Session):
def __init__(self, base_url=None, version=DEFAULT_DOCKER_API_VERSION,
timeout=DEFAULT_TIMEOUT_SECONDS):
timeout=DEFAULT_TIMEOUT_SECONDS, tls=False):
super(Client, self).__init__()
if base_url is None:
base_url = "http+unix://var/run/docker.sock"
if tls and not base_url.startswith('https://'):
raise errors.TLSParameterError(
'If using TLS, the base_url argument must begin with '
'"https://".')
if 'unix:///' in base_url:
base_url = base_url.replace('unix:/', 'unix:')
if base_url.startswith('unix:'):
......@@ -54,7 +61,13 @@ class Client(requests.Session):
self._timeout = timeout
self._auth_configs = auth.load_config()
self.mount('http+unix://', unixconn.UnixAdapter(base_url, timeout))
""" Use SSLAdapter for the ability to specify SSL version """
if isinstance(tls, TLSConfig):
tls.configure_client(self)
elif tls:
self.mount('https://', ssladapter.SSLAdapter(self.ssl_version))
else:
self.mount('http+unix://', unixconn.UnixAdapter(base_url, timeout))
def _set_request_timeout(self, kwargs):
"""Prepare the kwargs for an HTTP request by inserting the timeout
......
......@@ -63,3 +63,14 @@ class InvalidConfigFile(DockerException):
class DeprecatedMethod(DockerException):
pass
class TLSParameterError(DockerException):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg + (". TLS configurations should map the Docker CLI "
"client configurations. See "
"http://docs.docker.com/examples/https/ for "
"API details.")
from .ssladapter import SSLAdapter # flake8: noqa
""" Resolves OpenSSL issues in some servers:
https://lukasa.co.uk/2013/01/Choosing_SSL_Version_In_Requests/
https://github.com/kennethreitz/requests/pull/799
"""
from requests.adapters import HTTPAdapter
try:
from requests.packages.urllib3.poolmanager import PoolManager
except ImportError:
from urllib3.poolmanager import PoolManager
class SSLAdapter(HTTPAdapter):
'''An HTTPS Transport Adapter that uses an arbitrary SSL version.'''
def __init__(self, ssl_version=None, **kwargs):
self.ssl_version = ssl_version
super(SSLAdapter, self).__init__(**kwargs)
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(num_pools=connections,
maxsize=maxsize,
block=block,
ssl_version=self.ssl_version)
import os
from . import errors
from .ssladapter import ssladapter
class TLSConfig(object):
def __init__(self, tls, tls_cert=None, tls_key=None, tls_verify=False,
tls_ca_cert=None, ssl_version=None):
# Argument compatibility/mapping with
# http://docs.docker.com/examples/https/
# This diverges from the Docker CLI in that users can specify 'tls'
# here, but also disable any public/default CA pool verification by
# leaving tls_verify=False
# urllib3 sets a default ssl_version if ssl_version is None
# http://tinyurl.com/kxga8hb
self.ssl_version = ssl_version
# "tls" and "tls_verify" must have both or neither cert/key files
# In either case, Alert the user when both are expected, but any are
# missing.
if tls_cert or tls_key:
if not (tls_cert and tls_key) or (not os.path.isfile(tls_cert) or
not os.path.isfile(tls_key)):
raise errors.TLSParameterError(
'You must provide either both "tls_cert"/"tls_key" files, '
'or neither, in order to use TLS.')
self.cert = (tls_cert, tls_key)
# Either set tls_verify to True (public/default CA checks) or to the
# path of a CA Cert file.
if tls_verify:
if not tls_ca_cert:
self.verify = True
elif os.path.isfile(tls_ca_cert):
self.verify = tls_ca_cert
else:
raise errors.TLSParameterError(
'If "tls_verify" is set, then "tls_ca_cert" must be blank'
' (to check public CA list) OR a path to a Cert File.'
)
else:
self.verify = False
def configure_client(self, client):
client.verify = self.verify
client.ssl_version = self.ssl_version
client.cert = self.cert
self.mount('https://', ssladapter.SSLAdapter(self.ssl_version))
......@@ -22,7 +22,8 @@ setup(
name="docker-py",
version=version,
description="Python client for Docker.",
packages=['docker', 'docker.auth', 'docker.unixconn', 'docker.utils'],
packages=['docker', 'docker.auth', 'docker.unixconn', 'docker.utils',
'docker.ssladapter'],
install_requires=requirements + test_requirements,
zip_safe=False,
test_suite='tests',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment