Update oslo policy and its dependencies
This updates to commit 95a3b40004f88c096a9943ce41907eab0d4dae7a the policy module and its dependencies: - excutils - fileutils - policy 2b966f9 Fix deletion of cached file for policy enforcer 8202a96 Merge "Make policy debug logging less verbose" 238e601 Make policy debug logging less verbose 9c88dc3 file_open: fixed docstring to refer to open() instead of file() 6c7407b fileutils: port to Python 3 fe3389e Improve help strings 33a2cee save_and_reraise_exception: make logging respect the reraise parameter 15722f1 Adds a flag to determine whether to reload the rules in policy dacc065 Merge "Update oslo log messages with translation domains" 5d1f15a Documenting policy.json syntax fcf517d Update oslo log messages with translation domains b59cfd9 Merge "Allow policy.json resource vs constant check" e038d89 Fix policy tests for parallel testing 0da5de6 Allow policy.json resource vs constant check e4b2334 Replaces use of urlutils with six in policy module e71cd1a Merge "Trivial: Make vertical white space after license header consistent" 8b2b0b7 Use hacking import_exceptions for gettextutils._ 6d0a6c3 Correct invalid docstrings 6fa29ae Trivial: Make vertical white space after license header consistent 0d8f18b Use urlutils functions instead of urllib/urllib2 12bcdb7 Remove vim header 9ef9fec Use six.string_type instead of basestring 4bfb7a2 Apply six for metaclass 1538c80 ConfigFileNotFoundError with proper argument 477bf7a Add utils for creating tempfile 33533b0 Keystone user can't perform revoke_token d602070 Merge "excutils: replace unicode by six.u" 2ad95e4 parameterize fileutils removal functions d3b6e97 excutils: replace unicode by six.u e35e166 excutils: use six.reraise to re-raise 14ba138 Merge "Fix wrong argument in openstack common policy" 64bb5e2 Fix wrong argument in openstack common policy b7edc99 Fix missing argument bug in oslo common policy 96d1f88 Merge "BaseException.message is deprecated since Python 2.6" f58c936 Merge "Fix policy default_rule issue" 3626b6d Fix policy default_rule issue df3f2ba BaseException.message is deprecated since Python 2.6 7bf8ee9 Allow use of hacking 0.6.0 and enable new checks d74ac1d Merge "Fix missing argument bug in oslo common policy" e4ac367 Fix missing argument bug in oslo common policy 1a2df89 Enable H302 hacking check 323e465 Add conditional exception reraise 22ec8ff Make AMQP based RPC consumer threads more robust 7119e29 Enable hacking H404 test. 4246ce0 Added common code into fileutils and strutils. 21ee25f Add common code for fileutils. 6d27681 Enable H306 hacking check. 1091b4f Reduce duplicated code related to policies a514693 Removes len() on empty sequence evaluation fde1e15 Convert unicode for python3 portability e700d92 Replaces standard logging with common logging 65e3d8c update OpenStack, LLC to OpenStack Foundation 547ab34 Fix Copyright Headers - Rename LLC to Foundation 9e5912f Fix pep8 E125 errors. 6d102bc Provide i18n to those messages without _() 9a8c1d7 Move nova's util.synchronized decorator to openstack common. f182936 Merge "Revert "Add support for finer-grained policy decisions"" 76751a6 Revert "Add support for finer-grained policy decisions" 8b585cb Remove an unneeded 'global' 3fc4689 Add support for finer-grained policy decisions 21b69d8 Add a 'not' operator to the policy langage fa7dc58 Add a new policy language 8c6e7a7 Remove deprecated policy engine APIs Change-Id: Iddca4243d312c9cd768588753af49dde068d5e4b Co-Authored-By: Jordan Pittier <jordan.pittier@cloudwatt.com>
This commit is contained in:
parent
e5e61bf7ce
commit
e8002b1cac
@ -24,7 +24,7 @@ import traceback
|
||||
|
||||
import six
|
||||
|
||||
from cinder.openstack.common.gettextutils import _
|
||||
from cinder.openstack.common.gettextutils import _LE
|
||||
|
||||
|
||||
class save_and_reraise_exception(object):
|
||||
@ -49,9 +49,22 @@ class save_and_reraise_exception(object):
|
||||
decide_if_need_reraise()
|
||||
if not should_be_reraised:
|
||||
ctxt.reraise = False
|
||||
|
||||
If another exception occurs and reraise flag is False,
|
||||
the saved exception will not be logged.
|
||||
|
||||
If the caller wants to raise new exception during exception handling
|
||||
he/she sets reraise to False initially with an ability to set it back to
|
||||
True if needed::
|
||||
|
||||
except Exception:
|
||||
with save_and_reraise_exception(reraise=False) as ctxt:
|
||||
[if statements to determine whether to raise a new exception]
|
||||
# Not raising a new exception, so reraise
|
||||
ctxt.reraise = True
|
||||
"""
|
||||
def __init__(self):
|
||||
self.reraise = True
|
||||
def __init__(self, reraise=True):
|
||||
self.reraise = reraise
|
||||
|
||||
def __enter__(self):
|
||||
self.type_, self.value, self.tb, = sys.exc_info()
|
||||
@ -59,7 +72,8 @@ class save_and_reraise_exception(object):
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
if exc_type is not None:
|
||||
logging.error(_('Original exception being dropped: %s'),
|
||||
if self.reraise:
|
||||
logging.error(_LE('Original exception being dropped: %s'),
|
||||
traceback.format_exception(self.type_,
|
||||
self.value,
|
||||
self.tb))
|
||||
@ -88,7 +102,7 @@ def forever_retry_uncaught_exceptions(infunc):
|
||||
if (cur_time - last_log_time > 60 or
|
||||
this_exc_message != last_exc_message):
|
||||
logging.exception(
|
||||
_('Unexpected exception occurred %d time(s)... '
|
||||
_LE('Unexpected exception occurred %d time(s)... '
|
||||
'retrying.') % exc_count)
|
||||
last_log_time = cur_time
|
||||
last_exc_message = this_exc_message
|
||||
|
@ -1,5 +1,3 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack Foundation.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
@ -15,13 +13,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import contextlib
|
||||
import errno
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from cinder.openstack.common import excutils
|
||||
from cinder.openstack.common.gettextutils import _
|
||||
from cinder.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -53,15 +50,15 @@ def read_cached_file(filename, force_reload=False):
|
||||
"""
|
||||
global _FILE_CACHE
|
||||
|
||||
if force_reload and filename in _FILE_CACHE:
|
||||
del _FILE_CACHE[filename]
|
||||
if force_reload:
|
||||
delete_cached_file(filename)
|
||||
|
||||
reloaded = False
|
||||
mtime = os.path.getmtime(filename)
|
||||
cache_info = _FILE_CACHE.setdefault(filename, {})
|
||||
|
||||
if not cache_info or mtime > cache_info.get('mtime', 0):
|
||||
LOG.debug(_("Reloading cached file %s") % filename)
|
||||
LOG.debug("Reloading cached file %s" % filename)
|
||||
with open(filename) as fap:
|
||||
cache_info['data'] = fap.read()
|
||||
cache_info['mtime'] = mtime
|
||||
@ -69,42 +66,81 @@ def read_cached_file(filename, force_reload=False):
|
||||
return (reloaded, cache_info['data'])
|
||||
|
||||
|
||||
def delete_if_exists(path):
|
||||
def delete_cached_file(filename):
|
||||
"""Delete cached file if present.
|
||||
|
||||
:param filename: filename to delete
|
||||
"""
|
||||
global _FILE_CACHE
|
||||
|
||||
if filename in _FILE_CACHE:
|
||||
del _FILE_CACHE[filename]
|
||||
|
||||
|
||||
def delete_if_exists(path, remove=os.unlink):
|
||||
"""Delete a file, but ignore file not found error.
|
||||
|
||||
:param path: File to delete
|
||||
:param remove: Optional function to remove passed path
|
||||
"""
|
||||
|
||||
try:
|
||||
os.unlink(path)
|
||||
remove(path)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
return
|
||||
else:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def remove_path_on_error(path):
|
||||
def remove_path_on_error(path, remove=delete_if_exists):
|
||||
"""Protect code that wants to operate on PATH atomically.
|
||||
Any exception will cause PATH to be removed.
|
||||
|
||||
:param path: File to work with
|
||||
:param remove: Optional function to remove passed path
|
||||
"""
|
||||
|
||||
try:
|
||||
yield
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
delete_if_exists(path)
|
||||
remove(path)
|
||||
|
||||
|
||||
def file_open(*args, **kwargs):
|
||||
"""Open file
|
||||
|
||||
see built-in file() documentation for more details
|
||||
see built-in open() documentation for more details
|
||||
|
||||
Note: The reason this is kept in a separate module is to easily
|
||||
be able to provide a stub module that doesn't alter system
|
||||
state at all (for unit tests)
|
||||
"""
|
||||
return file(*args, **kwargs)
|
||||
return open(*args, **kwargs)
|
||||
|
||||
|
||||
def write_to_tempfile(content, path=None, suffix='', prefix='tmp'):
|
||||
"""Create temporary file or use existing file.
|
||||
|
||||
This util is needed for creating temporary file with
|
||||
specified content, suffix and prefix. If path is not None,
|
||||
it will be used for writing content. If the path doesn't
|
||||
exist it'll be created.
|
||||
|
||||
:param content: content for temporary file.
|
||||
:param path: same as parameter 'dir' for mkstemp
|
||||
:param suffix: same as parameter 'suffix' for mkstemp
|
||||
:param prefix: same as parameter 'prefix' for mkstemp
|
||||
|
||||
For example: it can be used in database tests for creating
|
||||
configuration files.
|
||||
"""
|
||||
if path:
|
||||
ensure_tree(path)
|
||||
|
||||
(fd, path) = tempfile.mkstemp(suffix=suffix, dir=path, prefix=prefix)
|
||||
try:
|
||||
os.write(fd, content)
|
||||
finally:
|
||||
os.close(fd)
|
||||
return path
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,46 +19,17 @@
|
||||
from oslo.config import cfg
|
||||
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder.openstack.common import policy
|
||||
from cinder import utils
|
||||
|
||||
|
||||
policy_opts = [
|
||||
cfg.StrOpt('policy_file',
|
||||
default='policy.json',
|
||||
help=_('JSON file representing policy')),
|
||||
cfg.StrOpt('policy_default_rule',
|
||||
default='default',
|
||||
help=_('Rule checked when requested rule is not found')), ]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(policy_opts)
|
||||
|
||||
_POLICY_PATH = None
|
||||
_POLICY_CACHE = {}
|
||||
|
||||
|
||||
def reset():
|
||||
global _POLICY_PATH
|
||||
global _POLICY_CACHE
|
||||
_POLICY_PATH = None
|
||||
_POLICY_CACHE = {}
|
||||
policy.reset()
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def init():
|
||||
global _POLICY_PATH
|
||||
global _POLICY_CACHE
|
||||
if not _POLICY_PATH:
|
||||
_POLICY_PATH = utils.find_config(CONF.policy_file)
|
||||
utils.read_cached_file(_POLICY_PATH, _POLICY_CACHE,
|
||||
reload_func=_set_brain)
|
||||
|
||||
|
||||
def _set_brain(data):
|
||||
default_rule = CONF.policy_default_rule
|
||||
policy.set_brain(policy.Brain.load_json(data, default_rule))
|
||||
global _ENFORCER
|
||||
if not _ENFORCER:
|
||||
_ENFORCER = policy.Enforcer()
|
||||
|
||||
|
||||
def enforce_action(context, action):
|
||||
@ -68,11 +39,8 @@ def enforce_action(context, action):
|
||||
applied to the given action using the policy enforcement api.
|
||||
"""
|
||||
|
||||
target = {
|
||||
'project_id': context.project_id,
|
||||
'user_id': context.user_id,
|
||||
}
|
||||
enforce(context, action, target)
|
||||
return enforce(context, action, {'project_id': context.project_id,
|
||||
'user_id': context.user_id})
|
||||
|
||||
|
||||
def enforce(context, action, target):
|
||||
@ -89,16 +57,15 @@ def enforce(context, action, target):
|
||||
for object creation this should be a dictionary representing the
|
||||
location of the object e.g. ``{'project_id': context.project_id}``
|
||||
|
||||
:raises cinder.exception.PolicyNotAuthorized: if verification fails.
|
||||
:raises PolicyNotAuthorized: if verification fails.
|
||||
|
||||
"""
|
||||
init()
|
||||
|
||||
match_list = ('rule:%s' % action,)
|
||||
credentials = context.to_dict()
|
||||
|
||||
policy.enforce(match_list, target, credentials,
|
||||
exception.PolicyNotAuthorized, action=action)
|
||||
return _ENFORCER.enforce(action, target, context.to_dict(),
|
||||
do_raise=True,
|
||||
exc=exception.PolicyNotAuthorized,
|
||||
action=action)
|
||||
|
||||
|
||||
def check_is_admin(roles):
|
||||
@ -107,8 +74,6 @@ def check_is_admin(roles):
|
||||
"""
|
||||
init()
|
||||
|
||||
action = 'context_is_admin'
|
||||
match_list = ('rule:%s' % action,)
|
||||
# include project_id on target to avoid KeyError if context_is_admin
|
||||
# policy definition is missing, and default admin_or_owner rule
|
||||
# attempts to apply. Since our credentials dict does not include a
|
||||
@ -116,4 +81,4 @@ def check_is_admin(roles):
|
||||
target = {'project_id': ''}
|
||||
credentials = {'roles': roles}
|
||||
|
||||
return policy.enforce(match_list, target, credentials)
|
||||
return _ENFORCER.enforce('context_is_admin', target, credentials)
|
||||
|
@ -187,6 +187,15 @@ class TestCase(testtools.TestCase):
|
||||
CONF.set_override('fatal_exception_format_errors', True)
|
||||
# This will be cleaned up by the NestedTempfile fixture
|
||||
CONF.set_override('lock_path', tempfile.mkdtemp())
|
||||
CONF.set_override('policy_file',
|
||||
os.path.join(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'..',
|
||||
)
|
||||
),
|
||||
'cinder/tests/policy.json'))
|
||||
|
||||
def _common_cleanup(self):
|
||||
"""Runs after each test method to tear down test environment."""
|
||||
|
@ -1,92 +1,92 @@
|
||||
{
|
||||
"context_is_admin": [["role:admin"]],
|
||||
"admin_api": [["is_admin:True"]],
|
||||
"admin_or_owner": [["is_admin:True"], ["project_id:%(project_id)s"]],
|
||||
"context_is_admin": "role:admin",
|
||||
"admin_api": "is_admin:True",
|
||||
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
|
||||
|
||||
"volume:create": [],
|
||||
"volume:get": [["rule:admin_or_owner"]],
|
||||
"volume:get_all": [],
|
||||
"volume:get_volume_metadata": [],
|
||||
"volume:delete_volume_metadata": [],
|
||||
"volume:update_volume_metadata": [],
|
||||
"volume:get_volume_admin_metadata": [["rule:admin_api"]],
|
||||
"volume:delete_volume_admin_metadata": [["rule:admin_api"]],
|
||||
"volume:update_volume_admin_metadata": [["rule:admin_api"]],
|
||||
"volume:delete": [],
|
||||
"volume:update": [],
|
||||
"volume:attach": [],
|
||||
"volume:detach": [],
|
||||
"volume:reserve_volume": [],
|
||||
"volume:unreserve_volume": [],
|
||||
"volume:begin_detaching": [],
|
||||
"volume:roll_detaching": [],
|
||||
"volume:initialize_connection": [],
|
||||
"volume:terminate_connection": [],
|
||||
"volume:create_snapshot": [],
|
||||
"volume:delete_snapshot": [],
|
||||
"volume:get_snapshot": [],
|
||||
"volume:get_all_snapshots": [],
|
||||
"volume:update_snapshot": [],
|
||||
"volume:extend": [],
|
||||
"volume:migrate_volume": [["rule:admin_api"]],
|
||||
"volume:migrate_volume_completion": [["rule:admin_api"]],
|
||||
"volume:update_readonly_flag": [],
|
||||
"volume:retype": [],
|
||||
"volume:copy_volume_to_image": [],
|
||||
"volume:create": "",
|
||||
"volume:get": "rule:admin_or_owner",
|
||||
"volume:get_all": "",
|
||||
"volume:get_volume_metadata": "",
|
||||
"volume:delete_volume_metadata": "",
|
||||
"volume:update_volume_metadata": "",
|
||||
"volume:get_volume_admin_metadata": "rule:admin_api",
|
||||
"volume:delete_volume_admin_metadata": "rule:admin_api",
|
||||
"volume:update_volume_admin_metadata": "rule:admin_api",
|
||||
"volume:delete": "",
|
||||
"volume:update": "",
|
||||
"volume:attach": "",
|
||||
"volume:detach": "",
|
||||
"volume:reserve_volume": "",
|
||||
"volume:unreserve_volume": "",
|
||||
"volume:begin_detaching": "",
|
||||
"volume:roll_detaching": "",
|
||||
"volume:initialize_connection": "",
|
||||
"volume:terminate_connection": "",
|
||||
"volume:create_snapshot": "",
|
||||
"volume:delete_snapshot": "",
|
||||
"volume:get_snapshot": "",
|
||||
"volume:get_all_snapshots": "",
|
||||
"volume:update_snapshot": "",
|
||||
"volume:extend": "",
|
||||
"volume:migrate_volume": "rule:admin_api",
|
||||
"volume:migrate_volume_completion": "rule:admin_api",
|
||||
"volume:update_readonly_flag": "",
|
||||
"volume:retype": "",
|
||||
"volume:copy_volume_to_image": "",
|
||||
|
||||
"volume_extension:volume_admin_actions:reset_status": [["rule:admin_api"]],
|
||||
"volume_extension:snapshot_admin_actions:reset_status": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:force_delete": [["rule:admin_api"]],
|
||||
"volume_extension:snapshot_admin_actions:force_delete": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:force_detach": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:migrate_volume": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:migrate_volume_completion": [["rule:admin_api"]],
|
||||
"volume_extension:volume_actions:upload_image": [],
|
||||
"volume_extension:types_manage": [],
|
||||
"volume_extension:types_extra_specs": [],
|
||||
"volume_extension:volume_type_encryption": [["rule:admin_api"]],
|
||||
"volume_extension:volume_encryption_metadata": [["rule:admin_or_owner"]],
|
||||
"volume_extension:qos_specs_manage": [],
|
||||
"volume_extension:extended_snapshot_attributes": [],
|
||||
"volume_extension:volume_image_metadata": [],
|
||||
"volume_extension:volume_host_attribute": [["rule:admin_api"]],
|
||||
"volume_extension:volume_tenant_attribute": [["rule:admin_api"]],
|
||||
"volume_extension:volume_mig_status_attribute": [["rule:admin_api"]],
|
||||
"volume_extension:hosts": [["rule:admin_api"]],
|
||||
"volume_extension:quotas:show": [],
|
||||
"volume_extension:quotas:update": [],
|
||||
"volume_extension:quotas:delete": [],
|
||||
"volume_extension:quota_classes": [],
|
||||
"volume_extension:volume_manage": [["rule:admin_api"]],
|
||||
"volume_extension:volume_unmanage": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:reset_status": "rule:admin_api",
|
||||
"volume_extension:snapshot_admin_actions:reset_status": "rule:admin_api",
|
||||
"volume_extension:volume_admin_actions:force_delete": "rule:admin_api",
|
||||
"volume_extension:snapshot_admin_actions:force_delete": "rule:admin_api",
|
||||
"volume_extension:volume_admin_actions:force_detach": "rule:admin_api",
|
||||
"volume_extension:volume_admin_actions:migrate_volume": "rule:admin_api",
|
||||
"volume_extension:volume_admin_actions:migrate_volume_completion": "rule:admin_api",
|
||||
"volume_extension:volume_actions:upload_image": "",
|
||||
"volume_extension:types_manage": "",
|
||||
"volume_extension:types_extra_specs": "",
|
||||
"volume_extension:volume_type_encryption": "rule:admin_api",
|
||||
"volume_extension:volume_encryption_metadata": "rule:admin_or_owner",
|
||||
"volume_extension:qos_specs_manage": "",
|
||||
"volume_extension:extended_snapshot_attributes": "",
|
||||
"volume_extension:volume_image_metadata": "",
|
||||
"volume_extension:volume_host_attribute": "rule:admin_api",
|
||||
"volume_extension:volume_tenant_attribute": "rule:admin_api",
|
||||
"volume_extension:volume_mig_status_attribute": "rule:admin_api",
|
||||
"volume_extension:hosts": "rule:admin_api",
|
||||
"volume_extension:quotas:show": "",
|
||||
"volume_extension:quotas:update": "",
|
||||
"volume_extension:quotas:delete": "",
|
||||
"volume_extension:quota_classes": "",
|
||||
"volume_extension:volume_manage": "rule:admin_api",
|
||||
"volume_extension:volume_unmanage": "rule:admin_api",
|
||||
|
||||
"limits_extension:used_limits": [],
|
||||
"limits_extension:used_limits": "",
|
||||
|
||||
"snapshot_extension:snapshot_actions:update_snapshot_status": [],
|
||||
"snapshot_extension:snapshot_actions:update_snapshot_status": "",
|
||||
|
||||
"volume:create_transfer": [],
|
||||
"volume:accept_transfer": [],
|
||||
"volume:delete_transfer": [],
|
||||
"volume:get_all_transfers": [],
|
||||
"volume:create_transfer": "",
|
||||
"volume:accept_transfer": "",
|
||||
"volume:delete_transfer": "",
|
||||
"volume:get_all_transfers": "",
|
||||
|
||||
"backup:create" : [],
|
||||
"backup:delete": [],
|
||||
"backup:get": [],
|
||||
"backup:get_all": [],
|
||||
"backup:restore": [],
|
||||
"backup:backup-import": [["rule:admin_api"]],
|
||||
"backup:backup-export": [["rule:admin_api"]],
|
||||
"backup:create" : "",
|
||||
"backup:delete": "",
|
||||
"backup:get": "",
|
||||
"backup:get_all": "",
|
||||
"backup:restore": "",
|
||||
"backup:backup-import": "rule:admin_api",
|
||||
"backup:backup-export": "rule:admin_api",
|
||||
|
||||
"volume_extension:replication:promote": [["rule:admin_api"]],
|
||||
"volume_extension:replication:reenable": [["rule:admin_api"]],
|
||||
"volume_extension:replication:promote": "rule:admin_api",
|
||||
"volume_extension:replication:reenable": "rule:admin_api",
|
||||
|
||||
"consistencygroup:create" : [],
|
||||
"consistencygroup:delete": [],
|
||||
"consistencygroup:get": [],
|
||||
"consistencygroup:get_all": [],
|
||||
"consistencygroup:create" : "",
|
||||
"consistencygroup:delete": "",
|
||||
"consistencygroup:get": "",
|
||||
"consistencygroup:get_all": "",
|
||||
|
||||
"consistencygroup:create_cgsnapshot" : [],
|
||||
"consistencygroup:delete_cgsnapshot": [],
|
||||
"consistencygroup:get_cgsnapshot": [],
|
||||
"consistencygroup:get_all_cgsnapshots": []
|
||||
"consistencygroup:create_cgsnapshot" : "",
|
||||
"consistencygroup:delete_cgsnapshot": "",
|
||||
"consistencygroup:get_cgsnapshot": "",
|
||||
"consistencygroup:get_all_cgsnapshots": ""
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ from oslo.config import cfg
|
||||
from cinder import context
|
||||
from cinder import exception
|
||||
from cinder.image import image_utils
|
||||
from cinder.openstack.common import fileutils
|
||||
from cinder.openstack.common import processutils
|
||||
from cinder.openstack.common import units
|
||||
from cinder import test
|
||||
@ -621,10 +622,10 @@ class TestTemporaryFile(test.TestCase):
|
||||
def test_file_unlinked(self):
|
||||
mox = self.mox
|
||||
mox.StubOutWithMock(image_utils, 'create_temporary_file')
|
||||
mox.StubOutWithMock(image_utils.os, 'unlink')
|
||||
mox.StubOutWithMock(fileutils, 'delete_if_exists')
|
||||
|
||||
image_utils.create_temporary_file().AndReturn('somefile')
|
||||
image_utils.os.unlink('somefile')
|
||||
fileutils.delete_if_exists('somefile')
|
||||
|
||||
mox.ReplayAll()
|
||||
|
||||
@ -634,10 +635,10 @@ class TestTemporaryFile(test.TestCase):
|
||||
def test_file_unlinked_on_error(self):
|
||||
mox = self.mox
|
||||
mox.StubOutWithMock(image_utils, 'create_temporary_file')
|
||||
mox.StubOutWithMock(image_utils.os, 'unlink')
|
||||
mox.StubOutWithMock(fileutils, 'delete_if_exists')
|
||||
|
||||
image_utils.create_temporary_file().AndReturn('somefile')
|
||||
image_utils.os.unlink('somefile')
|
||||
fileutils.delete_if_exists('somefile')
|
||||
|
||||
mox.ReplayAll()
|
||||
|
||||
@ -706,6 +707,7 @@ class TestXenServerImageToCoalescedVhd(test.TestCase):
|
||||
mox.StubOutWithMock(image_utils, 'fix_vhd_chain')
|
||||
mox.StubOutWithMock(image_utils, 'coalesce_chain')
|
||||
mox.StubOutWithMock(image_utils.os, 'unlink')
|
||||
mox.StubOutWithMock(fileutils, 'delete_if_exists')
|
||||
mox.StubOutWithMock(image_utils, 'rename_file')
|
||||
|
||||
image_utils.temporary_dir().AndReturn(fake_context('somedir'))
|
||||
@ -715,7 +717,7 @@ class TestXenServerImageToCoalescedVhd(test.TestCase):
|
||||
image_utils.fix_vhd_chain(['somedir/0.vhd', 'somedir/1.vhd'])
|
||||
image_utils.coalesce_chain(
|
||||
['somedir/0.vhd', 'somedir/1.vhd']).AndReturn('somedir/1.vhd')
|
||||
image_utils.os.unlink('image')
|
||||
fileutils.delete_if_exists('image')
|
||||
image_utils.rename_file('somedir/1.vhd', 'image')
|
||||
|
||||
mox.ReplayAll()
|
||||
|
@ -1,225 +0,0 @@
|
||||
|
||||
# Copyright 2011 Piston Cloud Computing, Inc.
|
||||
# All Rights Reserved.
|
||||
|
||||
# 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.
|
||||
|
||||
"""Test of Policy Engine For Cinder."""
|
||||
|
||||
import os.path
|
||||
import urllib2
|
||||
|
||||
from oslo.config import cfg
|
||||
import six
|
||||
|
||||
from cinder import context
|
||||
from cinder import exception
|
||||
import cinder.openstack.common.policy
|
||||
from cinder.openstack.common import policy as common_policy
|
||||
from cinder import policy
|
||||
from cinder import test
|
||||
from cinder import utils
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class PolicyFileTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(PolicyFileTestCase, self).setUp()
|
||||
# since is_admin is defined by policy, create context before reset
|
||||
self.context = context.RequestContext('fake', 'fake')
|
||||
policy.reset()
|
||||
self.target = {}
|
||||
self.addCleanup(policy.reset)
|
||||
|
||||
def test_modified_policy_reloads(self):
|
||||
with utils.tempdir() as tmpdir:
|
||||
tmpfilename = os.path.join(tmpdir, 'policy')
|
||||
self.flags(policy_file=tmpfilename)
|
||||
|
||||
action = "example:test"
|
||||
with open(tmpfilename, "w") as policyfile:
|
||||
policyfile.write("""{"example:test": []}""")
|
||||
policy.enforce(self.context, action, self.target)
|
||||
with open(tmpfilename, "w") as policyfile:
|
||||
policyfile.write("""{"example:test": ["false:false"]}""")
|
||||
# NOTE(vish): reset stored policy cache so we don't have to
|
||||
# sleep(1)
|
||||
policy._POLICY_CACHE = {}
|
||||
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
|
||||
self.context, action, self.target)
|
||||
|
||||
|
||||
class PolicyTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(PolicyTestCase, self).setUp()
|
||||
policy.reset()
|
||||
# NOTE(vish): preload rules to circumvent reloading from file
|
||||
policy.init()
|
||||
rules = {
|
||||
"true": [],
|
||||
"example:allowed": [],
|
||||
"example:denied": [["false:false"]],
|
||||
"example:get_http": [["http:http://www.example.com"]],
|
||||
"example:my_file": [["role:compute_admin"],
|
||||
["project_id:%(project_id)s"]],
|
||||
"example:early_and_fail": [["false:false", "rule:true"]],
|
||||
"example:early_or_success": [["rule:true"], ["false:false"]],
|
||||
"example:lowercase_admin": [["role:admin"], ["role:sysadmin"]],
|
||||
"example:uppercase_admin": [["role:ADMIN"], ["role:sysadmin"]],
|
||||
}
|
||||
# NOTE(vish): then overload underlying brain
|
||||
common_policy.set_brain(common_policy.Brain(rules))
|
||||
self.context = context.RequestContext('fake', 'fake', roles=['member'])
|
||||
self.target = {}
|
||||
self.addCleanup(policy.reset)
|
||||
|
||||
def test_enforce_nonexistent_action_throws(self):
|
||||
action = "example:noexist"
|
||||
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
|
||||
self.context, action, self.target)
|
||||
|
||||
def test_enforce_bad_action_throws(self):
|
||||
action = "example:denied"
|
||||
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
|
||||
self.context, action, self.target)
|
||||
|
||||
def test_enforce_good_action(self):
|
||||
action = "example:allowed"
|
||||
policy.enforce(self.context, action, self.target)
|
||||
|
||||
def test_enforce_http_true(self):
|
||||
|
||||
def fakeurlopen(url, post_data):
|
||||
return six.StringIO("True")
|
||||
self.stubs.Set(urllib2, 'urlopen', fakeurlopen)
|
||||
action = "example:get_http"
|
||||
target = {}
|
||||
result = policy.enforce(self.context, action, target)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_enforce_http_false(self):
|
||||
|
||||
def fakeurlopen(url, post_data):
|
||||
return six.StringIO("False")
|
||||
self.stubs.Set(urllib2, 'urlopen', fakeurlopen)
|
||||
action = "example:get_http"
|
||||
target = {}
|
||||
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
|
||||
self.context, action, target)
|
||||
|
||||
def test_templatized_enforcement(self):
|
||||
target_mine = {'project_id': 'fake'}
|
||||
target_not_mine = {'project_id': 'another'}
|
||||
action = "example:my_file"
|
||||
policy.enforce(self.context, action, target_mine)
|
||||
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
|
||||
self.context, action, target_not_mine)
|
||||
|
||||
def test_early_AND_enforcement(self):
|
||||
action = "example:early_and_fail"
|
||||
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
|
||||
self.context, action, self.target)
|
||||
|
||||
def test_early_OR_enforcement(self):
|
||||
action = "example:early_or_success"
|
||||
policy.enforce(self.context, action, self.target)
|
||||
|
||||
def test_ignore_case_role_check(self):
|
||||
lowercase_action = "example:lowercase_admin"
|
||||
uppercase_action = "example:uppercase_admin"
|
||||
# NOTE(dprince) we mix case in the Admin role here to ensure
|
||||
# case is ignored
|
||||
admin_context = context.RequestContext('admin',
|
||||
'fake',
|
||||
roles=['AdMiN'])
|
||||
policy.enforce(admin_context, lowercase_action, self.target)
|
||||
policy.enforce(admin_context, uppercase_action, self.target)
|
||||
|
||||
|
||||
class DefaultPolicyTestCase(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(DefaultPolicyTestCase, self).setUp()
|
||||
policy.reset()
|
||||
policy.init()
|
||||
|
||||
self.rules = {
|
||||
"default": [],
|
||||
"example:exist": [["false:false"]]
|
||||
}
|
||||
|
||||
self._set_brain('default')
|
||||
|
||||
self.context = context.RequestContext('fake', 'fake')
|
||||
|
||||
self.addCleanup(policy.reset)
|
||||
|
||||
def _set_brain(self, default_rule):
|
||||
brain = cinder.openstack.common.policy.Brain(self.rules,
|
||||
default_rule)
|
||||
cinder.openstack.common.policy.set_brain(brain)
|
||||
|
||||
def test_policy_called(self):
|
||||
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
|
||||
self.context, "example:exist", {})
|
||||
|
||||
def test_not_found_policy_calls_default(self):
|
||||
policy.enforce(self.context, "example:noexist", {})
|
||||
|
||||
def test_default_not_found(self):
|
||||
self._set_brain("default_noexist")
|
||||
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
|
||||
self.context, "example:noexist", {})
|
||||
|
||||
|
||||
class ContextIsAdminPolicyTestCase(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ContextIsAdminPolicyTestCase, self).setUp()
|
||||
policy.reset()
|
||||
policy.init()
|
||||
|
||||
def test_default_admin_role_is_admin(self):
|
||||
ctx = context.RequestContext('fake', 'fake', roles=['johnny-admin'])
|
||||
self.assertFalse(ctx.is_admin)
|
||||
ctx = context.RequestContext('fake', 'fake', roles=['admin'])
|
||||
self.assertTrue(ctx.is_admin)
|
||||
|
||||
def test_custom_admin_role_is_admin(self):
|
||||
# define explicit rules for context_is_admin
|
||||
rules = {
|
||||
'context_is_admin': [["role:administrator"], ["role:johnny-admin"]]
|
||||
}
|
||||
brain = common_policy.Brain(rules, CONF.policy_default_rule)
|
||||
common_policy.set_brain(brain)
|
||||
ctx = context.RequestContext('fake', 'fake', roles=['johnny-admin'])
|
||||
self.assertTrue(ctx.is_admin)
|
||||
ctx = context.RequestContext('fake', 'fake', roles=['administrator'])
|
||||
self.assertTrue(ctx.is_admin)
|
||||
# default rule no longer applies
|
||||
ctx = context.RequestContext('fake', 'fake', roles=['admin'])
|
||||
self.assertFalse(ctx.is_admin)
|
||||
|
||||
def test_context_is_admin_undefined(self):
|
||||
rules = {
|
||||
"admin_or_owner": [["role:admin"], ["project_id:%(project_id)s"]],
|
||||
"default": [["rule:admin_or_owner"]],
|
||||
}
|
||||
brain = common_policy.Brain(rules, CONF.policy_default_rule)
|
||||
common_policy.set_brain(brain)
|
||||
ctx = context.RequestContext('fake', 'fake')
|
||||
self.assertFalse(ctx.is_admin)
|
||||
ctx = context.RequestContext('fake', 'fake', roles=['admin'])
|
||||
self.assertTrue(ctx.is_admin)
|
@ -367,31 +367,6 @@ class GenericUtilsTestCase(test.TestCase):
|
||||
CONF.glance_port)
|
||||
self.assertEqual(generated_url, actual_url)
|
||||
|
||||
@mock.patch('__builtin__.open')
|
||||
@mock.patch('os.path.getmtime', return_value=1)
|
||||
def test_read_cached_file(self, mock_mtime, mock_open):
|
||||
fake_file = "/this/is/a/fake"
|
||||
cache_data = {"data": 1123, "mtime": 2}
|
||||
mock_open.return_value = _get_local_mock_open()
|
||||
data = utils.read_cached_file(fake_file, cache_data)
|
||||
self.assertEqual(cache_data["data"], data)
|
||||
mock_open.assert_called_once_with(fake_file)
|
||||
|
||||
@mock.patch('__builtin__.open')
|
||||
@mock.patch('os.path.getmtime', return_value=1)
|
||||
def test_read_modified_cached_file(self, mock_mtime, mock_open):
|
||||
fake_data = 'lorem ipsum'
|
||||
fake_file = "/this/is/a/fake"
|
||||
mock_open.return_value = _get_local_mock_open(fake_data)
|
||||
cache_data = {"data": 'original data', "mtime": 2}
|
||||
mock_reload = mock.Mock()
|
||||
data = utils.read_cached_file(fake_file,
|
||||
cache_data,
|
||||
reload_func=mock_reload)
|
||||
self.assertEqual(data, fake_data)
|
||||
mock_reload.assert_called_once_with(fake_data)
|
||||
mock_open.assert_called_once_with(fake_file)
|
||||
|
||||
def test_read_file_as_root(self):
|
||||
def fake_execute(*args, **kwargs):
|
||||
if args[1] == 'bad':
|
||||
|
@ -3920,15 +3920,10 @@ class VolumePolicyTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(VolumePolicyTestCase, self).setUp()
|
||||
|
||||
cinder.policy.reset()
|
||||
cinder.policy.init()
|
||||
|
||||
self.context = context.get_admin_context()
|
||||
self.stubs.Set(brick_lvm.LVM, '_vg_exists', lambda x: True)
|
||||
self.addCleanup(cinder.policy.reset)
|
||||
|
||||
def _set_rules(self, rules):
|
||||
cinder.common.policy.set_brain(cinder.common.policy.Brain(rules))
|
||||
|
||||
def test_check_policy(self):
|
||||
self.mox.StubOutWithMock(cinder.policy, 'enforce')
|
||||
|
@ -284,7 +284,6 @@ class TestWindowsDriver(test.TestCase):
|
||||
mox.IgnoreArg())
|
||||
windows_utils.WindowsUtils.change_disk_status(volume['name'],
|
||||
mox.IsA(bool))
|
||||
os.unlink(mox.IsA(str))
|
||||
vhdutils.VHDUtils.convert_vhd(fake_temp_path,
|
||||
fake_volume_path,
|
||||
constants.VHD_TYPE_FIXED)
|
||||
|
@ -493,26 +493,6 @@ def sanitize_hostname(hostname):
|
||||
return hostname
|
||||
|
||||
|
||||
def read_cached_file(filename, cache_info, reload_func=None):
|
||||
"""Read from a file if it has been modified.
|
||||
|
||||
:param cache_info: dictionary to hold opaque cache.
|
||||
:param reload_func: optional function to be called with data when
|
||||
file is reloaded due to a modification.
|
||||
|
||||
:returns: data from file
|
||||
|
||||
"""
|
||||
mtime = os.path.getmtime(filename)
|
||||
if not cache_info or mtime != cache_info.get('mtime'):
|
||||
with open(filename) as fap:
|
||||
cache_info['data'] = fap.read()
|
||||
cache_info['mtime'] = mtime
|
||||
if reload_func:
|
||||
reload_func(cache_info['data'])
|
||||
return cache_info['data']
|
||||
|
||||
|
||||
def hash_file(file_like_object):
|
||||
"""Generate a hash for the contents of a file."""
|
||||
checksum = hashlib.sha1()
|
||||
|
@ -202,17 +202,6 @@
|
||||
#fatal_exception_format_errors=false
|
||||
|
||||
|
||||
#
|
||||
# Options defined in cinder.policy
|
||||
#
|
||||
|
||||
# JSON file representing policy (string value)
|
||||
#policy_file=policy.json
|
||||
|
||||
# Rule checked when requested rule is not found (string value)
|
||||
#policy_default_rule=default
|
||||
|
||||
|
||||
#
|
||||
# Options defined in cinder.quota
|
||||
#
|
||||
@ -855,6 +844,18 @@
|
||||
#run_external_periodic_tasks=true
|
||||
|
||||
|
||||
#
|
||||
# Options defined in cinder.openstack.common.policy
|
||||
#
|
||||
|
||||
# The JSON file that defines policies. (string value)
|
||||
#policy_file=policy.json
|
||||
|
||||
# Default rule. Enforced when a requested rule is not found.
|
||||
# (string value)
|
||||
#policy_default_rule=default
|
||||
|
||||
|
||||
#
|
||||
# Options defined in cinder.scheduler.driver
|
||||
#
|
||||
|
@ -1,77 +1,77 @@
|
||||
{
|
||||
"context_is_admin": [["role:admin"]],
|
||||
"admin_or_owner": [["is_admin:True"], ["project_id:%(project_id)s"]],
|
||||
"default": [["rule:admin_or_owner"]],
|
||||
"context_is_admin": "role:admin",
|
||||
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
|
||||
"default": "rule:admin_or_owner",
|
||||
|
||||
"admin_api": [["is_admin:True"]],
|
||||
"admin_api": "is_admin:True",
|
||||
|
||||
"volume:create": [],
|
||||
"volume:get_all": [],
|
||||
"volume:get_volume_metadata": [],
|
||||
"volume:get_volume_admin_metadata": [["rule:admin_api"]],
|
||||
"volume:delete_volume_admin_metadata": [["rule:admin_api"]],
|
||||
"volume:update_volume_admin_metadata": [["rule:admin_api"]],
|
||||
"volume:get_snapshot": [],
|
||||
"volume:get_all_snapshots": [],
|
||||
"volume:extend": [],
|
||||
"volume:update_readonly_flag": [],
|
||||
"volume:retype": [],
|
||||
"volume:create": "",
|
||||
"volume:get_all": "",
|
||||
"volume:get_volume_metadata": "",
|
||||
"volume:get_volume_admin_metadata": "rule:admin_api",
|
||||
"volume:delete_volume_admin_metadata": "rule:admin_api",
|
||||
"volume:update_volume_admin_metadata": "rule:admin_api",
|
||||
"volume:get_snapshot": "",
|
||||
"volume:get_all_snapshots": "",
|
||||
"volume:extend": "",
|
||||
"volume:update_readonly_flag": "",
|
||||
"volume:retype": "",
|
||||
|
||||
"volume_extension:types_manage": [["rule:admin_api"]],
|
||||
"volume_extension:types_extra_specs": [["rule:admin_api"]],
|
||||
"volume_extension:volume_type_encryption": [["rule:admin_api"]],
|
||||
"volume_extension:volume_encryption_metadata": [["rule:admin_or_owner"]],
|
||||
"volume_extension:extended_snapshot_attributes": [],
|
||||
"volume_extension:volume_image_metadata": [],
|
||||
"volume_extension:types_manage": "rule:admin_api",
|
||||
"volume_extension:types_extra_specs": "rule:admin_api",
|
||||
"volume_extension:volume_type_encryption": "rule:admin_api",
|
||||
"volume_extension:volume_encryption_metadata": "rule:admin_or_owner",
|
||||
"volume_extension:extended_snapshot_attributes": "",
|
||||
"volume_extension:volume_image_metadata": "",
|
||||
|
||||
"volume_extension:quotas:show": [],
|
||||
"volume_extension:quotas:update": [["rule:admin_api"]],
|
||||
"volume_extension:quota_classes": [],
|
||||
"volume_extension:quotas:show": "",
|
||||
"volume_extension:quotas:update": "rule:admin_api",
|
||||
"volume_extension:quota_classes": "",
|
||||
|
||||
"volume_extension:volume_admin_actions:reset_status": [["rule:admin_api"]],
|
||||
"volume_extension:snapshot_admin_actions:reset_status": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:force_delete": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:force_detach": [["rule:admin_api"]],
|
||||
"volume_extension:snapshot_admin_actions:force_delete": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:migrate_volume": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:migrate_volume_completion": [["rule:admin_api"]],
|
||||
"volume_extension:volume_admin_actions:reset_status": "rule:admin_api",
|
||||
"volume_extension:snapshot_admin_actions:reset_status": "rule:admin_api",
|
||||
"volume_extension:volume_admin_actions:force_delete": "rule:admin_api",
|
||||
"volume_extension:volume_admin_actions:force_detach": "rule:admin_api",
|
||||
"volume_extension:snapshot_admin_actions:force_delete": "rule:admin_api",
|
||||
"volume_extension:volume_admin_actions:migrate_volume": "rule:admin_api",
|
||||
"volume_extension:volume_admin_actions:migrate_volume_completion": "rule:admin_api",
|
||||
|
||||
"volume_extension:volume_host_attribute": [["rule:admin_api"]],
|
||||
"volume_extension:volume_tenant_attribute": [["rule:admin_or_owner"]],
|
||||
"volume_extension:volume_mig_status_attribute": [["rule:admin_api"]],
|
||||
"volume_extension:hosts": [["rule:admin_api"]],
|
||||
"volume_extension:services": [["rule:admin_api"]],
|
||||
"volume_extension:volume_host_attribute": "rule:admin_api",
|
||||
"volume_extension:volume_tenant_attribute": "rule:admin_or_owner",
|
||||
"volume_extension:volume_mig_status_attribute": "rule:admin_api",
|
||||
"volume_extension:hosts": "rule:admin_api",
|
||||
"volume_extension:services": "rule:admin_api",
|
||||
|
||||
"volume_extension:volume_manage": [["rule:admin_api"]],
|
||||
"volume_extension:volume_unmanage": [["rule:admin_api"]],
|
||||
"volume_extension:volume_manage": "rule:admin_api",
|
||||
"volume_extension:volume_unmanage": "rule:admin_api",
|
||||
|
||||
"volume:services": [["rule:admin_api"]],
|
||||
"volume:services": "rule:admin_api",
|
||||
|
||||
"volume:create_transfer": [],
|
||||
"volume:accept_transfer": [],
|
||||
"volume:delete_transfer": [],
|
||||
"volume:get_all_transfers": [],
|
||||
"volume:create_transfer": "",
|
||||
"volume:accept_transfer": "",
|
||||
"volume:delete_transfer": "",
|
||||
"volume:get_all_transfers": "",
|
||||
|
||||
"volume_extension:replication:promote": ["rule:admin_api"],
|
||||
"volume_extension:replication:reenable": ["rule:admin_api"],
|
||||
"volume_extension:replication:promote": "rule:admin_api",
|
||||
"volume_extension:replication:reenable": "rule:admin_api",
|
||||
|
||||
"backup:create" : [],
|
||||
"backup:delete": [],
|
||||
"backup:get": [],
|
||||
"backup:get_all": [],
|
||||
"backup:restore": [],
|
||||
"backup:backup-import": [["rule:admin_api"]],
|
||||
"backup:backup-export": [["rule:admin_api"]],
|
||||
"backup:create" : "",
|
||||
"backup:delete": "",
|
||||
"backup:get": "",
|
||||
"backup:get_all": "",
|
||||
"backup:restore": "",
|
||||
"backup:backup-import": "rule:admin_api",
|
||||
"backup:backup-export": "rule:admin_api",
|
||||
|
||||
"snapshot_extension:snapshot_actions:update_snapshot_status": [],
|
||||
"snapshot_extension:snapshot_actions:update_snapshot_status": "",
|
||||
|
||||
"consistencygroup:create" : [["group:nobody"]],
|
||||
"consistencygroup:delete": [["group:nobody"]],
|
||||
"consistencygroup:get": [["group:nobody"]],
|
||||
"consistencygroup:get_all": [["group:nobody"]],
|
||||
"consistencygroup:create" : "group:nobody",
|
||||
"consistencygroup:delete": "group:nobody",
|
||||
"consistencygroup:get": "group:nobody",
|
||||
"consistencygroup:get_all": "group:nobody",
|
||||
|
||||
"consistencygroup:create_cgsnapshot" : [],
|
||||
"consistencygroup:delete_cgsnapshot": [],
|
||||
"consistencygroup:get_cgsnapshot": [],
|
||||
"consistencygroup:get_all_cgsnapshots": []
|
||||
"consistencygroup:create_cgsnapshot" : "",
|
||||
"consistencygroup:delete_cgsnapshot": "",
|
||||
"consistencygroup:get_cgsnapshot": "",
|
||||
"consistencygroup:get_all_cgsnapshots": ""
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user