From 6c814b241d7465113a6edfc023fa6ef9314f4591 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Mon, 22 Nov 2021 13:42:29 +0100 Subject: [PATCH] Add SYSTEM_SCOPE_SERVICES setting that hides panels Since not all services are ready to use the system scope token, we need a way to disable and enable the use of system scope token on a per-service basis. This setting let us configure which services should use the system scope token. By default the list is empty and system scope token is not used at all. Change-Id: I5e0cdc7288221571f183a37b800c19dc4cff5707 --- doc/source/configuration/settings.rst | 13 +++++++++++++ .../dashboards/admin/aggregates/panel.py | 7 +++++++ .../dashboards/admin/defaults/panel.py | 7 +++++++ .../dashboards/admin/flavors/panel.py | 7 +++++++ .../dashboards/admin/floating_ips/panel.py | 7 +++++++ .../dashboards/admin/hypervisors/panel.py | 7 +++++++ .../dashboards/admin/images/panel.py | 7 +++++++ openstack_dashboard/dashboards/admin/info/panel.py | 7 +++++++ .../dashboards/admin/instances/panel.py | 7 +++++++ .../dashboards/admin/metadata_defs/panel.py | 7 +++++++ .../dashboards/admin/networks/panel.py | 7 +++++++ .../dashboards/admin/overview/panel.py | 7 +++++++ .../dashboards/admin/rbac_policies/panel.py | 4 ++++ .../dashboards/admin/routers/panel.py | 7 +++++++ .../dashboards/admin/trunks/panel.py | 4 ++++ .../dashboards/identity/dashboard.py | 7 +++++++ openstack_dashboard/defaults.py | 5 +++++ .../templates/header/_context_selection.html | 4 ++-- .../templatetags/context_selection.py | 4 +++- .../feature-system-scope-a88a07b7f414b3d6.yaml | 9 +++++++++ 20 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/feature-system-scope-a88a07b7f414b3d6.yaml diff --git a/doc/source/configuration/settings.rst b/doc/source/configuration/settings.rst index 0d577c1bcb..7c84f656f7 100644 --- a/doc/source/configuration/settings.rst +++ b/doc/source/configuration/settings.rst @@ -2656,3 +2656,16 @@ generated ``kubeconfig`` file. .. seealso:: `KUBECONFIG_ENABLED`_ to enable the ``kubeconfig`` file generation. + + +SYSTEM_SCOPE_SERVICES +--------------------- +.. versionadded:: 21.1.0(Yoga) + +Default: ``[]`` + +A list of names of services for which the system scope token should be used. +If empty, system scope will be removed from the context switching menu. If not +empty, the context switching menu will show a "system scope" option, and the +admin panels for the services listed will be moved to that context, no longer +showing up in the project context. diff --git a/openstack_dashboard/dashboards/admin/aggregates/panel.py b/openstack_dashboard/dashboards/admin/aggregates/panel.py index 4d553ea875..315bef2e05 100644 --- a/openstack_dashboard/dashboards/admin/aggregates/panel.py +++ b/openstack_dashboard/dashboards/admin/aggregates/panel.py @@ -12,6 +12,7 @@ import logging +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -25,3 +26,9 @@ class Aggregates(horizon.Panel): slug = 'aggregates' policy_rules = (("compute", "compute_extension:aggregates"),) permissions = ('openstack.services.compute',) + + def allowed(self, context): + if (('compute' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/defaults/panel.py b/openstack_dashboard/dashboards/admin/defaults/panel.py index 9dfee0267d..2d95973881 100644 --- a/openstack_dashboard/dashboards/admin/defaults/panel.py +++ b/openstack_dashboard/dashboards/admin/defaults/panel.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -22,3 +23,9 @@ class Defaults(horizon.Panel): slug = 'defaults' policy_rules = (("compute", "context_is_admin"), ("volume", "context_is_admin"),) + + def allowed(self, context): + if (('compute' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/flavors/panel.py b/openstack_dashboard/dashboards/admin/flavors/panel.py index 772e73aed9..3cf3203b43 100644 --- a/openstack_dashboard/dashboards/admin/flavors/panel.py +++ b/openstack_dashboard/dashboards/admin/flavors/panel.py @@ -16,6 +16,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -26,3 +27,9 @@ class Flavors(horizon.Panel): slug = 'flavors' permissions = ('openstack.services.compute',) policy_rules = (("compute", "context_is_admin"),) + + def allowed(self, context): + if (('compute' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/floating_ips/panel.py b/openstack_dashboard/dashboards/admin/floating_ips/panel.py index 9d117b0773..3a8e5b80aa 100644 --- a/openstack_dashboard/dashboards/admin/floating_ips/panel.py +++ b/openstack_dashboard/dashboards/admin/floating_ips/panel.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -30,3 +31,9 @@ class AdminFloatingIps(horizon.Panel): def can_register(): return setting_utils.get_dict_config( 'OPENSTACK_NEUTRON_NETWORK', 'enable_router') + + def allowed(self, context): + if (('network' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/hypervisors/panel.py b/openstack_dashboard/dashboards/admin/hypervisors/panel.py index 5b29a5ec41..d02097bf91 100644 --- a/openstack_dashboard/dashboards/admin/hypervisors/panel.py +++ b/openstack_dashboard/dashboards/admin/hypervisors/panel.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -22,3 +23,9 @@ class Hypervisors(horizon.Panel): slug = 'hypervisors' permissions = ('openstack.services.compute',) policy_rules = (("compute", "os_compute_api:os-hypervisors"),) + + def allowed(self, context): + if (('compute' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/images/panel.py b/openstack_dashboard/dashboards/admin/images/panel.py index 2f6505ba97..b6f9a55ff0 100644 --- a/openstack_dashboard/dashboards/admin/images/panel.py +++ b/openstack_dashboard/dashboards/admin/images/panel.py @@ -16,6 +16,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -27,3 +28,9 @@ class Images(horizon.Panel): permissions = ('openstack.services.image',) policy_rules = ((("image", "context_is_admin"), ("image", "get_images")),) + + def allowed(self, context): + if (('compute' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/info/panel.py b/openstack_dashboard/dashboards/admin/info/panel.py index d314a8fd4e..9aa04aff24 100644 --- a/openstack_dashboard/dashboards/admin/info/panel.py +++ b/openstack_dashboard/dashboards/admin/info/panel.py @@ -16,6 +16,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -27,3 +28,9 @@ class Info(horizon.Panel): policy_rules = (("compute", "context_is_admin"), ("volume", "context_is_admin"), ("network", "context_is_admin"),) + + def allowed(self, context): + if (('compute' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/instances/panel.py b/openstack_dashboard/dashboards/admin/instances/panel.py index b0eb711694..0a4c21b977 100644 --- a/openstack_dashboard/dashboards/admin/instances/panel.py +++ b/openstack_dashboard/dashboards/admin/instances/panel.py @@ -16,6 +16,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -27,3 +28,9 @@ class Instances(horizon.Panel): permissions = ('openstack.services.compute',) policy_rules = ((("compute", "context_is_admin"), ("compute", "os_compute_api:servers:detail")),) + + def allowed(self, context): + if (('compute' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/metadata_defs/panel.py b/openstack_dashboard/dashboards/admin/metadata_defs/panel.py index 3baa4b1e17..32d8f78926 100644 --- a/openstack_dashboard/dashboards/admin/metadata_defs/panel.py +++ b/openstack_dashboard/dashboards/admin/metadata_defs/panel.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -30,3 +31,9 @@ class MetadataDefinitions(horizon.Panel): @staticmethod def can_register(): return glance.VERSIONS.active >= 2 + + def allowed(self, context): + if (('image' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/networks/panel.py b/openstack_dashboard/dashboards/admin/networks/panel.py index f1ce7638ee..821ce2101b 100644 --- a/openstack_dashboard/dashboards/admin/networks/panel.py +++ b/openstack_dashboard/dashboards/admin/networks/panel.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -22,3 +23,9 @@ class Networks(horizon.Panel): slug = 'networks' permissions = ('openstack.services.network',) policy_rules = (("network", "context_is_admin"),) + + def allowed(self, context): + if (('network' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/overview/panel.py b/openstack_dashboard/dashboards/admin/overview/panel.py index afd55aa397..b7f67a6733 100644 --- a/openstack_dashboard/dashboards/admin/overview/panel.py +++ b/openstack_dashboard/dashboards/admin/overview/panel.py @@ -16,6 +16,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -30,5 +31,11 @@ class Overview(horizon.Panel): ('compute', 'context_is_admin')),) permissions = ('openstack.services.compute',) + def allowed(self, context): + if (('compute' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) + dashboard.Admin.register(Overview) diff --git a/openstack_dashboard/dashboards/admin/rbac_policies/panel.py b/openstack_dashboard/dashboards/admin/rbac_policies/panel.py index 18a7a6f57f..b3198db399 100644 --- a/openstack_dashboard/dashboards/admin/rbac_policies/panel.py +++ b/openstack_dashboard/dashboards/admin/rbac_policies/panel.py @@ -12,6 +12,7 @@ import logging +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -29,6 +30,9 @@ class RBACPolicies(horizon.Panel): policy_rules = (("network", "context_is_admin"),) def allowed(self, context): + if (('network' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False request = context['request'] try: return ( diff --git a/openstack_dashboard/dashboards/admin/routers/panel.py b/openstack_dashboard/dashboards/admin/routers/panel.py index 3dc5444b1a..304737e24f 100644 --- a/openstack_dashboard/dashboards/admin/routers/panel.py +++ b/openstack_dashboard/dashboards/admin/routers/panel.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -29,3 +30,9 @@ class Routers(horizon.Panel): def can_register(): return setting_utils.get_dict_config( 'OPENSTACK_NEUTRON_NETWORK', 'enable_router') + + def allowed(self, context): + if (('network' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().allowed(context) diff --git a/openstack_dashboard/dashboards/admin/trunks/panel.py b/openstack_dashboard/dashboards/admin/trunks/panel.py index 8d5f702a02..b312c72f59 100644 --- a/openstack_dashboard/dashboards/admin/trunks/panel.py +++ b/openstack_dashboard/dashboards/admin/trunks/panel.py @@ -14,6 +14,7 @@ import logging +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -30,6 +31,9 @@ class Trunks(horizon.Panel): policy_rules = (("trunk", "context_is_admin"),) def allowed(self, context): + if (('network' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False request = context['request'] try: return ( diff --git a/openstack_dashboard/dashboards/identity/dashboard.py b/openstack_dashboard/dashboards/identity/dashboard.py index 63d61bf56f..9e2893fffd 100644 --- a/openstack_dashboard/dashboards/identity/dashboard.py +++ b/openstack_dashboard/dashboards/identity/dashboard.py @@ -13,6 +13,7 @@ # under the License. +from django.conf import settings from django.utils.translation import gettext_lazy as _ import horizon @@ -22,5 +23,11 @@ class Identity(horizon.Dashboard): name = _("Identity") slug = "identity" + def can_access(self, context): + if (('identity' in settings.SYSTEM_SCOPE_SERVICES) != + bool(context['request'].user.system_scoped)): + return False + return super().can_access(context) + horizon.register(Identity) diff --git a/openstack_dashboard/defaults.py b/openstack_dashboard/defaults.py index 30d7785b89..4ed8d1fc58 100644 --- a/openstack_dashboard/defaults.py +++ b/openstack_dashboard/defaults.py @@ -551,3 +551,8 @@ REST_API_ADDITIONAL_SETTINGS = [] KUBECONFIG_ENABLED = False KUBECONFIG_KUBERNETES_URL = "" KUBECONFIG_CERTIFICATE_AUTHORITY_DATA = "" + + +# Services may require a System Scope token for certain operations. This +# settings enables the use of the system scope token on per-service basis. +SYSTEM_SCOPE_SERVICES = [] diff --git a/openstack_dashboard/templates/header/_context_selection.html b/openstack_dashboard/templates/header/_context_selection.html index e75b2962f4..080b8a3818 100644 --- a/openstack_dashboard/templates/header/_context_selection.html +++ b/openstack_dashboard/templates/header/_context_selection.html @@ -31,8 +31,8 @@ {% endif %} - {% is_system_user as system_user %} - {% if system_user %} + {% show_systems as system_scope_enabled %} + {% if system_scope_enabled %}
  • {% show_system_list %}
  • diff --git a/openstack_dashboard/templatetags/context_selection.py b/openstack_dashboard/templatetags/context_selection.py index 08cf1b903c..afcdaa933f 100644 --- a/openstack_dashboard/templatetags/context_selection.py +++ b/openstack_dashboard/templatetags/context_selection.py @@ -42,7 +42,9 @@ def is_multidomain(): @register.simple_tag(takes_context=True) -def is_system_user(context): +def show_systems(context): + if not settings.SYSTEM_SCOPE_SERVICES: + return False try: request = context['request'] except KeyError: diff --git a/releasenotes/notes/feature-system-scope-a88a07b7f414b3d6.yaml b/releasenotes/notes/feature-system-scope-a88a07b7f414b3d6.yaml new file mode 100644 index 0000000000..dc02a760ed --- /dev/null +++ b/releasenotes/notes/feature-system-scope-a88a07b7f414b3d6.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + Horizon can now use a system scope token when performing admin operations. + To enable that, a new setting, SYSTEM_SCOPE_SERVICES, has to list the + OpenStack services for which this feature is to be enabled. When that + setting is not empty, a new option, "system scope" will appear in the + context switching menu, and the panels for the listed services will be + moved into that context in the main menu.