Introduce project scope_types in VNF LCM policy

oslo.policy introduced the scope_type feature which can
control the access level at system-level and project-level.
 - https://docs.openstack.org/oslo.policy/latest/user/usage.html#setting-scope

As per the SRBAC design, OpenStack does not support system scope so
we need to make scope type of each policy rule to project.

- https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html#phase-1

The policy with 'project' scope means user with 'project-scoped'
token have permission to access which is nothing but the current
case so no change in permission level. By adding the scope_type
to project explicitly gives benefit of better error message. For
example, if any user with system scope token try to access tacker
APIs then oslo policy will fail early (instead of failing in lower
layer at DB or VIM level) and give clear error message of invalid
scope.

This commit adds project scope in VNF LCM policies and its tests
also.

Partial implement blueprint implement-project-personas

Change-Id: Iead7f82b8c22c0c67981f5a7ae3a86016ee64734
This commit is contained in:
Ghanshyam Mann 2024-02-10 20:40:11 -08:00 committed by Ghanshyam
parent 0d9984199f
commit f421f25d65
3 changed files with 94 additions and 17 deletions

View File

@ -31,7 +31,8 @@ rules = [
'method': 'GET',
'path': '/vnflcm/v1/api_versions'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'create',
@ -42,7 +43,8 @@ rules = [
'method': 'POST',
'path': '/vnflcm/v1/vnf_instances'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'instantiate',
@ -53,7 +55,8 @@ rules = [
'method': 'POST',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}/instantiate'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'show',
@ -64,7 +67,8 @@ rules = [
'method': 'GET',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'terminate',
@ -75,7 +79,8 @@ rules = [
'method': 'POST',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}/terminate'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'heal',
@ -86,7 +91,8 @@ rules = [
'method': 'POST',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}/heal'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'scale',
@ -97,7 +103,8 @@ rules = [
'method': 'POST',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}/scale'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'show_lcm_op_occs',
@ -108,7 +115,8 @@ rules = [
'method': 'GET',
'path': '/vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'list_lcm_op_occs',
@ -119,7 +127,8 @@ rules = [
'method': 'GET',
'path': '/vnflcm/v1/vnf_lcm_op_occs'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'index',
@ -130,7 +139,8 @@ rules = [
'method': 'GET',
'path': '/vnflcm/v1/vnf_instances'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'delete',
@ -141,7 +151,8 @@ rules = [
'method': 'DELETE',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'update_vnf',
@ -152,7 +163,8 @@ rules = [
'method': 'PATCH',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'rollback',
@ -163,7 +175,8 @@ rules = [
'method': 'POST',
'path': '/vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/rollback'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'cancel',
@ -174,7 +187,8 @@ rules = [
'method': 'POST',
'path': '/vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/cancel'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'fail',
@ -185,7 +199,8 @@ rules = [
'method': 'POST',
'path': '/vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/fail'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'retry',
@ -196,7 +211,8 @@ rules = [
'method': 'POST',
'path': '/vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/retry'
}
]
],
scope_types=['project'],
),
policy.DocumentedRuleDefault(
name=VNFLCM % 'change_ext_conn',
@ -208,7 +224,8 @@ rules = [
'path':
'/vnflcm/v1/vnf_instances/{vnfInstanceId}/change_ext_conn'
}
]
],
scope_types=['project'],
),
]

View File

@ -69,6 +69,24 @@ class BasePolicyTest(base.TestCase):
project_id=self.other_project_id,
roles=['reader'])
# system scoped users to check if system scope tokens are not
# allowed in new RBAC.
self.system_admin_context = context.Context(
user_id="admin", roles=['admin', 'member', 'reader'],
system_scope='all')
self.system_member_context = context.Context(
user_id="member", roles=['member', 'reader'],
system_scope='all')
self.system_reader_context = context.Context(
user_id="reader", roles=['reader'],
system_scope='all')
self.system_foo_context = context.Context(
user_id="foo", roles=['foo'],
system_scope='all')
self.all_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,

View File

@ -15,6 +15,8 @@
from unittest import mock
from oslo_config import cfg
from tacker.api.vnflcm.v1 import controller
import tacker.conductor.conductorrpc.vnf_lcm_rpc as vnf_lcm_rpc
from tacker import objects
@ -428,3 +430,43 @@ class VNFLCMPolicyTest(base_test.BasePolicyTest):
self.controller.change_ext_conn,
req, uuidsentinel.instance_id,
body=body)
class VNFLCMScopeTypePolicyTest(VNFLCMPolicyTest):
"""Test VNF LCM APIs policies with scope enabled.
This class set the tacker.conf [oslo_policy] enforce_scope to True
so that we can switch on the scope checking on oslo policy side.
This check that system scope users are not allowed to access the
Tacker VNF LCM APIs.
"""
def setUp(self):
super(VNFLCMScopeTypePolicyTest, self).setUp()
cfg.CONF.set_override('enforce_scope', True,
group='oslo_policy')
self.project_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
# With scope enabled, system scoped users will not be
# allowed to create VNF or a few of the VNF operations
# in their project.
self.project_unauthorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context, self.system_foo_context
]
self.project_member_authorized_contexts = [
self.legacy_admin_context, self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.project_foo_context
]
# With scope enabled, system scoped users will not be allowed
# to get, instantiate, terminate etc operations of VNF
self.project_member_unauthorized_contexts = [
self.system_admin_context, self.system_member_context,
self.system_reader_context, self.system_foo_context,
self.other_project_member_context,
self.other_project_reader_context]