From 670522ee310cd9ac816e4db9e204498901bd7590 Mon Sep 17 00:00:00 2001 From: Volker Theile Date: Fri, 3 Aug 2018 08:48:00 +0200 Subject: [PATCH] mgr/dashboard: RGW proxy can't handle self-signed certificates Fixes tracker.ceph.com/issues/24677 Signed-off-by: Volker Theile --- doc/mgr/dashboard.rst | 7 ++++ src/pybind/mgr/dashboard/rest_client.py | 3 +- .../mgr/dashboard/services/rgw_client.py | 3 +- src/pybind/mgr/dashboard/settings.py | 1 + .../mgr/dashboard/tests/test_rgw_client.py | 40 +++++++++++++++++++ 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/pybind/mgr/dashboard/tests/test_rgw_client.py diff --git a/doc/mgr/dashboard.rst b/doc/mgr/dashboard.rst index c521a24a6442a..c0fb1b7cb0cdc 100644 --- a/doc/mgr/dashboard.rst +++ b/doc/mgr/dashboard.rst @@ -232,6 +232,13 @@ exist and you may find yourself in the situation that you have to use them:: $ ceph dashboard set-rgw-api-admin-resource $ ceph dashboard set-rgw-api-user-id +If you are using a self-signed certificate in your Object Gateway setup, then +you should disable certificate verification in the dashboard to avoid refused +connections, e.g. caused by certificates signed by unknown CA or not matching +the host name:: + + $ ceph dashboard set-rgw-api-ssl-verify False + If the Object Gateway takes too long to process requests and the dashboard runs into timeouts, then you can set the timeout value to your needs:: diff --git a/src/pybind/mgr/dashboard/rest_client.py b/src/pybind/mgr/dashboard/rest_client.py index 6099fe945254f..c17ad1fde38f8 100644 --- a/src/pybind/mgr/dashboard/rest_client.py +++ b/src/pybind/mgr/dashboard/rest_client.py @@ -318,7 +318,7 @@ def __call__(self, class RestClient(object): - def __init__(self, host, port, client_name=None, ssl=False, auth=None): + def __init__(self, host, port, client_name=None, ssl=False, auth=None, ssl_verify=True): super(RestClient, self).__init__() self.client_name = client_name if client_name else '' self.host = host @@ -329,6 +329,7 @@ def __init__(self, host, port, client_name=None, ssl=False, auth=None): self.headers = {'Accept': 'application/json'} self.auth = auth self.session = TimeoutRequestsSession() + self.session.verify = ssl_verify def _login(self, request=None): pass diff --git a/src/pybind/mgr/dashboard/services/rgw_client.py b/src/pybind/mgr/dashboard/services/rgw_client.py index 2ba80dc8d32f1..09d32fe951fdc 100644 --- a/src/pybind/mgr/dashboard/services/rgw_client.py +++ b/src/pybind/mgr/dashboard/services/rgw_client.py @@ -171,12 +171,13 @@ def __init__(self, # pylint: disable-msg=R0913 port = port if port else RgwClient._port admin_path = admin_path if admin_path else RgwClient._ADMIN_PATH ssl = ssl if ssl else RgwClient._ssl + ssl_verify = Settings.RGW_API_SSL_VERIFY self.service_url = build_url(host=host, port=port) self.admin_path = admin_path s3auth = S3Auth(access_key, secret_key, service_url=self.service_url) - super(RgwClient, self).__init__(host, port, 'RGW', ssl, s3auth) + super(RgwClient, self).__init__(host, port, 'RGW', ssl, s3auth, ssl_verify=ssl_verify) # If user ID is not set, then try to get it via the RGW Admin Ops API. self.userid = userid if userid else self._get_user_id(self.admin_path) diff --git a/src/pybind/mgr/dashboard/settings.py b/src/pybind/mgr/dashboard/settings.py index 16426f48bc23a..1b6d5d014e821 100644 --- a/src/pybind/mgr/dashboard/settings.py +++ b/src/pybind/mgr/dashboard/settings.py @@ -29,6 +29,7 @@ class Options(object): RGW_API_ADMIN_RESOURCE = ('admin', str) RGW_API_SCHEME = ('http', str) RGW_API_USER_ID = ('', str) + RGW_API_SSL_VERIFY = (True, bool) # Grafana settings GRAFANA_API_URL = ('http://localhost:3000', str) diff --git a/src/pybind/mgr/dashboard/tests/test_rgw_client.py b/src/pybind/mgr/dashboard/tests/test_rgw_client.py new file mode 100644 index 0000000000000..1502cdeb55b95 --- /dev/null +++ b/src/pybind/mgr/dashboard/tests/test_rgw_client.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +import unittest + +from .. import mgr +from ..services.rgw_client import RgwClient + + +class RgwClientTest(unittest.TestCase): + settings = { + 'RGW_API_ACCESS_KEY': 'klausmustermann', + 'RGW_API_SECRET_KEY': 'supergeheim', + 'RGW_API_HOST': 'localhost', + 'RGW_API_USER_ID': 'rgwadmin' + } + + @classmethod + def mock_set_config(cls, key, val): + cls.settings[key] = val + + @classmethod + def mock_get_config(cls, key, default): + return cls.settings.get(key, default) + + @classmethod + def setUpClass(cls): + mgr.get_config.side_effect = cls.mock_get_config + mgr.set_config.side_effect = cls.mock_set_config + + def setUp(self): + RgwClient._user_instances.clear() # pylint: disable=protected-access + + def test_ssl_verify(self): + mgr.set_config('RGW_API_SSL_VERIFY', True) + instance = RgwClient.admin_instance() + self.assertTrue(instance.session.verify) + + def test_no_ssl_verify(self): + mgr.set_config('RGW_API_SSL_VERIFY', False) + instance = RgwClient.admin_instance() + self.assertFalse(instance.session.verify)