Allow RBAC on Neutron quotas

This patch adds the support to allow role based access control
on quota of resources.

Change-Id: I6544d4a0794944abb3e1c2ff89134bf313cf35e8
Closes-Bug: #1671448
This commit is contained in:
andrewbogott 2019-12-26 23:34:31 -06:00 committed by Andrew Bogott
parent fe79ef22b8
commit c9242f9a88
4 changed files with 89 additions and 16 deletions

View File

@ -31,6 +31,7 @@ from neutron.conf.policies import network_ip_availability
from neutron.conf.policies import network_segment_range from neutron.conf.policies import network_segment_range
from neutron.conf.policies import port from neutron.conf.policies import port
from neutron.conf.policies import qos from neutron.conf.policies import qos
from neutron.conf.policies import quotas
from neutron.conf.policies import rbac from neutron.conf.policies import rbac
from neutron.conf.policies import router from neutron.conf.policies import router
from neutron.conf.policies import security_group from neutron.conf.policies import security_group
@ -60,6 +61,7 @@ def list_rules():
network_segment_range.list_rules(), network_segment_range.list_rules(),
port.list_rules(), port.list_rules(),
qos.list_rules(), qos.list_rules(),
quotas.list_rules(),
rbac.list_rules(), rbac.list_rules(),
router.list_rules(), router.list_rules(),
security_group.list_rules(), security_group.list_rules(),

View File

@ -0,0 +1,64 @@
# 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 neutron.conf.policies import base
COLLECTION_PATH = '/quota'
RESOURCE_PATH = '/quota/{id}'
rules = [
policy.DocumentedRuleDefault(
'get_quota',
base.RULE_ADMIN_ONLY,
'Get a resource quota',
[
{
'method': 'GET',
'path': COLLECTION_PATH,
},
{
'method': 'GET',
'path': RESOURCE_PATH,
},
]
),
policy.DocumentedRuleDefault(
'update_quota',
base.RULE_ADMIN_ONLY,
'Update a resource quota',
[
{
'method': 'PUT',
'path': RESOURCE_PATH,
},
]
),
policy.DocumentedRuleDefault(
'delete_quota',
base.RULE_ADMIN_ONLY,
'Delete a resource quota',
[
{
'method': 'DELETE',
'path': RESOURCE_PATH,
},
]
),
]
def list_rules():
return rules

View File

@ -27,6 +27,7 @@ from neutron._i18n import _
from neutron.api import extensions from neutron.api import extensions
from neutron.api.v2 import base from neutron.api.v2 import base
from neutron.api.v2 import resource from neutron.api.v2 import resource
from neutron import policy
from neutron import quota from neutron import quota
from neutron.quota import resource_registry from neutron.quota import resource_registry
from neutron import wsgi from neutron import wsgi
@ -42,6 +43,14 @@ EXTENDED_ATTRIBUTES_2_0 = {
} }
def validate_policy(context, policy_name):
policy.init()
policy.enforce(context,
policy_name,
target={'project_id': context.project_id},
plugin=None)
class QuotaSetsController(wsgi.Controller): class QuotaSetsController(wsgi.Controller):
def __init__(self, plugin): def __init__(self, plugin):
@ -70,12 +79,11 @@ class QuotaSetsController(wsgi.Controller):
tenant_id) tenant_id)
def default(self, request, id): def default(self, request, id):
if id != request.context.tenant_id: context = request.context
self._check_admin(request.context, if id != context.tenant_id:
reason=_("Only admin is authorized " validate_policy(context, "get_quota")
"to access quotas for another tenant"))
return {self._resource_name: self._driver.get_default_quotas( return {self._resource_name: self._driver.get_default_quotas(
context=request.context, context=context,
resources=resource_registry.get_all_resources(), resources=resource_registry.get_all_resources(),
tenant_id=id)} tenant_id=id)}
@ -85,7 +93,7 @@ class QuotaSetsController(wsgi.Controller):
def index(self, request): def index(self, request):
context = request.context context = request.context
self._check_admin(context) validate_policy(context, "get_quota")
return {self._resource_name + "s": return {self._resource_name + "s":
self._driver.get_all_quotas( self._driver.get_all_quotas(
context, resource_registry.get_all_resources())} context, resource_registry.get_all_resources())}
@ -99,22 +107,15 @@ class QuotaSetsController(wsgi.Controller):
def show(self, request, id): def show(self, request, id):
if id != request.context.tenant_id: if id != request.context.tenant_id:
self._check_admin(request.context, validate_policy(request.context, "get_quota")
reason=_("Only admin is authorized "
"to access quotas for another tenant"))
return {self._resource_name: self._get_quotas(request, id)} return {self._resource_name: self._get_quotas(request, id)}
def _check_admin(self, context,
reason=_("Only admin can view or configure quota")):
if not context.is_admin:
raise exceptions.AdminRequired(reason=reason)
def delete(self, request, id): def delete(self, request, id):
self._check_admin(request.context) validate_policy(request.context, "delete_quota")
self._driver.delete_tenant_quota(request.context, id) self._driver.delete_tenant_quota(request.context, id)
def update(self, request, id, body=None): def update(self, request, id, body=None):
self._check_admin(request.context) validate_policy(request.context, "update_quota")
if self._update_extended_attributes: if self._update_extended_attributes:
self._update_attributes() self._update_attributes()
body = base.Controller.prepare_request_body( body = base.Controller.prepare_request_body(

View File

@ -0,0 +1,6 @@
---
fixes:
- |
`1671448 <https://bugs.launchpad.net/neutron/+bug/1671448>`_
Access for Neutron quotas now governed using standard configurable
RBAC policies: 'get_quota', 'update_quota', 'delete_quota'