]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: removed `@AuthRequired` decorator
authorRicardo Dias <rdias@suse.com>
Tue, 24 Apr 2018 12:48:38 +0000 (13:48 +0100)
committerRicardo Dias <rdias@suse.com>
Tue, 26 Jun 2018 11:28:53 +0000 (12:28 +0100)
Now all controllers require authentication by default.
No disable authentication, a boolean parameter can be passed
in the `@ApiController` decorator.

Fixes: http://tracker.ceph.com/issues/23796
Signed-off-by: Ricardo Dias <rdias@suse.com>
25 files changed:
src/pybind/mgr/dashboard/controllers/__init__.py
src/pybind/mgr/dashboard/controllers/auth.py
src/pybind/mgr/dashboard/controllers/cephfs.py
src/pybind/mgr/dashboard/controllers/cluster_configuration.py
src/pybind/mgr/dashboard/controllers/dashboard.py
src/pybind/mgr/dashboard/controllers/docs.py
src/pybind/mgr/dashboard/controllers/erasure_code_profile.py
src/pybind/mgr/dashboard/controllers/grafana.py
src/pybind/mgr/dashboard/controllers/host.py
src/pybind/mgr/dashboard/controllers/logging.py
src/pybind/mgr/dashboard/controllers/monitor.py
src/pybind/mgr/dashboard/controllers/osd.py
src/pybind/mgr/dashboard/controllers/perf_counters.py
src/pybind/mgr/dashboard/controllers/pool.py
src/pybind/mgr/dashboard/controllers/rbd.py
src/pybind/mgr/dashboard/controllers/rbd_mirroring.py
src/pybind/mgr/dashboard/controllers/rgw.py
src/pybind/mgr/dashboard/controllers/summary.py
src/pybind/mgr/dashboard/controllers/task.py
src/pybind/mgr/dashboard/controllers/tcmu_iscsi.py
src/pybind/mgr/dashboard/tests/test_controllers.py
src/pybind/mgr/dashboard/tests/test_exceptions.py
src/pybind/mgr/dashboard/tests/test_grafana.py
src/pybind/mgr/dashboard/tests/test_rest_tasks.py
src/pybind/mgr/dashboard/tests/test_tools.py

index a86c753cff50f7637aa48fbbd727f1cd40faa422..328eb271d892cf0d8b0b2dd78a51615f1b7473e1 100644 (file)
@@ -21,9 +21,10 @@ from ..services.exception import serialize_dashboard_exception
 
 
 class Controller(object):
-    def __init__(self, path, base_url=None):
+    def __init__(self, path, base_url=None, secure=True):
         self.path = path
         self.base_url = base_url
+        self.secure = secure
 
         if self.path and self.path[0] != "/":
             self.path = "/" + self.path
@@ -44,19 +45,19 @@ class Controller(object):
             'tools.sessions.on': True,
             'tools.sessions.name': Session.NAME,
             'tools.session_expire_at_browser_close.on': True,
-            'tools.dashboard_exception_handler.on': True
+            'tools.dashboard_exception_handler.on': True,
+            'tools.authenticate.on': self.secure,
         }
         if not hasattr(cls, '_cp_config'):
             cls._cp_config = {}
-        if 'tools.authenticate.on' not in cls._cp_config:
-            config['tools.authenticate.on'] = False
         cls._cp_config.update(config)
         return cls
 
 
 class ApiController(Controller):
-    def __init__(self, path):
-        super(ApiController, self).__init__(path, base_url="/api")
+    def __init__(self, path, secure=True):
+        super(ApiController, self).__init__(path, base_url="/api",
+                                            secure=secure)
 
     def __call__(self, cls):
         cls = super(ApiController, self).__call__(cls)
@@ -65,24 +66,10 @@ class ApiController(Controller):
 
 
 class UiApiController(Controller):
-    def __init__(self, path):
-        super(UiApiController, self).__init__(path, base_url="/ui-api")
-
-
-def AuthRequired(enabled=True):
-    if not isinstance(enabled, bool):
-        raise TypeError('AuthRequired used incorrectly. '
-                        'You are likely missing parentheses!')
-
-    def decorate(cls):
-        if not hasattr(cls, '_cp_config'):
-            cls._cp_config = {
-                'tools.authenticate.on': enabled
-            }
-        else:
-            cls._cp_config['tools.authenticate.on'] = enabled
-        return cls
-    return decorate
+    def __init__(self, path, security_scope=None, secure=True):
+        super(UiApiController, self).__init__(path, base_url="/ui-api",
+                                              security_scope=security_scope,
+                                              secure=secure)
 
 
 def Endpoint(method=None, path=None, path_params=None, query_params=None,
@@ -434,8 +421,8 @@ class BaseController(object):
             path_params = [p['name'] for p in self.path_params]
             query_params = [p['name'] for p in self.query_params]
             return [p for p in func_params
-                    if p['name'] not in path_params and
-                    p['name'] not in query_params]
+                    if p['name'] not in path_params
+                    and p['name'] not in query_params]
 
         @property
         def group(self):
index 17e5eb9fa4ef42149c4666e48e857da6d8b22c9f..033e5ea27c961787142e515d4d0b96ace6895702 100644 (file)
@@ -12,7 +12,7 @@ from ..services.auth import AuthManager
 from ..tools import Session
 
 
-@ApiController('/auth')
+@ApiController('/auth', secure=False)
 class Auth(RESTController):
     """
     Provide login and logout actions.
index b6cc36d21c959e3b3e3bb61427626291ccbb68fd..90fa5c9c0b8c0a280270544271703f089babdf1c 100644 (file)
@@ -5,15 +5,14 @@ from collections import defaultdict
 
 import cherrypy
 
-from ..exceptions import DashboardException
-from . import ApiController, AuthRequired, RESTController
+from . import ApiController, RESTController
 from .. import mgr
+from ..exceptions import DashboardException
 from ..services.ceph_service import CephService
 from ..tools import ViewCache
 
 
 @ApiController('/cephfs')
-@AuthRequired()
 class CephFS(RESTController):
     def __init__(self):
         super(CephFS, self).__init__()
index 0e724cf1a4acc7a398e8a401d6bb75ab8f5a1b5d..03597d5afbbef929c5892d6c0f1cc615aa905714 100644 (file)
@@ -3,13 +3,12 @@ from __future__ import absolute_import
 
 import cherrypy
 
+from . import ApiController, RESTController
 from .. import mgr
 from ..services.ceph_service import CephService
-from . import ApiController, RESTController, AuthRequired
 
 
 @ApiController('/cluster_conf')
-@AuthRequired()
 class ClusterConfiguration(RESTController):
 
     def _append_config_option_values(self, options):
index 4e21810b4b496c1ec64e728be7e7f5610cff7427..87bf62089bdb6471364aed21fb54d05909702908 100644 (file)
@@ -4,7 +4,7 @@ from __future__ import absolute_import
 import collections
 import json
 
-from . import ApiController, AuthRequired, Endpoint, BaseController
+from . import ApiController, Endpoint, BaseController
 from .. import mgr
 from ..services.ceph_service import CephService
 from ..tools import NotificationQueue
@@ -14,7 +14,6 @@ LOG_BUFFER_SIZE = 30
 
 
 @ApiController('/dashboard')
-@AuthRequired()
 class Dashboard(BaseController):
     def __init__(self):
         super(Dashboard, self).__init__()
index b61bea997bbb93bf5b027b21153a06ffecdf67c5..3438c83999743bae27011923248defc33a8a103e 100644 (file)
@@ -3,12 +3,11 @@ from __future__ import absolute_import
 
 import cherrypy
 
-from . import Controller, BaseController, AuthRequired, Endpoint, ENDPOINT_MAP
+from . import Controller, BaseController, Endpoint, ENDPOINT_MAP
 from .. import logger
 
 
 @Controller('/docs')
-@AuthRequired()
 class Docs(BaseController):
 
     @classmethod
index b5178ea9bbb1443a4494c63cbc3e70d5e740a5e9..9c9f0d3f591f274871d29cb54c1fc275a7fe34cf 100644 (file)
@@ -3,7 +3,7 @@ from __future__ import absolute_import
 
 from cherrypy import NotFound
 
-from . import ApiController, AuthRequired, RESTController
+from . import ApiController, RESTController
 from ..services.ceph_service import CephService
 from .. import mgr
 
@@ -16,7 +16,6 @@ def _serialize_ecp(name, ecp):
 
 
 @ApiController('/erasure_code_profile')
-@AuthRequired()
 class ErasureCodeProfile(RESTController):
     """
     create() supports additional key-value arguments that are passed to the
index cffb6d0b976814167b799a723d5a2428a535f68b..e7ae55f3a02d49ef5a8ddbd067ffa4cb10967e79 100644 (file)
@@ -5,7 +5,7 @@ import cherrypy
 import requests
 from six.moves.urllib.parse import urlparse  # pylint: disable=import-error
 
-from . import ApiController, BaseController, AuthRequired, Proxy, Endpoint
+from . import ApiController, BaseController, Proxy, Endpoint
 from .. import logger
 from ..settings import Settings
 
@@ -102,7 +102,6 @@ class GrafanaRestClient(object):
 
 
 @ApiController('/grafana')
-@AuthRequired()
 class Grafana(BaseController):
 
     @Endpoint()
@@ -117,7 +116,6 @@ class Grafana(BaseController):
 
 
 @ApiController('/grafana/proxy')
-@AuthRequired()
 class GrafanaProxy(BaseController):
     @Proxy()
     def __call__(self, path, **params):
index ff08112afa1a7da94dcec405175650f96dcdd579..76c2afea3b010c1f2b5b0689d100a15586d8e3ff 100644 (file)
@@ -1,12 +1,11 @@
 # -*- coding: utf-8 -*-
 from __future__ import absolute_import
 
-from . import ApiController, AuthRequired, RESTController
+from . import ApiController, RESTController
 from .. import mgr
 
 
 @ApiController('/host')
-@AuthRequired()
 class Host(RESTController):
     def list(self):
         return mgr.list_servers()
index 33c0558f0016fd2a14a1413ce1bd86bf9032cc4c..9c7d6de7ee2ea514ee816e8080455a4d4104ef36 100644 (file)
@@ -2,7 +2,7 @@ from . import UiApiController, BaseController, Endpoint
 from .. import logger
 
 
-@UiApiController('/logging')
+@UiApiController('/logging', secure=False)
 class Logging(BaseController):
 
     @Endpoint('POST', path='js-error')
index 12bba726b86763770f653497fa2c63bcb1592840..be3a85fe24b959dad26e4b80b3c1f506fcb92a6d 100644 (file)
@@ -3,12 +3,11 @@ from __future__ import absolute_import
 
 import json
 
-from . import ApiController, AuthRequired, Endpoint, BaseController
+from . import ApiController, Endpoint, BaseController
 from .. import mgr
 
 
 @ApiController('/monitor')
-@AuthRequired()
 class Monitor(BaseController):
     @Endpoint()
     def __call__(self):
index 77b275a0ccc423f0bc97d8fe8dc883c82fd0723d..0b462ef9c4008c55213f038be26951b88a8f637d 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import absolute_import
 
-from . import ApiController, AuthRequired, RESTController
+from . import ApiController, RESTController
 from .. import mgr, logger
 from ..services.ceph_service import CephService
 from ..services.exception import handle_send_command_error
@@ -9,7 +9,6 @@ from ..tools import str_to_bool
 
 
 @ApiController('/osd')
-@AuthRequired()
 class Osd(RESTController):
     def list(self):
         osds = self.get_osd_map()
index cced79f1883acf42c9da4d08bffdae8bb4ebcd09..68a82dc6a831b7d9ea6bf04cb1f89f092aa0e0a1 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import absolute_import
 
-from . import ApiController, AuthRequired, RESTController
+from . import ApiController, RESTController
 from .. import mgr
 from ..services.ceph_service import CephService
 
@@ -39,43 +39,36 @@ class PerfCounter(RESTController):
 
 
 @ApiController('perf_counters/mds')
-@AuthRequired()
 class MdsPerfCounter(PerfCounter):
     service_type = 'mds'
 
 
 @ApiController('perf_counters/mon')
-@AuthRequired()
 class MonPerfCounter(PerfCounter):
     service_type = 'mon'
 
 
 @ApiController('perf_counters/osd')
-@AuthRequired()
 class OsdPerfCounter(PerfCounter):
     service_type = 'osd'
 
 
 @ApiController('perf_counters/rgw')
-@AuthRequired()
 class RgwPerfCounter(PerfCounter):
     service_type = 'rgw'
 
 
 @ApiController('perf_counters/rbd-mirror')
-@AuthRequired()
 class RbdMirrorPerfCounter(PerfCounter):
     service_type = 'rbd-mirror'
 
 
 @ApiController('perf_counters/mgr')
-@AuthRequired()
 class MgrPerfCounter(PerfCounter):
     service_type = 'mgr'
 
 
 @ApiController('perf_counters')
-@AuthRequired()
 class PerfCounters(RESTController):
     def list(self):
         return mgr.get_all_perf_counters()
index ae61330923130b9d758c358b415db8b6cfa9cd6a..09f7c75d1ff83f91ca560278b1a4a07a1080a24c 100644 (file)
@@ -3,7 +3,7 @@ from __future__ import absolute_import
 
 import cherrypy
 
-from . import ApiController, RESTController, Endpoint, AuthRequired
+from . import ApiController, RESTController, Endpoint
 from .. import mgr
 from ..services.ceph_service import CephService
 from ..services.exception import handle_send_command_error
@@ -11,7 +11,6 @@ from ..tools import str_to_bool
 
 
 @ApiController('/pool')
-@AuthRequired()
 class Pool(RESTController):
 
     @classmethod
index 05409fd9d6d6de4c6e35d1bdb72c4c65f013c7a7..3eca70a6ab1052bf45c7e0c1bac7c981ce141fda 100644 (file)
@@ -11,7 +11,7 @@ import six
 
 import rbd
 
-from . import ApiController, AuthRequired, RESTController, Task
+from . import ApiController, RESTController, Task
 from .. import mgr
 from ..services.ceph_service import CephService
 from ..tools import ViewCache
@@ -113,7 +113,6 @@ def _sort_features(features, enable=True):
 
 
 @ApiController('/block/image')
-@AuthRequired()
 class Rbd(RESTController):
 
     RESOURCE_ID = "pool_name/image_name"
@@ -375,7 +374,6 @@ class Rbd(RESTController):
 
 
 @ApiController('/block/image/:pool_name/:image_name/snap')
-@AuthRequired()
 class RbdSnapshot(RESTController):
 
     RESOURCE_ID = "snapshot_name"
index ceb299170ed2322d417f0f32d1b801754d9dc3be..a1823ed5e7d6ae682a33a665c7704a91d0e102a2 100644 (file)
@@ -8,7 +8,7 @@ from functools import partial
 
 import rbd
 
-from . import ApiController, AuthRequired, Endpoint, BaseController
+from . import ApiController, Endpoint, BaseController
 from .. import logger, mgr
 from ..services.ceph_service import CephService
 from ..tools import ViewCache
@@ -155,7 +155,6 @@ def get_daemons_and_pools():  # pylint: disable=R0915
 
 
 @ApiController('/rbdmirror')
-@AuthRequired()
 class RbdMirror(BaseController):
 
     def __init__(self):
index e1b551aafe64e3a8e171ed92ecbd289c498d3d36..ee989a137fa2f15a3c643d2bcd0f4df8f7ec4bf7 100644 (file)
@@ -4,7 +4,7 @@ from __future__ import absolute_import
 import json
 import cherrypy
 
-from . import ApiController, BaseController, RESTController, AuthRequired, Endpoint
+from . import ApiController, BaseController, RESTController, Endpoint
 from .. import logger
 from ..services.ceph_service import CephService
 from ..services.rgw_client import RgwClient
@@ -13,7 +13,6 @@ from ..exceptions import DashboardException
 
 
 @ApiController('/rgw')
-@AuthRequired()
 class Rgw(BaseController):
 
     @Endpoint()
@@ -37,7 +36,6 @@ class Rgw(BaseController):
 
 
 @ApiController('/rgw/daemon')
-@AuthRequired()
 class RgwDaemon(RESTController):
 
     def list(self):
@@ -97,7 +95,6 @@ class RgwRESTController(RESTController):
 
 
 @ApiController('/rgw/bucket')
-@AuthRequired()
 class RgwBucket(RgwRESTController):
 
     def list(self):
@@ -128,7 +125,6 @@ class RgwBucket(RgwRESTController):
 
 
 @ApiController('/rgw/user')
-@AuthRequired()
 class RgwUser(RgwRESTController):
 
     def list(self):
index d01ee1d1e33e9237e52ee4eaa2feb0890bd735db..59ff0f4015cf2fb472c772bb1dea001e163f2454 100644 (file)
@@ -3,15 +3,15 @@ from __future__ import absolute_import
 
 import json
 
+
+from . import ApiController, Endpoint, BaseController
 from .. import mgr
-from . import AuthRequired, ApiController, Endpoint, BaseController
 from ..controllers.rbd_mirroring import get_daemons_and_pools
 from ..tools import ViewCacheNoDataException
 from ..tools import TaskManager
 
 
 @ApiController('/summary')
-@AuthRequired()
 class Summary(BaseController):
     def _health_status(self):
         health_data = mgr.get("health")
index 537f34158f2b58290ffa3301a4dbab5b65d7b4a1..9380f07015ae74e315c4ac998a30a50c78c159fc 100644 (file)
@@ -1,12 +1,11 @@
 # -*- coding: utf-8 -*-
 from __future__ import absolute_import
 
-from . import ApiController, AuthRequired, RESTController
+from . import ApiController, RESTController
 from ..tools import TaskManager
 
 
 @ApiController('/task')
-@AuthRequired()
 class Task(RESTController):
     def list(self, name=None):
         executing_t, finished_t = TaskManager.list_serializable(name)
index 89e7c8ed890a05d1944ed28bcf87aab2178a85f6..4043b0deeb3479b0dabf90daccd0a668206ab8f6 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import absolute_import
 
-from . import ApiController, AuthRequired, RESTController
+from . import ApiController, RESTController
 from .. import mgr
 from ..services.ceph_service import CephService
 
@@ -9,7 +9,6 @@ SERVICE_TYPE = 'tcmu-runner'
 
 
 @ApiController('/tcmuiscsi')
-@AuthRequired()
 class TcmuIscsi(RESTController):
     # pylint: disable=too-many-nested-blocks
     def list(self):  # pylint: disable=unused-argument
index 8981d3b611a8495991067c59878ad8900450ab06..333f7a377429087d4a8d0f848f17536db1b99dc6 100644 (file)
@@ -6,7 +6,7 @@ from ..controllers import BaseController, RESTController, Controller, \
                           ApiController, Endpoint
 
 
-@Controller("/btest/{key}", base_url="/ui")
+@Controller("/btest/{key}", base_url="/ui", secure=False)
 class BTest(BaseController):
     @Endpoint()
     def test1(self, key, opt=1):
@@ -38,7 +38,7 @@ class BTest(BaseController):
         return {'key': key, 'opt': opt}
 
 
-@ApiController("/rtest/{key}")
+@ApiController("/rtest/{key}", secure=False)
 class RTest(RESTController):
     RESOURCE_ID = 'skey/ekey'
 
@@ -72,7 +72,7 @@ class RTest(RESTController):
         return {'key': key, 'skey': skey, 'ekey': ekey, 'opt': opt}
 
 
-@Controller("/")
+@Controller("/", secure=False)
 class Root(BaseController):
     @Endpoint(json_response=False)
     def __call__(self):
index 8998cd38d81c1d43282972630f953a82a0f90fc8..a6c38d84ef04928ab2893d7988325109bb4a2421 100644 (file)
@@ -13,7 +13,7 @@ from ..tools import ViewCache, TaskManager, NotificationQueue
 
 
 # pylint: disable=W0613
-@Controller('foo')
+@Controller('foo', secure=False)
 class FooResource(RESTController):
 
     @Endpoint()
index 975fcb62d4bc62863c2d54afed5c2e200da18035..f88cb72635808e5a8abc04b3434a49260966a9c6 100644 (file)
@@ -25,7 +25,7 @@ class Grafana(TestCase):
                 url='//localhost:3000', username='admin', password='admin')
 
 
-@Controller('grafana/mocked')
+@Controller('/grafana/mocked', secure=False)
 class GrafanaMockInstance(BaseController):
     @Proxy()
     def __call__(self, path, **params):
index ea7bba23171debd88ca7d483febc2d6425f58598..6e8f01b40b7738da07e1fa728c4f2a2383ae8dd6 100644 (file)
@@ -9,7 +9,7 @@ from ..controllers.task import Task as TaskController
 from ..tools import NotificationQueue, TaskManager
 
 
-@Controller('test/task')
+@Controller('/test/task', secure=False)
 class TaskTest(RESTController):
     sleep_time = 0.0
 
index aaadd1e8af53a6d486919c79d7d463039bed4a92..bd27822931e6273ff44373029ef57a984bedb74c 100644 (file)
@@ -15,7 +15,7 @@ from ..tools import is_valid_ipv6_address, dict_contains_path
 
 
 # pylint: disable=W0613
-@Controller('/foo')
+@Controller('/foo', secure=False)
 class FooResource(RESTController):
     elems = []
 
@@ -40,20 +40,20 @@ class FooResource(RESTController):
         return dict(key=key, newdata=newdata)
 
 
-@Controller('/foo/:key/:method')
+@Controller('/foo/:key/:method', secure=False)
 class FooResourceDetail(RESTController):
     def list(self, key, method):
         return {'detail': (key, [method])}
 
 
-@ApiController('/rgw/proxy')
+@ApiController('/rgw/proxy', secure=False)
 class GenerateControllerRoutesController(BaseController):
     @Proxy()
     def __call__(self, path, **params):
         pass
 
 
-@ApiController('/fooargs')
+@ApiController('/fooargs', secure=False)
 class FooArgs(RESTController):
     def set(self, code, name=None, opt1=None, opt2=None):
         return {'code': code, 'name': name, 'opt1': opt1, 'opt2': opt2}