mirror of
https://github.com/ansible-collections/community.docker.git
synced 2025-12-16 11:58:43 +00:00
* utils: fix IPv6 address w/ port parsing This was using a deprecated function (`urllib.splitnport`), ostensibly to work around issues with brackets on IPv6 addresses. Ironically, its usage was broken, and would result in mangled IPv6 addresses if they had a port specified in some instances. Usage of the deprecated function has been eliminated and extra test cases added where missing. All existing cases pass as-is. (The only other change to the test was to improve assertion messages.) Cherry-picked fromf16c4e1147Co-authored-by: Milas Bowman <milas.bowman@docker.com> * client: fix exception semantics in _raise_for_status We want "The above exception was the direct cause of the following exception:" instead of "During handling of the above exception, another exception occurred:" Cherry-picked frombb11197ee3Co-authored-by: Maor Kleinberger <kmaork@gmail.com> * tls: use auto-negotiated highest version Specific TLS versions are deprecated in latest Python, which causes test failures due to treating deprecation errors as warnings. Luckily, the fix here is straightforward: we can eliminate some custom version selection logic by using `PROTOCOL_TLS_CLIENT`, which is the recommended method and will select the highest TLS version supported by both client and server. Cherry-picked from56dd6de7dfCo-authored-by: Milas Bowman <milas.bowman@docker.com> * transport: fix ProxyCommand for SSH conn Cherry-picked from4e19cc48dfCo-authored-by: Guy Lichtman <glicht@users.noreply.github.com> * ssh: do not create unnecessary subshell on exec Cherry-picked frombb40ba051fCo-authored-by: liubo <liubo@uniontech.com> * ssh: reject unknown host keys when using Python SSH impl In the Secure Shell (SSH) protocol, host keys are used to verify the identity of remote hosts. Accepting unknown host keys may leave the connection open to man-in-the-middle attacks. Do not accept unknown host keys. In particular, do not set the default missing host key policy for the Paramiko library to either AutoAddPolicy or WarningPolicy. Both of these policies continue even when the host key is unknown. The default setting of RejectPolicy is secure because it throws an exception when it encounters an unknown host key. Reference: https://cwe.mitre.org/data/definitions/295.html NOTE: This only affects SSH connections using the native Python SSH implementation (Paramiko), when `use_ssh_client=False` (default). If using the system SSH client (`use_ssh_client=True`), the host configuration (e.g. `~/.ssh/config`) will apply. Cherry-picked fromd9298647d9Co-authored-by: Audun Nes <audun.nes@gmail.com> * lint: fix deprecation warnings from threading package Set `daemon` attribute instead of using `setDaemon` method that was deprecated in Python 3.10. Cherry-picked fromadf5a97b12Co-authored-by: Karthikeyan Singaravelan <tir.karthi@gmail.com> * api: preserve cause when re-raising error Use `from e` to ensure that the error context is propagated correctly. Cherry-picked from05e143429eCo-authored-by: Milas Bowman <milas.bowman@docker.com> * build: trim trailing whitespace from dockerignore entries Cherry-picked from3ee3a2486fCo-authored-by: Clément Loiselet <clement.loiselet@capgemini.com> * Improve formulation, also mention the security change as a breaking change. Co-authored-by: Milas Bowman <milas.bowman@docker.com> Co-authored-by: Maor Kleinberger <kmaork@gmail.com> Co-authored-by: Guy Lichtman <glicht@users.noreply.github.com> Co-authored-by: liubo <liubo@uniontech.com> Co-authored-by: Audun Nes <audun.nes@gmail.com> Co-authored-by: Karthikeyan Singaravelan <tir.karthi@gmail.com> Co-authored-by: Clément Loiselet <clement.loiselet@capgemini.com>
123 lines
4.5 KiB
Python
123 lines
4.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
# This code is part of the Ansible collection community.docker, but is an independent component.
|
|
# This particular file, and this file only, is based on the Docker SDK for Python (https://github.com/docker/docker-py/)
|
|
#
|
|
# Copyright (c) 2016-2022 Docker, Inc.
|
|
#
|
|
# It is licensed under the Apache 2.0 license (see LICENSES/Apache-2.0.txt in this collection)
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from __future__ import (absolute_import, division, print_function)
|
|
__metaclass__ = type
|
|
|
|
import os
|
|
import ssl
|
|
import sys
|
|
|
|
from . import errors
|
|
from .transport.ssladapter import SSLHTTPAdapter
|
|
|
|
|
|
class TLSConfig(object):
|
|
"""
|
|
TLS configuration.
|
|
|
|
Args:
|
|
client_cert (tuple of str): Path to client cert, path to client key.
|
|
ca_cert (str): Path to CA cert file.
|
|
verify (bool or str): This can be ``False`` or a path to a CA cert
|
|
file.
|
|
ssl_version (int): A valid `SSL version`_.
|
|
assert_hostname (bool): Verify the hostname of the server.
|
|
|
|
.. _`SSL version`:
|
|
https://docs.python.org/3.5/library/ssl.html#ssl.PROTOCOL_TLSv1
|
|
"""
|
|
cert = None
|
|
ca_cert = None
|
|
verify = None
|
|
ssl_version = None
|
|
|
|
def __init__(self, client_cert=None, ca_cert=None, verify=None,
|
|
ssl_version=None, assert_hostname=None,
|
|
assert_fingerprint=None):
|
|
# Argument compatibility/mapping with
|
|
# https://docs.docker.com/engine/articles/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 verify=False
|
|
|
|
self.assert_hostname = assert_hostname
|
|
self.assert_fingerprint = assert_fingerprint
|
|
|
|
# If the user provides an SSL version, we should use their preference
|
|
if ssl_version:
|
|
self.ssl_version = ssl_version
|
|
elif (sys.version_info.major, sys.version_info.minor) < (3, 6):
|
|
# If the user provides no ssl version, we should default to
|
|
# TLSv1_2. This option is the most secure, and will work for the
|
|
# majority of users with reasonably up-to-date software. However,
|
|
# before doing so, detect openssl version to ensure we can support
|
|
# it.
|
|
if ssl.OPENSSL_VERSION_INFO[:3] >= (1, 0, 1) and hasattr(
|
|
ssl, 'PROTOCOL_TLSv1_2'):
|
|
# If the OpenSSL version is high enough to support TLSv1_2,
|
|
# then we should use it.
|
|
self.ssl_version = getattr(ssl, 'PROTOCOL_TLSv1_2')
|
|
else:
|
|
# Otherwise, TLS v1.0 seems to be the safest default;
|
|
# SSLv23 fails in mysterious ways:
|
|
# https://github.com/docker/docker-py/issues/963
|
|
self.ssl_version = ssl.PROTOCOL_TLSv1
|
|
else:
|
|
self.ssl_version = ssl.PROTOCOL_TLS_CLIENT
|
|
|
|
# "client_cert" must have both or neither cert/key files. In
|
|
# either case, Alert the user when both are expected, but any are
|
|
# missing.
|
|
|
|
if client_cert:
|
|
try:
|
|
tls_cert, tls_key = client_cert
|
|
except ValueError:
|
|
raise errors.TLSParameterError(
|
|
'client_cert must be a tuple of'
|
|
' (client certificate, key file)'
|
|
)
|
|
|
|
if not (tls_cert and tls_key) or (not os.path.isfile(tls_cert) or
|
|
not os.path.isfile(tls_key)):
|
|
raise errors.TLSParameterError(
|
|
'Path to a certificate and key files must be provided'
|
|
' through the client_cert param'
|
|
)
|
|
self.cert = (tls_cert, tls_key)
|
|
|
|
# If verify is set, make sure the cert exists
|
|
self.verify = verify
|
|
self.ca_cert = ca_cert
|
|
if self.verify and self.ca_cert and not os.path.isfile(self.ca_cert):
|
|
raise errors.TLSParameterError(
|
|
'Invalid CA certificate provided for `ca_cert`.'
|
|
)
|
|
|
|
def configure_client(self, client):
|
|
"""
|
|
Configure a client with these TLS options.
|
|
"""
|
|
client.ssl_version = self.ssl_version
|
|
|
|
if self.verify and self.ca_cert:
|
|
client.verify = self.ca_cert
|
|
else:
|
|
client.verify = self.verify
|
|
|
|
if self.cert:
|
|
client.cert = self.cert
|
|
|
|
client.mount('https://', SSLHTTPAdapter(
|
|
ssl_version=self.ssl_version,
|
|
assert_hostname=self.assert_hostname,
|
|
assert_fingerprint=self.assert_fingerprint,
|
|
))
|