Merge "Implement configurator role RBAC for sysinv API"

This commit is contained in:
Zuul 2025-04-14 15:31:37 +00:00 committed by Gerrit Code Review
commit 61802367ee
10 changed files with 211 additions and 48 deletions

View File

@ -57,6 +57,9 @@ def _install_cert(cc, certificate_file, data):
try:
response = cc.certificate.certificate_install(sec_file, data=data)
err_msg = response.get('error_message')
if err_msg:
raise exc.HTTPForbidden(err_msg)
except exc.HTTPNotFound:
raise exc.CommandError('Certificate not installed %s. No response.' %
certificate_file)

View File

@ -1,23 +1,80 @@
---
# The commented lines below contains the default values for presented rules.
# admin role of admin,services projects
# "admin": "role:admin and (project_name:admin or project_name:services)"
# admin_in_system_projects: role:admin and (project_name:admin or project_name:services)
# reader_or_operator_in_system_projects: (role:reader or role:operator) and
# (project_name:admin or project_name:services)
# admin_or_operator_in_system_projects: (role:admin or role:operator) and
# (project_name:admin or project_name:services)
# admin,configurator roles of admin,services projects
# "admin_or_configurator": "(role:admin or role:configurator) and
# (project_name:admin or project_name:services)"
# config_api:service_parameter:add: rule:admin_in_system_projects
# config_api:service_parameter:apply: rule:admin_in_system_projects
# config_api:service_parameter:delete: rule:admin_in_system_projects
# config_api:service_parameter:get: rule:reader_or_operator_in_system_projects
# config_api:service_parameter:modify: rule:admin_or_operator_in_system_projects
# admin,operator,configurator roles of admin,services projects
# "admin_or_operator_or_configurator": "(role:admin or role:operator or
# role:configurator) and (project_name:admin or project_name:services)"
# config_api:ihosts:add: rule:admin_in_system_projects
# config_api:ihosts:delete: rule:admin_in_system_projects
# config_api:ihosts:get: rule:reader_or_operator_in_system_projects
# config_api:ihosts:modify: rule:admin_or_operator_in_system_projects
# reader,operator,configurator roles of admin,services projects
# "reader_or_operator_or_configurator": "(role:reader or role:operator or
# role:configurator) and (project_name:admin or project_name:services)"
# config_api:registry_image:add: rule:admin_or_operator_in_system_projects
# config_api:registry_image:delete: rule:admin_in_system_projects
# config_api:registry_image:get: "rule:reader_or_operator_in_system_projects
# Add a Service Parameter.
# POST /v1/service_parameter
# "config_api:service_parameter:add": "rule:admin_or_configurator"
# Apply Service Parameters.
# POST /v1/service_parameter/apply
# "config_api:service_parameter:apply": "rule:admin_or_configurator"
# Delete a Service Parameter.
# DELETE /v1/service_parameter/{parameter_id}
# "config_api:service_parameter:delete": "rule:admin_or_configurator"
# Get Service Parameters.
# GET /v1/service_parameter
# GET /v1/service_parameter/{parameter_id}
# "config_api:service_parameter:get": "rule:reader_or_operator_or_configurator"
# Modify Service Parameter value.
# PATCH /v1/service_parameter/{parameter_id}
# "config_api:service_parameter:modify": "rule:admin_or_configurator"
# Add a host Parameter.
# POST /v1/ihosts
# "config_api:ihosts:post": "rule:admin_or_configurator"
# Delete a host Parameter.
# DELETE /v1/ihosts/{parameter_id}
# "config_api:ihosts:delete": "rule:admin_or_configurator"
# Get host Parameters.
# GET /v1/ihosts
# GET /v1/ihosts/{parameter_id}
# "config_api:ihosts:get": "rule:reader_or_operator_or_configurator"
# Modify host value.
# PATCH /v1/ihosts/{parameter_id}
# "config_api:ihosts:patch": "rule:admin_or_operator_or_configurator"
# Run registry garbage collect.
# POST /v1/registry_image
# "config_api:registry_image:add": "rule:admin_or_operator_or_configurator"
# Delete a registry image.
# DELETE /v1/registry_image
# "config_api:registry_image:delete": "rule:admin_or_configurator"
# Get registry images list.
# GET /v1/registry_image
# "config_api:registry_image:get": "rule:reader_or_operator_or_configurator"
# Get certificate
# GET /v1/certificate
# GET /v1/certificate/{parameter_id}
# GET /v1/certificate/get_all_certs
# GET /v1/certificate/get_all_k8s_certs
# "config_api:certificate:get": "rule:reader_or_operator_or_configurator"
# Delete certificate
# DELETE /v1/certificate/{parameter_id}
# "config_api:certificate:delete": "rule:admin"
# install/renew certificate
# POST /v1/certificate/certificate_install
# POST /v1/certificate/certificate_renew
# "config_api:certificate:post": "rule:admin"

View File

@ -39,9 +39,11 @@ from sysinv.api.controllers.v1 import collection
from sysinv.api.controllers.v1 import link
from sysinv.api.controllers.v1 import types
from sysinv.api.controllers.v1 import utils
from sysinv.api.policies import certificate as cert_policy
from sysinv.common import constants
from sysinv.common import exception
from sysinv.common import kubernetes as sys_kube
from sysinv.common import policy
from sysinv.common import utils as cutils
from sysinv.openstack.common.rpc.common import RemoteError
from wsme import types as wtypes
@ -647,6 +649,18 @@ class CertificateController(rest.RestController):
return soon_to_expiry_certs
return cert_data
def enforce_policy(self, method_name, request):
"""Check policy rules for each action of this controller."""
context_dict = request.context.to_dict()
if method_name in ["get_all", "get_one", "get_all_certs", "get_all_k8s_certs"]:
policy.authorize(cert_policy.POLICY_ROOT % "get", {}, context_dict)
elif method_name in ["certificate_install", "certificate_renew"]:
policy.authorize(cert_policy.POLICY_ROOT % "post", {}, context_dict)
elif method_name in ["delete"]:
policy.authorize(cert_policy.POLICY_ROOT % method_name, {}, context_dict)
else:
raise exception.PolicyNotFound()
def _check_endpoint_domain_exists():
# Check that public endpoint FQDN is configured

View File

@ -164,7 +164,7 @@ class ContextHook(hooks.PecanHook):
'project_name': project_name,
'roles': roles
}
is_admin = policy.authorize(base_policy.ADMIN_IN_SYSTEM_PROJECTS, {},
is_admin = policy.authorize(base_policy.ADMIN_OR_CONFIGURATOR, {},
credentials, do_raise=False)
utils.safe_rstrip(state.request.path, '/')
@ -209,12 +209,12 @@ class AccessPolicyHook(hooks.PecanHook):
if method == 'GET':
role = "reader or operator"
has_api_access = policy.authorize(
base_policy.READER_OR_OPERATOR_IN_SYSTEM_PROJECTS, {},
base_policy.READER_OR_OPERATOR_OR_CONFIGURATOR, {},
context.to_dict(), do_raise=False)
else:
role = "admin"
has_api_access = policy.authorize(
base_policy.ADMIN_IN_SYSTEM_PROJECTS, {},
base_policy.ADMIN_OR_CONFIGURATOR, {},
context.to_dict(), do_raise=False)
if not has_api_access:
raise exc.HTTPForbidden("Not allowed/Role " + role + " is needed")

View File

@ -20,6 +20,7 @@ from sysinv.api.policies import base
from sysinv.api.policies import ihosts
from sysinv.api.policies import registry_image
from sysinv.api.policies import service_parameter
from sysinv.api.policies import certificate
def list_rules():
@ -27,5 +28,6 @@ def list_rules():
base.list_rules(),
service_parameter.list_rules(),
ihosts.list_rules(),
registry_image.list_rules()
registry_image.list_rules(),
certificate.list_rules(),
)

View File

@ -16,28 +16,38 @@
from oslo_policy import policy
ADMIN_IN_SYSTEM_PROJECTS = 'admin_in_system_projects'
READER_OR_OPERATOR_IN_SYSTEM_PROJECTS = 'reader_or_operator_in_system_projects'
ADMIN_OR_OPERATOR_IN_SYSTEM_PROJECTS = 'admin_or_operator_in_system_projects'
ADMIN = 'admin'
ADMIN_OR_CONFIGURATOR = 'admin_or_configurator'
READER_OR_OPERATOR_OR_CONFIGURATOR = 'reader_or_operator_or_configurator'
ADMIN_OR_OPERATOR_OR_CONFIGURATOR = 'admin_or_operator_or_configurator'
base_rules = [
policy.RuleDefault(
name=ADMIN_IN_SYSTEM_PROJECTS,
name=ADMIN,
check_str='role:admin and (project_name:admin or ' +
'project_name:services)',
description="Base rule.",
description='admin role of admin,services projects',
),
policy.RuleDefault(
name=ADMIN_OR_OPERATOR_IN_SYSTEM_PROJECTS,
check_str='(role:admin or role:operator) and (project_name:admin or ' +
'project_name:services)',
description="Base rule."
name=ADMIN_OR_CONFIGURATOR,
check_str='(role:admin or role:configurator) and ' +
'(project_name:admin or project_name:services)',
description='admin,configurator roles of admin,services ' +
'projects',
),
policy.RuleDefault(
name=READER_OR_OPERATOR_IN_SYSTEM_PROJECTS,
check_str='(role:reader or role:operator) and (project_name:admin or ' +
'project_name:services)',
description="Base rule."
name=ADMIN_OR_OPERATOR_OR_CONFIGURATOR,
check_str='(role:admin or role:operator or role:configurator) and ' +
'(project_name:admin or project_name:services)',
description='admin,operator,configurator roles of admin,services ' +
'projects',
),
policy.RuleDefault(
name=READER_OR_OPERATOR_OR_CONFIGURATOR,
check_str='(role:reader or role:operator or role:configurator) and ' +
'(project_name:admin or project_name:services)',
description='reader,operator,configurator roles of admin,services ' +
'projects',
)
]

View File

@ -0,0 +1,77 @@
# Copyright (c) 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.
#
# SPDX-License-Identifier: Apache-2.0
from oslo_policy import policy
from sysinv.api.policies import base
POLICY_ROOT = 'config_api:certificate:%s'
certificate_rules = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'get',
check_str='rule:' + base.READER_OR_OPERATOR_OR_CONFIGURATOR,
description="Get certificate",
operations=[
{
'method': 'GET',
'path': '/v1/certificate'
},
{
'method': 'GET',
'path': '/v1/certificate/{parameter_id}'
},
{
'method': 'GET',
'path': '/v1/certificate/get_all_certs'
},
{
'method': 'GET',
'path': '/v1/certificate/get_all_k8s_certs'
}
]
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str='rule:' + base.ADMIN,
description="Delete certificate",
operations=[
{
'method': 'DELETE',
'path': '/v1/certificate/{parameter_id}'
}
]
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'post',
check_str='rule:' + base.ADMIN,
description="install/renew certificate",
operations=[
{
'method': 'POST',
'path': '/v1/certificate/certificate_install'
},
{
'method': 'POST',
'path': '/v1/certificate/certificate_renew'
},
]
),
]
def list_rules():
return certificate_rules

View File

@ -23,7 +23,7 @@ POLICY_ROOT = 'config_api:ihosts:%s'
ihosts_rules = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'post',
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.ADMIN_OR_CONFIGURATOR,
description="Add a host Parameter.",
operations=[
{
@ -34,7 +34,7 @@ ihosts_rules = [
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.ADMIN_OR_CONFIGURATOR,
description="Delete a host Parameter.",
operations=[
{
@ -45,7 +45,7 @@ ihosts_rules = [
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'get',
check_str='rule:' + base.READER_OR_OPERATOR_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.READER_OR_OPERATOR_OR_CONFIGURATOR,
description="Get host Parameters.",
operations=[
{
@ -60,7 +60,7 @@ ihosts_rules = [
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'patch',
check_str='rule:' + base.ADMIN_OR_OPERATOR_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.ADMIN_OR_OPERATOR_OR_CONFIGURATOR,
description="Modify host value.",
operations=[
{

View File

@ -23,7 +23,7 @@ POLICY_ROOT = 'config_api:registry_image:%s'
registry_image_rules = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'add',
check_str='rule:' + base.ADMIN_OR_OPERATOR_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.ADMIN_OR_OPERATOR_OR_CONFIGURATOR,
description="Run registry garbage collect.",
operations=[
{
@ -34,7 +34,7 @@ registry_image_rules = [
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.ADMIN_OR_CONFIGURATOR,
description="Delete a registry image.",
operations=[
{
@ -45,7 +45,7 @@ registry_image_rules = [
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'get',
check_str='rule:' + base.READER_OR_OPERATOR_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.READER_OR_OPERATOR_OR_CONFIGURATOR,
description="Get registry images list.",
operations=[
{

View File

@ -23,7 +23,7 @@ POLICY_ROOT = 'config_api:service_parameter:%s'
service_parameter_rules = [
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'add',
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.ADMIN_OR_CONFIGURATOR,
description="Add a Service Parameter.",
operations=[
{
@ -34,7 +34,7 @@ service_parameter_rules = [
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'apply',
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.ADMIN_OR_CONFIGURATOR,
description="Apply Service Parameters.",
operations=[
{
@ -45,7 +45,7 @@ service_parameter_rules = [
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'delete',
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.ADMIN_OR_CONFIGURATOR,
description="Delete a Service Parameter.",
operations=[
{
@ -56,7 +56,7 @@ service_parameter_rules = [
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'get',
check_str='rule:' + base.READER_OR_OPERATOR_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.READER_OR_OPERATOR_OR_CONFIGURATOR,
description="Get Service Parameters.",
operations=[
{
@ -71,7 +71,7 @@ service_parameter_rules = [
),
policy.DocumentedRuleDefault(
name=POLICY_ROOT % 'modify',
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
check_str='rule:' + base.ADMIN_OR_CONFIGURATOR,
description="Modify Service Parameter value.",
operations=[
{