Merge "Revert "Add JSON driver for access rules config""
This commit is contained in:
commit
8f1e4cf348
|
@ -1,31 +0,0 @@
|
|||
# Copyright 2019 SUSE Linux GmbH
|
||||
#
|
||||
# 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 abc
|
||||
|
||||
import six
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class AccessRulesConfigDriverBase(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
def list_access_rules_config(self, service=None):
|
||||
"""List access rules config."""
|
||||
raise NotImplementedError() # pragma: no cover
|
||||
|
||||
@abc.abstractmethod
|
||||
def check_access_rule(self, service, request_path, request_method):
|
||||
"""Check if an access rule exists in config."""
|
||||
raise NotImplementedError() # pragma: no cover
|
|
@ -1,160 +0,0 @@
|
|||
# Copyright 2019 SUSE Linux GmbH
|
||||
#
|
||||
# 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 re
|
||||
|
||||
from oslo_log import log
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from keystone.access_rules_config.backends import base
|
||||
import keystone.conf
|
||||
from keystone import exception
|
||||
|
||||
CONF = keystone.conf.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class AccessRulesConfig(base.AccessRulesConfigDriverBase):
|
||||
"""This backend reads the access rules from a JSON file on disk.
|
||||
|
||||
The format of the file is a mapping from service type to rules for that
|
||||
service type. For example::
|
||||
|
||||
{
|
||||
"identity": [
|
||||
{
|
||||
"path": "/v3/users",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*",
|
||||
"method": "DELETE"
|
||||
}
|
||||
...
|
||||
],
|
||||
"image": [
|
||||
{
|
||||
"path": "/v2/images",
|
||||
"method": "GET"
|
||||
},
|
||||
...
|
||||
],
|
||||
...
|
||||
}
|
||||
|
||||
This will be transmuted in memory to a hash map that looks like this::
|
||||
|
||||
{
|
||||
"identity": {
|
||||
"GET": [
|
||||
{
|
||||
"path": "/v3/users"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*"
|
||||
}
|
||||
...
|
||||
],
|
||||
"POST": [ ... ]
|
||||
},
|
||||
...
|
||||
}
|
||||
|
||||
The path may include a wildcard like '*' or '**' or a named wildcard like
|
||||
{server_id}. An application credential access rule validation request for
|
||||
a path like "/v3/users/uuid" will match with a configured access rule like
|
||||
"/v3/users/*" or "/v3/users/{user_id}", and a request for a path like
|
||||
"/v3/users/uuid/application_credentials/uuid" will match with a configured
|
||||
access rule like "/v3/users/**".
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(AccessRulesConfig, self).__init__()
|
||||
access_rules_file = CONF.access_rules_config.rules_file
|
||||
self.access_rules = dict()
|
||||
self.access_rules_json = dict()
|
||||
try:
|
||||
with open(access_rules_file, "rb") as f:
|
||||
self.access_rules_json = jsonutils.load(f)
|
||||
except IOError:
|
||||
LOG.warning('No config file found for access rules, application'
|
||||
' credential access rules will be unavailable.')
|
||||
return
|
||||
except ValueError as e:
|
||||
raise exception.AccessRulesConfigFileError(error=e)
|
||||
|
||||
for service, rules in self.access_rules_json.items():
|
||||
self.access_rules[service] = dict()
|
||||
for rule in rules:
|
||||
try:
|
||||
self.access_rules[service].setdefault(
|
||||
rule['method'], []).append({
|
||||
'path': rule['path']
|
||||
})
|
||||
except KeyError as e:
|
||||
raise exception.AccessRulesConfigFileError(error=e)
|
||||
|
||||
def _path_matches(self, request_path, path_pattern):
|
||||
# The fnmatch module doesn't provide the ability to match * versus **,
|
||||
# so convert to regex.
|
||||
# replace {tags} with *
|
||||
pattern = r'{[^}]*}'
|
||||
replace = r'*'
|
||||
path_regex = re.sub(pattern, replace, path_pattern)
|
||||
# temporarily sub out **
|
||||
pattern = r'([^\*]*)\*\*([^\*]*)'
|
||||
replace = r'\1%TMP%\2'
|
||||
path_regex = re.sub(pattern, replace, path_regex)
|
||||
# replace * with [^\/]* (all except /)
|
||||
pattern = r'([^\*]?)\*($|[^\*])'
|
||||
replace = r'\1[^\/]*\2'
|
||||
path_regex = re.sub(pattern, replace, path_regex)
|
||||
# replace ** with .* (includes /)
|
||||
pattern = r'%TMP%'
|
||||
replace = '.*'
|
||||
path_regex = re.sub(pattern, replace, path_regex)
|
||||
path_regex = r'^%s$' % path_regex
|
||||
regex = re.compile(path_regex)
|
||||
return regex.match(request_path)
|
||||
|
||||
def list_access_rules_config(self, service=None):
|
||||
"""List access rules config in human readable form."""
|
||||
if service:
|
||||
if service not in self.access_rules_json:
|
||||
raise exception.AccessRulesConfigNotFound(service=service)
|
||||
return {service: self.access_rules_json[service]}
|
||||
return self.access_rules_json
|
||||
|
||||
def check_access_rule(self, service, request_path, request_method):
|
||||
"""Check if an access rule exists in config."""
|
||||
if (service in self.access_rules
|
||||
and request_method in self.access_rules[service]):
|
||||
rules = self.access_rules[service][request_method]
|
||||
for rule in rules:
|
||||
if self._path_matches(request_path, rule['path']):
|
||||
return True
|
||||
return False
|
|
@ -20,7 +20,6 @@ import oslo_messaging
|
|||
from oslo_middleware import cors
|
||||
from osprofiler import opts as profiler
|
||||
|
||||
from keystone.conf import access_rules_config
|
||||
from keystone.conf import application_credential
|
||||
from keystone.conf import assignment
|
||||
from keystone.conf import auth
|
||||
|
@ -59,7 +58,6 @@ CONF = cfg.CONF
|
|||
|
||||
|
||||
conf_modules = [
|
||||
access_rules_config,
|
||||
application_credential,
|
||||
assignment,
|
||||
auth,
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
# Copyright 2019 SUSE Linux GmbH
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from keystone.conf import utils
|
||||
|
||||
|
||||
driver = cfg.StrOpt(
|
||||
'driver',
|
||||
default='json',
|
||||
help=utils.fmt("""
|
||||
Entry point for the access rules config backend driver in the
|
||||
`keystone.access_rules_config` namespace. Keystone only provides a `json`
|
||||
driver, so there is no reason to change this unless you are providing a custom
|
||||
entry point.
|
||||
"""))
|
||||
|
||||
caching = cfg.BoolOpt(
|
||||
'caching',
|
||||
default=True,
|
||||
help=utils.fmt("""
|
||||
Toggle for access rules caching. This has no effect unless global caching is
|
||||
enabled.
|
||||
"""))
|
||||
|
||||
cache_time = cfg.IntOpt(
|
||||
'cache_time',
|
||||
help=utils.fmt("""
|
||||
Time to cache access rule data in seconds. This has no effect unless global
|
||||
caching is enabled.
|
||||
"""))
|
||||
|
||||
rules_file = cfg.StrOpt(
|
||||
'rules_file',
|
||||
default='/etc/keystone/access_rules.json',
|
||||
help=utils.fmt("""
|
||||
Path to access rules configuration. If not present, no access rule
|
||||
configuration will be loaded and application credential access rules will be
|
||||
unavailable.
|
||||
"""))
|
||||
|
||||
GROUP_NAME = __name__.split('.')[-1]
|
||||
ALL_OPTS = [
|
||||
driver,
|
||||
caching,
|
||||
cache_time,
|
||||
rules_file,
|
||||
]
|
||||
|
||||
|
||||
def register_opts(conf):
|
||||
conf.register_opts(ALL_OPTS, group=GROUP_NAME)
|
||||
|
||||
|
||||
def list_opts():
|
||||
return {GROUP_NAME: ALL_OPTS}
|
|
@ -549,11 +549,6 @@ class ApplicationCredentialNotFound(NotFound):
|
|||
"%(application_credential_id)s.")
|
||||
|
||||
|
||||
class AccessRulesConfigNotFound(NotFound):
|
||||
message_format = _(
|
||||
"Could not find access rules config for service %(service)s.")
|
||||
|
||||
|
||||
class Conflict(Error):
|
||||
message_format = _("Conflict occurred attempting to store %(type)s -"
|
||||
" %(details)s.")
|
||||
|
@ -714,8 +709,3 @@ class CacheDeserializationError(Exception):
|
|||
'obj': obj, 'data': data
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class AccessRulesConfigFileError(UnexpectedError):
|
||||
debug_message_format = _(
|
||||
'Could not parse access rules config file: %(error)s')
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
# Copyright 2019 SUSE Linux GmbH
|
||||
#
|
||||
# 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 uuid
|
||||
|
||||
from keystone.access_rules_config.backends import json as json_driver
|
||||
from keystone import exception
|
||||
from keystone.tests import unit
|
||||
from keystone.tests.unit.ksfixtures import access_rules_config
|
||||
from keystone.tests.unit.ksfixtures import temporaryfile
|
||||
|
||||
|
||||
class JSONDriverTestCase(unit.TestCase):
|
||||
"""Tests for validating the access rules config driver."""
|
||||
|
||||
def setUp(self):
|
||||
super(JSONDriverTestCase, self).setUp()
|
||||
rules_file = '%s/access_rules.json' % unit.TESTCONF
|
||||
self.useFixture(access_rules_config.AccessRulesConfig(
|
||||
self.config_fixture, rules_file=rules_file))
|
||||
self.driver = json_driver.AccessRulesConfig()
|
||||
|
||||
def test_invalid_json_raises_error(self):
|
||||
tmpfile = self.useFixture(temporaryfile.SecureTempFile())
|
||||
invalid_access_rules = tmpfile.file_name
|
||||
with open(invalid_access_rules, 'w') as f:
|
||||
f.write("This is an invalid data")
|
||||
self.useFixture(access_rules_config.AccessRulesConfig(
|
||||
self.config_fixture, rules_file=invalid_access_rules))
|
||||
self.assertRaises(exception.AccessRulesConfigFileError,
|
||||
json_driver.AccessRulesConfig)
|
||||
|
||||
def test_list_access_rules_config(self):
|
||||
rules = self.driver.list_access_rules_config()
|
||||
self.assertIn('identity', rules)
|
||||
self.assertIn('image', rules)
|
||||
|
||||
def test_list_access_rules_config_for_service(self):
|
||||
rules = self.driver.list_access_rules_config(service='image')
|
||||
self.assertNotIn('identity', rules)
|
||||
self.assertIn('image', rules)
|
||||
|
||||
def test_check_access_rule(self):
|
||||
result = self.driver.check_access_rule('identity', '/v3/users', 'GET')
|
||||
self.assertTrue(result)
|
||||
userid = uuid.uuid4().hex
|
||||
check_path = '/v3/users/%(userid)s' % {'userid': userid}
|
||||
result = self.driver.check_access_rule('identity', check_path, 'GET')
|
||||
self.assertTrue(result)
|
||||
img = uuid.uuid4().hex
|
||||
memb = uuid.uuid4().hex
|
||||
check_path = '/v2/images/%(img)s/members/%(memb)s' % {'img': img,
|
||||
'memb': memb}
|
||||
result = self.driver.check_access_rule('image', check_path, 'PUT')
|
||||
self.assertTrue(result)
|
||||
result = self.driver.check_access_rule('image', '/servers', 'GET')
|
||||
self.assertFalse(result)
|
||||
result = self.driver.check_access_rule('glance', '/v2/images', 'GET')
|
||||
self.assertFalse(result)
|
||||
result = self.driver.check_access_rule('image', 'images', 'POST')
|
||||
self.assertFalse(result)
|
||||
projectid = uuid.uuid4().hex
|
||||
check_path = '/v3/%(projectid)s/volumes' % {'projectid': projectid}
|
||||
result = self.driver.check_access_rule('block-storage', check_path,
|
||||
'GET')
|
||||
self.assertTrue(result)
|
||||
check_path = '/v2/%(projectid)s/volumes' % {'projectid': projectid}
|
||||
result = self.driver.check_access_rule('block-storage', check_path,
|
||||
'GET')
|
||||
self.assertFalse(result)
|
||||
result = self.driver.check_access_rule('compute', '/v2.1/servers',
|
||||
'GET')
|
||||
self.assertTrue(result)
|
|
@ -1,890 +0,0 @@
|
|||
{
|
||||
"identity": [
|
||||
{
|
||||
"path": "/v3/users/*/application_credentials",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*/application_credentials",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*/application_credentials/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*/application_credentials/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/auth/catalog",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/auth/projects",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/auth/domains",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/auth/system",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/credentials",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/credentials",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/credentials/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/credentials/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/credentials/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/config/default",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/config/*/default",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/config/*/*/default",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config/*/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config/*/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config/*/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/config",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/groups",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/groups",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/groups/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/groups/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/groups/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/groups/*/users",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/groups/*/users/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/groups/*/users/*",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/groups/*/users/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/domains/*/users/*/roles/*/inherited_to_projects",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/domains/*/groups/*/roles/*/inherited_to_projects",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/domains/*/users/*/roles/inherited_to_projects",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/domains/*/groups/*/roles/inherited_to_projects",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/domains/*/users/*/roles/*/inherited_to_projects",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/domains/*/groups/*/roles/*/inherited_to_projects",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/domains/*/users/*/roles/*/inherited_to_projects",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/domains/*/groups/*/roles/*/inherited_to_projects",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/projects/*/users/*/roles/*/inherited_to_projects",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/projects/*/groups/*/roles/*/inherited_to_projects",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/projects/*/users/*/roles/*/inherited_to_projects",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/projects/*/groups/*/roles/*/inherited_to_projects",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/projects/*/users/*/roles/*/inherited_to_projects",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/OS-INHERIT/projects/*/groups/*/roles/*/inherited_to_projects",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/role_assignments",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/auth/tokens/OS-PKI/revoked",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/policies",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/policies",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/policies/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/policies/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/policies/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/tags",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/tags",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/tags",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/tags/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/tags/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/tags/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/regions/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/regions/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/regions/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/regions",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/regions",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/groups/*/roles",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/groups/*/roles/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/groups/*/roles/*",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/groups/*/roles/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/users/*/roles",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/users/*/roles/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/users/*/roles/*",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/domains/*/users/*/roles/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/groups/*/roles",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/groups/*/roles/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/groups/*/roles/*",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/groups/*/roles/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/users/*/roles",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/users/*/roles/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/users/*/roles/*",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/projects/*/users/*/roles/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles/*/implies",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles/*/implies/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles/*/implies/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles/*/implies/*",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/roles/*/implies/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/role_assignments",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/role_inferences",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/services",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/services",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/services/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/services/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/services/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/endpoints",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/endpoints",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/endpoints/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/endpoints/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/endpoints/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/users/*/roles",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/users/*/roles/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/users/*/roles/*",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/users/*/roles/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/users/*/roles/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/groups/*/roles",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/groups/*/roles/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/groups/*/roles/*",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/groups/*/roles/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/system/groups/*/roles/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/registered_limits",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/registered_limits",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/registered_limits/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/registered_limits/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/registered_limits/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/limits/model",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/limits",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/limits",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/limits/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/limits/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/limits/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*/groups",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*/projects",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v3/users/*/password",
|
||||
"method": "POST"
|
||||
}
|
||||
],
|
||||
"image": [
|
||||
{
|
||||
"path": "/v1/images",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v1/images",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v1/images/detail",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v1/images/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v1/images/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v1/images/*",
|
||||
"method": "HEAD"
|
||||
},
|
||||
{
|
||||
"path": "/v1/images/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v1/images/*/members/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v1/images/*/members",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v1/images/*/members/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v1/shared-images/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/file",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/file",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*",
|
||||
"method": "PATCH"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/actions/deactivate",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/actions/reactivate",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/images",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/image",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/members",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/member",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/members",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/members/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/members",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/members/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/members/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/tags/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v2/images/*/tags/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/objects",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/objects",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/objects/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/objects/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/objects/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/properties",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/properties",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/properties/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/properties/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/properties/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/tags/*",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/tags/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/tags/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/tags/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/tags",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/tags",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/tags",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*",
|
||||
"method": "PUT"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/resource_types",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/resource_types",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/resource_types",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/metadefs/namespaces/*/resource_types/*",
|
||||
"method": "DELETE"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/namespace",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/namespaces",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/resource_type",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/resource_types",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/object",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/objects",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/property",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/properties",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/tag",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/metadefs/tags",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/tasks",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/schemas/task",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/tasks",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"path": "/v2/tasks",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/v2/tasks/*",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/versions",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"method": "GET"
|
||||
}
|
||||
],
|
||||
"block-storage": [
|
||||
{
|
||||
"path": "/v3/**",
|
||||
"method": "GET"
|
||||
}
|
||||
],
|
||||
"compute": [
|
||||
{
|
||||
"path": "**",
|
||||
"method": "GET"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -11,7 +11,6 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from keystone.tests.unit.ksfixtures.access_rules_config import AccessRulesConfig # noqa
|
||||
from keystone.tests.unit.ksfixtures.auth_plugins import ConfigAuthPlugins # noqa
|
||||
from keystone.tests.unit.ksfixtures.backendloader import BackendLoader # noqa
|
||||
from keystone.tests.unit.ksfixtures.cache import Cache # noqa
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
# Copyright 2019 SUSE Linux GmbH
|
||||
#
|
||||
# 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 fixtures
|
||||
|
||||
|
||||
class AccessRulesConfig(fixtures.Fixture):
|
||||
"""A fixture for working with JSON access rules config."""
|
||||
|
||||
def __init__(self, config_fixture, rules_file=None):
|
||||
self._config_fixture = config_fixture
|
||||
self._rules_file = rules_file
|
||||
|
||||
def setUp(self):
|
||||
super(AccessRulesConfig, self).setUp()
|
||||
self._config_fixture.config(group='access_rules_config',
|
||||
rules_file=self._rules_file)
|
|
@ -178,9 +178,6 @@ keystone.unified_limit.model =
|
|||
flat = keystone.limit.models.flat:FlatModel
|
||||
strict_two_level = keystone.limit.models.strict_two_level:StrictTwoLevelModel
|
||||
|
||||
keystone.access_rules_config =
|
||||
json = keystone.access_rules_config.backends.json:AccessRulesConfig
|
||||
|
||||
oslo.config.opts =
|
||||
keystone = keystone.conf.opts:list_opts
|
||||
|
||||
|
|
Loading…
Reference in New Issue