Skip to content

Commit

Permalink
policy: clean-up
Browse files Browse the repository at this point in the history
Registers in-code the last remaining policy rules.
Adds missing 'discoverable' rules. Without them,
the extension_info API can fail, as it tries to check the
os_compute_api:os_server_tags:discoverable rule. As it wasn't
previously registered, when listing the available extensions,
an exception of type PolicyNotRegistered is encountered.
In order to validate this, functional/api_sample_tests/test_extension_info.py
now runs without mocking policy.authorize.

Switches extension_info to context.can.
Switches nova.cells.filters to context.can.
Switches network.neutronv2.api to context.can.

Removes the rest of the entries in etc/policy.json.
Removes DefaultPolicyTestCase, as it tests the default
policy rule, which is not registered.
Removes rules from fake_policy.py that brings no value,
that are the same as the default values.
Removes extensions authorizer factories.
Removes nova.policy.enforce.

Change-Id: Ie7771768f4f3efe0edc787c12f297aa93d533d7e
Partially-Implements: bp policy-in-code
  • Loading branch information
claudiubelu committed Jun 30, 2016
1 parent bc22a15 commit 7d01bce
Show file tree
Hide file tree
Showing 20 changed files with 266 additions and 259 deletions.
9 changes: 0 additions & 9 deletions etc/nova/policy.json
@@ -1,11 +1,2 @@
{
"context_is_admin": "role:admin",
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
"default": "rule:admin_or_owner",

"cells_scheduler_filter:TargetCellFilter": "is_admin:True",

"admin_api": "is_admin:True",

"network:attach_external_network": "is_admin:True"
}
6 changes: 4 additions & 2 deletions nova/api/openstack/compute/extension_info.py
Expand Up @@ -22,6 +22,7 @@
from nova.api.openstack import wsgi
from nova import exception
from nova.i18n import _LE
from nova.policies import base as base_policies
from nova.policies import extensions as ext_policies

ALIAS = 'extensions'
Expand Down Expand Up @@ -175,8 +176,9 @@ def _get_extensions(self, context):
)

for alias, ext in six.iteritems(self.extension_info.get_extensions()):
authorize = extensions.os_compute_soft_authorizer(alias)
if authorize(context, action='discoverable'):
action = ':'.join([
base_policies.COMPUTE_API, alias, 'discoverable'])
if context.can(action, fatal=False):
discoverable_extensions[alias] = ext
else:
LOG.debug("Filter out extension %s from discover list",
Expand Down
46 changes: 0 additions & 46 deletions nova/api/openstack/extensions.py
Expand Up @@ -23,13 +23,11 @@
import webob.dec
import webob.exc

import nova.api.openstack
from nova.api.openstack import wsgi
from nova import exception
from nova.i18n import _
from nova.i18n import _LE
from nova.i18n import _LW
import nova.policy

LOG = logging.getLogger(__name__)

Expand Down Expand Up @@ -265,50 +263,6 @@ def __init__(self, collection, controller=None, parent=None,
self.member_name = member_name


# This will be deprecated after policy cleanup finished
def core_authorizer(api_name, extension_name):
def authorize(context, target=None, action=None):
if target is None:
target = {'project_id': context.project_id,
'user_id': context.user_id}
if action is None:
act = '%s:%s' % (api_name, extension_name)
else:
act = '%s:%s:%s' % (api_name, extension_name, action)
nova.policy.enforce(context, act, target)
return authorize


def _soft_authorizer(hard_authorizer, api_name, extension_name):
hard_authorize = hard_authorizer(api_name, extension_name)

def authorize(context, target=None, action=None):
try:
hard_authorize(context, target=target, action=action)
return True
except exception.Forbidden:
return False
return authorize


# This will be deprecated after policy cleanup finished
def soft_core_authorizer(api_name, extension_name):
return _soft_authorizer(core_authorizer, api_name, extension_name)


# NOTE(alex_xu): The functions os_compute_authorizer and
# os_compute_soft_authorizer are used to policy enforcement for OpenStack
# Compute API, now Nova V2.1 REST API will invoke it.
#

def os_compute_authorizer(extension_name):
return core_authorizer('os_compute_api', extension_name)


def os_compute_soft_authorizer(extension_name):
return soft_core_authorizer('os_compute_api', extension_name)


@six.add_metaclass(abc.ABCMeta)
class V21APIExtensionBase(object):
"""Abstract base class for all v2.1 API extensions.
Expand Down
5 changes: 1 addition & 4 deletions nova/cells/filters/__init__.py
Expand Up @@ -18,7 +18,6 @@
"""

from nova import filters
from nova import policy


class BaseCellFilter(filters.BaseFilter):
Expand All @@ -31,9 +30,7 @@ def authorized(self, ctxt):
is the name of the filter class.
"""
name = 'cells_scheduler_filter:' + self.__class__.__name__
target = {'project_id': ctxt.project_id,
'user_id': ctxt.user_id}
return policy.enforce(ctxt, name, target, do_raise=False)
return ctxt.can(name, fatal=False)

def _filter_one(self, cell, filter_properties):
return self.cell_passes(cell, filter_properties)
Expand Down
8 changes: 3 additions & 5 deletions nova/network/neutronv2/api.py
Expand Up @@ -26,7 +26,6 @@
from oslo_utils import uuidutils
import six

from nova.api.openstack import extensions
from nova.compute import utils as compute_utils
import nova.conf
from nova import exception
Expand All @@ -40,14 +39,12 @@
from nova.pci import request as pci_request
from nova.pci import utils as pci_utils
from nova.pci import whitelist as pci_whitelist
from nova.policies import base as base_policies

CONF = nova.conf.CONF

LOG = logging.getLogger(__name__)

soft_external_network_attach_authorize = extensions.soft_core_authorizer(
'network', 'attach_external_network')

_SESSION = None
_ADMIN_AUTH = None

Expand Down Expand Up @@ -287,7 +284,8 @@ def _populate_mac_address(instance, port_req_body, available_macs):

def _check_external_network_attach(self, context, nets):
"""Check if attaching to external network is permitted."""
if not soft_external_network_attach_authorize(context):
if not context.can(base_policies.NETWORK_ATTACH_EXTERNAL,
fatal=False):
for net in nets:
# Perform this check here rather than in validate_networks to
# ensure the check is performed every time
Expand Down
10 changes: 10 additions & 0 deletions nova/policies/__init__.py
Expand Up @@ -22,8 +22,10 @@
from nova.policies import availability_zone
from nova.policies import baremetal_nodes
from nova.policies import base
from nova.policies import block_device_mapping
from nova.policies import block_device_mapping_v1
from nova.policies import cells
from nova.policies import cells_scheduler
from nova.policies import certificates
from nova.policies import cloudpipe
from nova.policies import config_drive
Expand Down Expand Up @@ -53,6 +55,7 @@
from nova.policies import hide_server_addresses
from nova.policies import hosts
from nova.policies import hypervisors
from nova.policies import image_metadata
from nova.policies import image_size
from nova.policies import images
from nova.policies import instance_actions
Expand All @@ -64,6 +67,7 @@
from nova.policies import migrate_server
from nova.policies import migrations
from nova.policies import multinic
from nova.policies import multiple_create
from nova.policies import networks
from nova.policies import networks_associate
from nova.policies import pause_server
Expand Down Expand Up @@ -91,6 +95,7 @@
from nova.policies import tenant_networks
from nova.policies import used_limits
from nova.policies import user_data
from nova.policies import versions
from nova.policies import virtual_interfaces
from nova.policies import volumes
from nova.policies import volumes_attachments
Expand All @@ -107,8 +112,10 @@ def list_rules():
availability_zone.list_rules(),
baremetal_nodes.list_rules(),
base.list_rules(),
block_device_mapping.list_rules(),
block_device_mapping_v1.list_rules(),
cells.list_rules(),
cells_scheduler.list_rules(),
certificates.list_rules(),
cloudpipe.list_rules(),
config_drive.list_rules(),
Expand Down Expand Up @@ -138,6 +145,7 @@ def list_rules():
hide_server_addresses.list_rules(),
hosts.list_rules(),
hypervisors.list_rules(),
image_metadata.list_rules(),
image_size.list_rules(),
images.list_rules(),
instance_actions.list_rules(),
Expand All @@ -149,6 +157,7 @@ def list_rules():
migrate_server.list_rules(),
migrations.list_rules(),
multinic.list_rules(),
multiple_create.list_rules(),
networks.list_rules(),
networks_associate.list_rules(),
pause_server.list_rules(),
Expand Down Expand Up @@ -176,6 +185,7 @@ def list_rules():
tenant_networks.list_rules(),
used_limits.list_rules(),
user_data.list_rules(),
versions.list_rules(),
virtual_interfaces.list_rules(),
volumes.list_rules(),
volumes_attachments.list_rules()
Expand Down
4 changes: 4 additions & 0 deletions nova/policies/base.py
Expand Up @@ -12,6 +12,9 @@

from oslo_policy import policy

COMPUTE_API = 'os_compute_api'
NETWORK_ATTACH_EXTERNAL = 'network:attach_external_network'

RULE_ADMIN_OR_OWNER = 'rule:admin_or_owner'
RULE_ADMIN_API = 'rule:admin_api'
RULE_ANY = '@'
Expand All @@ -21,6 +24,7 @@
policy.RuleDefault('admin_or_owner',
'is_admin:True or project_id:%(project_id)s'),
policy.RuleDefault('admin_api', 'is_admin:True'),
policy.RuleDefault(NETWORK_ATTACH_EXTERNAL, 'is_admin:True'),
]


Expand Down
32 changes: 32 additions & 0 deletions nova/policies/block_device_mapping.py
@@ -0,0 +1,32 @@
# Copyright 2016 Cloudbase Solutions Srl
# 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.

from oslo_policy import policy

from nova.policies import base


POLICY_ROOT = 'os_compute_api:os-block-device-mapping:%s'


block_device_mapping_policies = [
policy.RuleDefault(
name=POLICY_ROOT % 'discoverable',
check_str=base.RULE_ANY),
]


def list_rules():
return block_device_mapping_policies
33 changes: 33 additions & 0 deletions nova/policies/cells_scheduler.py
@@ -0,0 +1,33 @@
# Copyright 2016 Cloudbase Solutions Srl
# 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.

from oslo_policy import policy


POLICY_ROOT = 'cells_scheduler_filter:%s'


cells_scheduler_policies = [
policy.RuleDefault(
name=POLICY_ROOT % 'DifferentCellFilter',
check_str='is_admin:True'),
policy.RuleDefault(
name=POLICY_ROOT % 'TargetCellFilter',
check_str='is_admin:True'),
]


def list_rules():
return cells_scheduler_policies
32 changes: 32 additions & 0 deletions nova/policies/image_metadata.py
@@ -0,0 +1,32 @@
# Copyright 2016 Cloudbase Solutions Srl
# 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.

from oslo_policy import policy

from nova.policies import base


POLICY_ROOT = 'os_compute_api:image-metadata:%s'


image_metadata_policies = [
policy.RuleDefault(
name=POLICY_ROOT % 'discoverable',
check_str=base.RULE_ANY),
]


def list_rules():
return image_metadata_policies
32 changes: 32 additions & 0 deletions nova/policies/multiple_create.py
@@ -0,0 +1,32 @@
# Copyright 2016 Cloudbase Solutions Srl
# 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.

from oslo_policy import policy

from nova.policies import base


POLICY_ROOT = 'os_compute_api:os-multiple-create:%s'


multiple_create_policies = [
policy.RuleDefault(
name=POLICY_ROOT % 'discoverable',
check_str=base.RULE_ANY),
]


def list_rules():
return multiple_create_policies
3 changes: 3 additions & 0 deletions nova/policies/server_tags.py
Expand Up @@ -40,6 +40,9 @@
policy.RuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.RULE_ANY),
policy.RuleDefault(
name=POLICY_ROOT % 'discoverable',
check_str=base.RULE_ANY),
]


Expand Down
3 changes: 3 additions & 0 deletions nova/policies/servers_migrations.py
Expand Up @@ -34,6 +34,9 @@
policy.RuleDefault(
name=POLICY_ROOT % 'index',
check_str=base.RULE_ADMIN_API),
policy.RuleDefault(
name='os_compute_api:server-migrations:discoverable',
check_str=base.RULE_ANY),
]


Expand Down
2 changes: 1 addition & 1 deletion nova/policies/shelve.py
Expand Up @@ -32,7 +32,7 @@
name=POLICY_ROOT % 'shelve_offload',
check_str=base.RULE_ADMIN_API),
policy.RuleDefault(
name=POLICY_ROOT % 'shelve:discoverable',
name=POLICY_ROOT % 'discoverable',
check_str=base.RULE_ANY),
]

Expand Down

0 comments on commit 7d01bce

Please sign in to comment.