Browse Source

Fix assert_hostname logic in tls_config_from_options

Signed-off-by: Joffrey F <[email protected]>
Joffrey F 9 years ago
parent
commit
44715f18bd
2 changed files with 48 additions and 7 deletions
  1. 20 7
      compose/cli/docker_client.py
  2. 28 0
      tests/unit/cli/docker_client_test.py

+ 20 - 7
compose/cli/docker_client.py

@@ -21,24 +21,37 @@ def tls_config_from_options(options):
     cert = options.get('--tlscert')
     key = options.get('--tlskey')
     verify = options.get('--tlsverify')
-    hostname = urlparse(options.get('--host') or '').hostname
+    host = options.get('--host')
+    skip_hostname_check = options.get('--skip-hostname-check', False)
+
+    if not skip_hostname_check:
+        hostname = urlparse(host).hostname if host else None
+        # If the protocol is omitted, urlparse fails to extract the hostname.
+        # Make another attempt by appending a protocol.
+        if not hostname and host:
+            hostname = urlparse('tcp://{0}'.format(host)).hostname
 
     advanced_opts = any([ca_cert, cert, key, verify])
 
     if tls is True and not advanced_opts:
         return True
-    elif advanced_opts:
+    elif advanced_opts:  # --tls is a noop
         client_cert = None
         if cert or key:
             client_cert = (cert, key)
+
+        assert_hostname = None
+        if skip_hostname_check:
+            assert_hostname = False
+        elif hostname:
+            assert_hostname = hostname
+
         return TLSConfig(
             client_cert=client_cert, verify=verify, ca_cert=ca_cert,
-            assert_hostname=(
-                hostname or not options.get('--skip-hostname-check', False)
-            )
+            assert_hostname=assert_hostname
         )
-    else:
-        return None
+
+    return None
 
 
 def docker_client(environment, version=None, tls_config=None, host=None):

+ 28 - 0
tests/unit/cli/docker_client_test.py

@@ -103,3 +103,31 @@ class TLSConfigTestCase(unittest.TestCase):
         options = {'--tlskey': self.key}
         with pytest.raises(docker.errors.TLSParameterError):
             tls_config_from_options(options)
+
+    def test_assert_hostname_explicit_host(self):
+        options = {
+            '--tlscacert': self.ca_cert, '--host': 'tcp://foobar.co.uk:1254'
+        }
+        result = tls_config_from_options(options)
+        assert isinstance(result, docker.tls.TLSConfig)
+        assert result.assert_hostname == 'foobar.co.uk'
+
+    def test_assert_hostname_explicit_host_no_proto(self):
+        options = {
+            '--tlscacert': self.ca_cert, '--host': 'foobar.co.uk:1254'
+        }
+        result = tls_config_from_options(options)
+        assert isinstance(result, docker.tls.TLSConfig)
+        assert result.assert_hostname == 'foobar.co.uk'
+
+    def test_assert_hostname_implicit_host(self):
+        options = {'--tlscacert': self.ca_cert}
+        result = tls_config_from_options(options)
+        assert isinstance(result, docker.tls.TLSConfig)
+        assert result.assert_hostname is None
+
+    def test_assert_hostname_explicit_skip(self):
+        options = {'--tlscacert': self.ca_cert, '--skip-hostname-check': True}
+        result = tls_config_from_options(options)
+        assert isinstance(result, docker.tls.TLSConfig)
+        assert result.assert_hostname is False