Files
distcloud/distributedcloud/dcorch/common/context.py
amantri 474c63ae4e Implement configurator role RBAC for dc related processes
This commit implements RBAC for configurator role, this role
has the same level of access as the existing admin role.
The existing base rules are changed to accommodate the new
configurator role. For the incoming create,delete,modify requests the
admin access is provided by authorizing the user with the policy rules.

Test Plan:
PASS: Expect only admin,operator,configurator role users can
      execute the following commands
	dcmanager subcloud manage <subcloud>
	dcmanager subcloud unmanage <subcloud>
	dcmanager subcloud-backup create --subcloud
	dcmanager subcloud-backup delete --subcloud
PASS: Expect configurator,admin,operator,reader role users
      allowed to execute the following command
	dcmanager alarm summary
PASS: Verify only configurator,admin allowed to do the
      following
	dcmanager subcloud prestage
	dcmanager subcloud reconfigure
	dcmanager subcloud reinstall
	dcmanager subcloud redeploy
	dcmanager subcloud restore
	dcmanager subcloud update_status
        dcmanager subcloud update
        dcmanager subcloud delete <subcloud>
        dcmanager patch-strategy create
        dcmanager patch-strategy apply
        dcmanager patch-strategy abort
        dcmanager patch-strategy delete
        dcmanager subcloud-group add
        dcmanager subcloud-group delete
	dcmanager subcloud-deploy upload
        dcmanager kube-rootca-update-strategy create/delete
        dcmanager patch-strategy-config update
        dcmanager subcloud-peer-group add/delete
        dcmanager sw-deploy-strategy create/delete
        dcmanager peer-group-association add/delete
	dcmanager system-peer add/delete

Story: 2011348
Task: 52055

Change-Id: I9e7d5932f0d158f20db1c9741e9b6c707cedf28a
Signed-off-by: amantri <ayyappa.mantri@windriver.com>
2025-05-05 16:44:05 +00:00

172 lines
5.5 KiB
Python

# Copyright (c) 2020-2022, 2024-2025 Wind River Systems, Inc.
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import pecan
from pecan import hooks
from oslo_context import context as base_context
from oslo_utils import encodeutils
from dcorch.api.policies import base as base_policy
from dcorch.api import policy
from dcorch.db import api as db_api
ALLOWED_WITHOUT_AUTH = "/"
class RequestContext(base_context.RequestContext):
"""Stores information about the security context.
The context encapsulates information related to the user accessing the
the system, as well as additional request information.
"""
def __init__(
self,
auth_token=None,
user=None,
project=None,
domain=None,
user_domain=None,
project_domain=None,
is_admin=None,
read_only=False,
show_deleted=False,
request_id=None,
auth_url=None,
trusts=None,
user_name=None,
project_name=None,
domain_name=None,
user_domain_name=None,
project_domain_name=None,
auth_token_info=None,
region_name=None,
roles=None,
password=None,
**kwargs
):
"""Initializer of request context."""
# We still have 'tenant' param because oslo_context still use it.
# pylint: disable=E1123
super(RequestContext, self).__init__(
auth_token=auth_token,
user=user,
tenant=project,
domain=domain,
user_domain=user_domain,
project_domain=project_domain,
roles=roles,
read_only=read_only,
show_deleted=show_deleted,
request_id=request_id,
)
# request_id might be a byte array
self.request_id = encodeutils.safe_decode(self.request_id)
# we save an additional 'project' internally for use
self.project = project
# Session for DB access
self._session = None
self.auth_url = auth_url
self.trusts = trusts
self.user_name = user_name
self.project_name = project_name
self.domain_name = domain_name
self.user_domain_name = user_domain_name
self.project_domain_name = project_domain_name
self.auth_token_info = auth_token_info
self.region_name = region_name
self.roles = roles or []
self.password = password
# Check user is admin or not
if is_admin is None:
self.is_admin = policy.authorize(
base_policy.ADMIN_OR_CONFIGURATOR, {}, self.to_dict(), do_raise=False
)
else:
self.is_admin = is_admin
@property
def session(self):
if self._session is None:
self._session = db_api.get_session()
return self._session
def to_dict(self):
return {
"auth_url": self.auth_url,
"auth_token": self.auth_token,
"auth_token_info": self.auth_token_info,
"user": self.user,
"user_name": self.user_name,
"user_domain": self.user_domain,
"user_domain_name": self.user_domain_name,
"project": self.project,
"project_name": self.project_name,
"project_domain": self.project_domain,
"project_domain_name": self.project_domain_name,
"domain": self.domain,
"domain_name": self.domain_name,
"trusts": self.trusts,
"region_name": self.region_name,
"roles": self.roles,
"show_deleted": self.show_deleted,
"is_admin": self.is_admin,
"request_id": self.request_id,
"password": self.password,
}
@classmethod
def from_dict(cls, values):
return cls(**values)
def get_admin_context(show_deleted=False):
return RequestContext(is_admin=True, show_deleted=show_deleted)
def get_service_context(**args):
"""An abstraction layer for getting service context.
There could be multiple cloud backends for dcorch-engine to use. This
abstraction layer provides an indirection for dcorch-engine to get the
credentials of 'dcorch' user on the specific cloud. By default,
this credential refers to the credentials built for keystone middleware
in an OpenStack cloud.
"""
pass
class AuthHook(hooks.PecanHook):
def before(self, state):
if state.request.path == ALLOWED_WITHOUT_AUTH:
return
req = state.request
identity_status = req.headers.get("X-Identity-Status")
service_identity_status = req.headers.get("X-Service-Identity-Status")
if identity_status == "Confirmed" or service_identity_status == "Confirmed":
return
if req.headers.get("X-Auth-Token"):
msg = "Auth token is invalid: %s" % req.headers["X-Auth-Token"]
else:
msg = "Authentication required"
msg = "Failed to validate access token: %s" % str(msg)
pecan.abort(status_code=401, detail=msg)