Przeglądaj źródła

Update TLS version configuration code. Tests.

Signed-off-by: Joffrey F <[email protected]>
Joffrey F 9 lat temu
rodzic
commit
e7a8b2fed5

+ 22 - 2
compose/cli/command.py

@@ -4,6 +4,7 @@ from __future__ import unicode_literals
 import logging
 import os
 import re
+import ssl
 
 import six
 
@@ -46,10 +47,28 @@ def get_config_path_from_options(base_dir, options, environment):
     return None
 
 
-def get_client(environment, verbose=False, version=None, tls_config=None, host=None):
+def get_tls_version(environment):
+    compose_tls_version = environment.get('COMPOSE_TLS_VERSION', None)
+    if not compose_tls_version:
+        return None
+
+    tls_attr_name = "PROTOCOL_{}".format(compose_tls_version)
+    if not hasattr(ssl, tls_attr_name):
+        log.warn(
+            'The {} protocol is unavailable. You may need to update your '
+            'version of Python or OpenSSL. Falling back to TLSv1 (default).'
+        )
+        return None
+
+    return getattr(ssl, tls_attr_name)
+
+
+def get_client(environment, verbose=False, version=None, tls_config=None, host=None,
+               tls_version=None):
+
     client = docker_client(
         version=version, tls_config=tls_config, host=host,
-        environment=environment
+        environment=environment, tls_version=get_tls_version(environment)
     )
     if verbose:
         version_info = six.iteritems(client.version())
@@ -74,6 +93,7 @@ def get_project(project_dir, config_path=None, project_name=None, verbose=False,
     api_version = environment.get(
         'COMPOSE_API_VERSION',
         API_VERSIONS[config_data.version])
+
     client = get_client(
         verbose=verbose, version=api_version, tls_config=tls_config,
         host=host, environment=environment

+ 3 - 2
compose/cli/docker_client.py

@@ -39,7 +39,8 @@ def tls_config_from_options(options):
     return None
 
 
-def docker_client(environment, version=None, tls_config=None, host=None):
+def docker_client(environment, version=None, tls_config=None, host=None,
+                  tls_version=None):
     """
     Returns a docker-py client configured using environment variables
     according to the same logic as the official Docker client.
@@ -49,7 +50,7 @@ def docker_client(environment, version=None, tls_config=None, host=None):
                  "Please use COMPOSE_HTTP_TIMEOUT instead.")
 
     try:
-        kwargs = kwargs_from_env(environment=environment)
+        kwargs = kwargs_from_env(environment=environment, ssl_version=tls_version)
     except TLSParameterError:
         raise UserError(
             "TLS configuration is invalid - make sure your DOCKER_TLS_VERIFY "

+ 5 - 0
docs/reference/envvars.md

@@ -78,6 +78,11 @@ Configures the path to the `ca.pem`, `cert.pem`, and `key.pem` files used for TL
 Configures the time (in seconds) a request to the Docker daemon is allowed to hang before Compose considers
 it failed. Defaults to 60 seconds.
 
+## COMPOSE\_TLS\_VERSION
+
+Configure which TLS version is used for TLS communication with the `docker`
+daemon. Defaults to `TLSv1`.
+Supported values are: `TLSv1`, `TLSv1_1`, `TLSv1_2`.
 
 ## Related Information
 

+ 19 - 0
tests/unit/cli/command_test.py

@@ -2,10 +2,12 @@ from __future__ import absolute_import
 from __future__ import unicode_literals
 
 import os
+import ssl
 
 import pytest
 
 from compose.cli.command import get_config_path_from_options
+from compose.cli.command import get_tls_version
 from compose.config.environment import Environment
 from compose.const import IS_WINDOWS_PLATFORM
 from tests import mock
@@ -46,3 +48,20 @@ class TestGetConfigPathFromOptions(object):
     def test_no_path(self):
         environment = Environment.from_env_file('.')
         assert not get_config_path_from_options('.', {}, environment)
+
+
+class TestGetTlsVersion(object):
+    def test_get_tls_version_default(self):
+        environment = {}
+        assert get_tls_version(environment) is None
+
+    def test_get_tls_version_upgrade(self):
+        environment = {'COMPOSE_TLS_VERSION': 'TLSv1_2'}
+        assert get_tls_version(environment) == ssl.PROTOCOL_TLSv1_2
+
+    def test_get_tls_version_unavailable(self):
+        environment = {'COMPOSE_TLS_VERSION': 'TLSv5_5'}
+        with mock.patch('compose.cli.command.log') as mock_log:
+            tls_version = get_tls_version(environment)
+        mock_log.warn.assert_called_once_with(mock.ANY)
+        assert tls_version is None