Add granular policy rules for /resource_classes*
This adds policy rules or the various /resource_classes* routes with the default being backward compatible with existing deployments (requires role:admin). The "non admin forbidden non json" gabbit had to be changed because the policy check moved so the test would fail with a 406 response instead of 403. Part of blueprint granular-placement-policy Change-Id: I90ef62e8e7b9e75830ac60e0c5c7e92845ab4afe
This commit is contained in:
parent
0a461979df
commit
77973ba7c5
|
@ -141,7 +141,10 @@ PER_ROUTE_POLICY = [
|
|||
'/$',
|
||||
# /resource_providers
|
||||
# /resource_providers/{uuid}
|
||||
'/resource_providers(/[A-Za-z0-9-]+)?$'
|
||||
'/resource_providers(/[A-Za-z0-9-]+)?$',
|
||||
# /resource_classes
|
||||
# /resource_classes/{name}
|
||||
'/resource_classes',
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import webob
|
|||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement import microversion
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova.api.openstack.placement.policies import resource_class as policies
|
||||
from nova.api.openstack.placement.schemas import resource_class as schema
|
||||
from nova.api.openstack.placement import util
|
||||
from nova.api.openstack.placement import wsgi_wrapper
|
||||
|
@ -62,6 +63,7 @@ def create_resource_class(req):
|
|||
header pointing to the newly created resource class.
|
||||
"""
|
||||
context = req.environ['placement.context']
|
||||
context.can(policies.CREATE)
|
||||
data = util.extract_json(req.body, schema.POST_RC_SCHEMA_V1_2)
|
||||
|
||||
try:
|
||||
|
@ -93,6 +95,7 @@ def delete_resource_class(req):
|
|||
"""
|
||||
name = util.wsgi_path_item(req.environ, 'name')
|
||||
context = req.environ['placement.context']
|
||||
context.can(policies.DELETE)
|
||||
# The containing application will catch a not found here.
|
||||
rc = rp_obj.ResourceClass.get_by_name(context, name)
|
||||
try:
|
||||
|
@ -119,6 +122,7 @@ def get_resource_class(req):
|
|||
"""
|
||||
name = util.wsgi_path_item(req.environ, 'name')
|
||||
context = req.environ['placement.context']
|
||||
context.can(policies.SHOW)
|
||||
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
||||
# The containing application will catch a not found here.
|
||||
rc = rp_obj.ResourceClass.get_by_name(context, name)
|
||||
|
@ -147,6 +151,7 @@ def list_resource_classes(req):
|
|||
a collection of resource classes.
|
||||
"""
|
||||
context = req.environ['placement.context']
|
||||
context.can(policies.LIST)
|
||||
want_version = req.environ[microversion.MICROVERSION_ENVIRON]
|
||||
rcs = rp_obj.ResourceClassList.get_all(context)
|
||||
|
||||
|
@ -172,6 +177,7 @@ def update_resource_class(req):
|
|||
"""
|
||||
name = util.wsgi_path_item(req.environ, 'name')
|
||||
context = req.environ['placement.context']
|
||||
context.can(policies.UPDATE)
|
||||
|
||||
data = util.extract_json(req.body, schema.PUT_RC_SCHEMA_V1_2)
|
||||
|
||||
|
@ -210,6 +216,7 @@ def update_resource_class(req):
|
|||
"""
|
||||
name = util.wsgi_path_item(req.environ, 'name')
|
||||
context = req.environ['placement.context']
|
||||
context.can(policies.UPDATE)
|
||||
|
||||
# Use JSON validation to validation resource class name.
|
||||
util.extract_json('{"name": "%s"}' % name, schema.PUT_RC_SCHEMA_V1_2)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
import itertools
|
||||
|
||||
from nova.api.openstack.placement.policies import base
|
||||
from nova.api.openstack.placement.policies import resource_class
|
||||
from nova.api.openstack.placement.policies import resource_provider
|
||||
|
||||
|
||||
|
@ -20,4 +21,5 @@ def list_rules():
|
|||
return itertools.chain(
|
||||
base.list_rules(),
|
||||
resource_provider.list_rules(),
|
||||
resource_class.list_rules(),
|
||||
)
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
# 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_policy import policy
|
||||
|
||||
from nova.api.openstack.placement.policies import base
|
||||
|
||||
|
||||
PREFIX = 'placement:resource_classes:%s'
|
||||
LIST = PREFIX % 'list'
|
||||
CREATE = PREFIX % 'create'
|
||||
SHOW = PREFIX % 'show'
|
||||
UPDATE = PREFIX % 'update'
|
||||
DELETE = PREFIX % 'delete'
|
||||
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
LIST,
|
||||
base.RULE_ADMIN_API,
|
||||
"List resource classes.",
|
||||
[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/resource_classes'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
CREATE,
|
||||
base.RULE_ADMIN_API,
|
||||
"Create resource class.",
|
||||
[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/resource_classes'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
SHOW,
|
||||
base.RULE_ADMIN_API,
|
||||
"Show resource class.",
|
||||
[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/resource_classes/{name}'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
UPDATE,
|
||||
base.RULE_ADMIN_API,
|
||||
"Update resource class.",
|
||||
[
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/resource_classes/{name}'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
DELETE,
|
||||
base.RULE_ADMIN_API,
|
||||
"Delete resource class.",
|
||||
[
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/resource_classes/{name}'
|
||||
}
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return rules
|
|
@ -0,0 +1,40 @@
|
|||
# This tests the individual CRUD operations on /resource_classes
|
||||
# using a non-admin user with an open policy configuration. The
|
||||
# response validation is intentionally minimal.
|
||||
fixtures:
|
||||
- OpenPolicyFixture
|
||||
|
||||
defaults:
|
||||
request_headers:
|
||||
x-auth-token: user
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement latest
|
||||
|
||||
tests:
|
||||
|
||||
- name: list resource classes
|
||||
GET: /resource_classes
|
||||
response_json_paths:
|
||||
$.resource_classes.`len`: 12 # Number of standard resource classes
|
||||
|
||||
- name: create resource class
|
||||
POST: /resource_classes
|
||||
data:
|
||||
name: CUSTOM_RES_CLASS_POLICY
|
||||
status: 201
|
||||
response_headers:
|
||||
location: //resource_classes/CUSTOM_RES_CLASS_POLICY/
|
||||
|
||||
- name: show resource class
|
||||
GET: /resource_classes/CUSTOM_RES_CLASS_POLICY
|
||||
response_json_paths:
|
||||
$.name: CUSTOM_RES_CLASS_POLICY
|
||||
|
||||
- name: update resource class
|
||||
PUT: /resource_classes/CUSTOM_NEW_CLASS_POLICY
|
||||
status: 201
|
||||
|
||||
- name: delete resource class
|
||||
DELETE: /resource_classes/CUSTOM_NEW_CLASS_POLICY
|
||||
status: 204
|
|
@ -63,14 +63,16 @@ tests:
|
|||
response_json_paths:
|
||||
$.errors[0].title: Forbidden
|
||||
|
||||
- name: non admin forbidden non json
|
||||
GET: /resource_classes
|
||||
- name: post invalid non json
|
||||
POST: /resource_classes
|
||||
request_headers:
|
||||
x-auth-token: user
|
||||
accept: text/plain
|
||||
status: 403
|
||||
accept: text/plain
|
||||
content-type: application/json
|
||||
data:
|
||||
name: FOO
|
||||
status: 400
|
||||
response_strings:
|
||||
- admin required
|
||||
- JSON does not validate
|
||||
|
||||
- name: post illegal characters in name
|
||||
POST: /resource_classes
|
||||
|
|
Loading…
Reference in New Issue