From: Nizamudeen A Date: Tue, 9 Jan 2024 05:15:36 +0000 (+0530) Subject: mgr/dashboard: multi-cluster authentication X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=aaad9a9f4e0d64531925fafc2ef230a021f18780;p=ceph.git mgr/dashboard: multi-cluster authentication Signed-off-by: Nizamudeen A --- diff --git a/src/pybind/mgr/dashboard/controllers/multi_cluster.py b/src/pybind/mgr/dashboard/controllers/multi_cluster.py new file mode 100644 index 0000000000000..652fafd25a3c4 --- /dev/null +++ b/src/pybind/mgr/dashboard/controllers/multi_cluster.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- + +import json +import requests + +from . import APIDoc, APIRouter, CreatePermission, UpdatePermission, ReadPermission, Endpoint, EndpointDoc, RESTController +from ..exceptions import DashboardException +from ..settings import Settings +from ..security import Scope + + +@APIRouter('/multi-cluster', Scope.CONFIG_OPT) +@APIDoc('Multi-cluster Management API', 'Multi-cluster') +class MultiCluster(RESTController): + def _proxy(self, method, base_url, path, params=None, payload=None, verify=False): + try: + headers = { + 'Accept': 'application/vnd.ceph.api.v1.0+json', + 'Content-Type': 'application/json', + } + response = requests.request(method, base_url + path, params=params, + json=payload, verify=verify, headers=headers) + except Exception as e: + raise DashboardException( + "Could not reach {}".format(base_url+path), + http_status_code=404, + component='dashboard') + + try: + content = json.loads(response.content, strict=False) + except json.JSONDecodeError as e: + raise DashboardException( + "Error parsing Dashboard API response: {}".format(e.msg), + component='dashboard') + return content + + + @Endpoint('POST') + @CreatePermission + @EndpointDoc("Authenticate to a remote cluster") + def auth(self, url: str, name: str, username=None, password=None, token=None): + multicluster_config = {} + + if isinstance(Settings.MULTICLUSTER_CONFIG, str): + try: + item_to_dict = json.loads(Settings.MULTICLUSTER_CONFIG) + except json.JSONDecodeError: + item_to_dict = {} + multicluster_config = item_to_dict.copy() + else: + multicluster_config = Settings.MULTICLUSTER_CONFIG.copy() + + if 'config' not in multicluster_config: + multicluster_config['config'] = [] + + if token: + multicluster_config['config'].append({ + 'name': name, + 'url': url, + 'token': token + }) + + Settings.MULTICLUSTER_CONFIG = multicluster_config + return + + if username and password: + payload = { + 'username': username, + 'password': password + } + content = self._proxy('POST', url, 'api/auth', payload=payload) + if 'token' not in content: + raise DashboardException( + "Could not authenticate to remote cluster", + http_status_code=400, + component='dashboard') + + else: + token = content['token'] + + multicluster_config['config'].append({ + 'name': name, + 'url': url, + 'token': token + }) + + Settings.MULTICLUSTER_CONFIG = multicluster_config diff --git a/src/pybind/mgr/dashboard/settings.py b/src/pybind/mgr/dashboard/settings.py index 6018f0d7f9c73..acff17e94e5f5 100644 --- a/src/pybind/mgr/dashboard/settings.py +++ b/src/pybind/mgr/dashboard/settings.py @@ -119,6 +119,10 @@ class Options(object): 'gateway', 'logs', 'crush', 'maps']), [str]) + MULTICLUSTER_CONFIG = Setting({}, [dict, str]) + + UNSAFE_TLS_v1_2 = Setting(False, [bool]) + @staticmethod def has_default_value(name): return getattr(Settings, name, None) is None or \