From: Volker Theile Date: Wed, 2 Dec 2020 08:54:24 +0000 (+0100) Subject: mgr/dashboard: Disable TLS 1.0 and 1.1 X-Git-Tag: v15.2.8~4^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0812441c98e120158004edc06e5466ae05cc5afb;p=ceph.git mgr/dashboard: Disable TLS 1.0 and 1.1 Disable these TLS versions because of security issues. Fixes: https://tracker.ceph.com/issues/48360 Signed-off-by: Volker Theile (cherry picked from commit 5cf222b6d2a5cdc7ff23357b12878d34a4e68801) --- diff --git a/qa/tasks/mgr/test_dashboard.py b/qa/tasks/mgr/test_dashboard.py index 44b6602a6da..9f904a6e0c0 100644 --- a/qa/tasks/mgr/test_dashboard.py +++ b/qa/tasks/mgr/test_dashboard.py @@ -1,10 +1,10 @@ - - -from tasks.mgr.mgr_test_case import MgrTestCase - import logging +import ssl + import requests +from requests.adapters import HTTPAdapter +from .mgr_test_case import MgrTestCase log = logging.getLogger(__name__) @@ -124,3 +124,32 @@ class TestDashboard(MgrTestCase): )) self.assertListEqual(failures, []) + + def test_tls(self): + class CustomHTTPAdapter(HTTPAdapter): + def __init__(self, ssl_version): + self.ssl_version = ssl_version + super().__init__() + + def init_poolmanager(self, *args, **kwargs): + kwargs['ssl_version'] = self.ssl_version + return super().init_poolmanager(*args, **kwargs) + + uri = self._get_uri("dashboard") + + # TLSv1 + with self.assertRaises(requests.exceptions.SSLError): + session = requests.Session() + session.mount(uri, CustomHTTPAdapter(ssl.PROTOCOL_TLSv1)) + session.get(uri, allow_redirects=False, verify=False) + + # TLSv1.1 + with self.assertRaises(requests.exceptions.SSLError): + session = requests.Session() + session.mount(uri, CustomHTTPAdapter(ssl.PROTOCOL_TLSv1_1)) + session.get(uri, allow_redirects=False, verify=False) + + session = requests.Session() + session.mount(uri, CustomHTTPAdapter(ssl.PROTOCOL_TLS)) + r = session.get(uri, allow_redirects=False, verify=False) + self.assertEqual(r.status_code, 200) diff --git a/src/pybind/mgr/dashboard/module.py b/src/pybind/mgr/dashboard/module.py index 27501f963b9..6057802ebf0 100644 --- a/src/pybind/mgr/dashboard/module.py +++ b/src/pybind/mgr/dashboard/module.py @@ -9,6 +9,8 @@ import errno import logging import os import socket +import ssl +import sys import tempfile import threading import time @@ -97,8 +99,8 @@ class CherryPyConfig(object): """ server_addr = self.get_localized_module_option( # type: ignore 'server_addr', get_default_addr()) - ssl = self.get_localized_module_option('ssl', True) # type: ignore - if not ssl: + use_ssl = self.get_localized_module_option('ssl', True) # type: ignore + if not use_ssl: server_port = self.get_localized_module_option('server_port', 8080) # type: ignore else: server_port = self.get_localized_module_option('ssl_server_port', 8443) # type: ignore @@ -108,7 +110,7 @@ class CherryPyConfig(object): 'no server_addr configured; ' 'try "ceph config set mgr mgr/{}/{}/server_addr "' .format(self.module_name, self.get_mgr_id())) # type: ignore - self.log.info('server: ssl=%s host=%s port=%d', 'yes' if ssl else 'no', # type: ignore + self.log.info('server: ssl=%s host=%s port=%d', 'yes' if use_ssl else 'no', # type: ignore server_addr, server_port) # Initialize custom handlers. @@ -144,7 +146,7 @@ class CherryPyConfig(object): 'tools.plugin_hooks_filter_request.on': True, } - if ssl: + if use_ssl: # SSL initialization cert = self.get_store("crt") # type: ignore if cert is not None: @@ -166,9 +168,18 @@ class CherryPyConfig(object): verify_tls_files(cert_fname, pkey_fname) + # Create custom SSL context to disable TLS 1.0 and 1.1. + context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + context.load_cert_chain(cert_fname, pkey_fname) + if sys.version_info >= (3, 7): + context.minimum_version = ssl.TLSVersion.TLSv1_2 + else: + context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + config['server.ssl_module'] = 'builtin' config['server.ssl_certificate'] = cert_fname config['server.ssl_private_key'] = pkey_fname + config['server.ssl_context'] = context self.update_cherrypy_config(config) @@ -176,7 +187,7 @@ class CherryPyConfig(object): 'url_prefix', default='')) uri = "{0}://{1}:{2}{3}/".format( - 'https' if ssl else 'http', + 'https' if use_ssl else 'http', socket.getfqdn(server_addr if server_addr != '::' else ''), server_port, self.url_prefix