Add new policy list_all_projects for share/share-snapshot

Administrator can now configure new policy `list_all_projects` for share
and share snapshot. This policy is applicable for listing of
respective resources in all projects and helps to remove hardcoded admin
checks.

Closes-bug: #2084532
Change-Id: I43cca075bb5c5d0a5061fbd6b4064ccdfc2a23bb
This commit is contained in:
Kiran Pawar 2024-10-15 13:38:52 +00:00
parent 27f3663a46
commit 22ccfe999c
5 changed files with 80 additions and 5 deletions

View File

@ -100,6 +100,12 @@ deprecated_list_snapshots_in_deferred_deletion_states = policy.DeprecatedRule(
deprecated_reason=DEPRECATED_REASON,
deprecated_since='2024.1/Caracal'
)
deprecated_list_all_projects = policy.DeprecatedRule(
name=BASE_POLICY_NAME % 'list_all_projects',
check_str=base.RULE_ADMIN_API,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='2025.1/Epoxy'
)
share_snapshot_policies = [
policy.DocumentedRuleDefault(
@ -132,6 +138,23 @@ share_snapshot_policies = [
],
deprecated_rule=deprecated_snapshot_get_all
),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'list_all_projects',
check_str=base.ADMIN,
scope_types=['project'],
description="List share snapshots by all projects.",
operations=[
{
'method': 'GET',
'path': '/snapshots?all_tenants=1',
},
{
'method': 'GET',
'path': '/snapshots/detail?all_tenants=1',
}
],
deprecated_rule=deprecated_list_all_projects
),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'force_delete',
check_str=base.ADMIN,

View File

@ -227,6 +227,13 @@ deprecated_list_shares_in_deferred_deletion_states = policy.DeprecatedRule(
deprecated_since='2024.1/Caracal'
)
deprecated_list_all_projects = policy.DeprecatedRule(
name=BASE_POLICY_NAME % 'list_all_projects',
check_str=base.RULE_ADMIN_API,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='2025.1/Epoxy'
)
shares_policies = [
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'create',
@ -682,6 +689,23 @@ shares_policies = [
],
deprecated_rule=deprecated_list_shares_in_deferred_deletion_states
),
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME % 'list_all_projects',
check_str=base.ADMIN,
scope_types=['project'],
description="List share by all projects.",
operations=[
{
'method': 'GET',
'path': '/shares?all_tenants=1',
},
{
'method': 'GET',
'path': '/shares/detail?all_tenants=1',
}
],
deprecated_rule=deprecated_list_all_projects
),
]

View File

@ -2356,6 +2356,12 @@ class API(base.Base):
if show_deferred_deleted:
filters['list_deferred_delete'] = True
list_all_projects = False
all_tenants = utils.is_all_tenants(search_opts)
if all_tenants:
list_all_projects = policy.check_policy(
context, 'share', 'list_all_projects', do_raise=False)
# Get filtered list of shares
if 'host' in filters:
policy.check_policy(context, 'share', 'list_by_host')
@ -2365,7 +2371,7 @@ class API(base.Base):
result = get_methods['get_by_share_server'](
context, search_opts.pop('share_server_id'), filters=filters,
sort_key=sort_key, sort_dir=sort_dir)
elif context.is_admin and utils.is_all_tenants(search_opts):
elif list_all_projects:
result = get_methods['get_all'](
context, filters=filters, sort_key=sort_key, sort_dir=sort_dir)
else:
@ -2420,7 +2426,12 @@ class API(base.Base):
LOG.debug("Searching for snapshots by: %s", search_opts)
# Read and remove key 'all_tenants' if was provided
all_tenants = search_opts.pop('all_tenants', None)
list_all_projects = False
all_tenants = utils.is_all_tenants(search_opts)
if all_tenants:
search_opts.pop('all_tenants', None)
list_all_projects = policy.check_policy(
context, 'share_snapshot', 'list_all_projects', do_raise=False)
string_args = {'sort_key': sort_key, 'sort_dir': sort_dir}
string_args.update(search_opts)
@ -2448,7 +2459,7 @@ class API(base.Base):
self.db.share_snapshot_get_all_by_project_with_count
if show_count else self.db.share_snapshot_get_all_by_project)}
if context.is_admin and all_tenants:
if list_all_projects:
result = get_methods['get_all'](
context, filters=search_opts, limit=limit, offset=offset,
sort_key=sort_key, sort_dir=sort_dir)

View File

@ -264,6 +264,8 @@ class ShareAPITestCase(test.TestCase):
ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True)
self.mock_object(db_api, 'share_get_all',
mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES))
self.mock_object(share_api.policy, 'check_policy',
mock.Mock(return_value=True))
shares = self.api.get_all(ctx, {'all_tenants': 1})
@ -276,6 +278,8 @@ class ShareAPITestCase(test.TestCase):
ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True)
self.mock_object(db_api, 'share_get_all',
mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES))
self.mock_object(share_api.policy, 'check_policy',
mock.Mock(return_value=True))
shares = self.api.get_all(ctx, {'all_tenants': ''})
@ -348,6 +352,7 @@ class ShareAPITestCase(test.TestCase):
ctx, 'share',
'list_shares_in_deferred_deletion_states',
do_raise=False),
mock.call(ctx, 'share', 'list_all_projects', do_raise=False),
mock.call(ctx, 'share', 'list_by_share_server_id')])
db_api.share_get_all_by_share_server.assert_called_once_with(
@ -3050,12 +3055,17 @@ class ShareAPITestCase(test.TestCase):
@mock.patch.object(db_api, 'share_snapshot_get_all', mock.Mock())
def test_get_all_snapshots_admin_all_tenants(self):
mock_policy = self.mock_object(share_api.policy, 'check_policy',
mock.Mock(return_value=False))
mock_policy = self.mock_object(
share_api.policy, 'check_policy',
mock.Mock(side_effect=[False, True, False]))
self.api.get_all_snapshots(self.context,
search_opts={'all_tenants': 1})
mock_policy.assert_has_calls([
mock.call(self.context, 'share_snapshot', 'get_all_snapshots'),
mock.call(
self.context, 'share_snapshot',
'list_all_projects',
do_raise=False),
mock.call(
self.context, 'share_snapshot',
'list_snapshots_in_deferred_deletion_states',

View File

@ -0,0 +1,7 @@
---
upgrade:
- |
Administrator can now configure new policy `list_all_projects` for share
and share snapshot. This policy is applicable for listing of respective
resources in all projects. Please check `launchpad bug 2084532
<https://bugs.launchpad.net/manila/+bug/2084532>`_ for more details.