~corey.bryant/ubuntu/trusty/neutron/lp1318721

« back to all changes in this revision

Viewing changes to neutron/policy.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Corey Bryant
  • Date: 2014-10-06 09:15:06 UTC
  • mfrom: (28.1.4 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20141006091506-cesvev43moce4y74
Tags: 1:2014.1.3-0ubuntu1
[ Corey Bryant ]
* Resynchronize with stable/icehouse (4a0210e) (LP: #1377136):
  - [3a30d19] Deletes floating ip related connection states
  - [dd4b77f] Forbid regular users to reset admin-only attrs to default values
  - [dc2c893] Add delete operations for the ODL MechanismDriver
  - [b51e2c7] Add missing ml2 plugin to migration 1fcfc149aca4
  - [a17a500] Don't convert numeric protocol values to int
  - [3a85946] NSX: Optionally not enforce nat rule match length check
  - [645f984] Don't spawn metadata-proxy for non-isolated nets
  - [b464d89] Big Switch: Check for 'id' in port before lookup
  - [3116ffa] use TRUE in SQL for boolean var
  - [3520e66] call security_groups_member_updated in port_update
  - [50e1534] Don't allow user to set firewall rule with port and no protocol
  - [0061533] BSN: Add context to backend request for debugging
  - [6de6d61] Improve ODL ML2 Exception Handling
  - [2a4153d] Send network name and uuid to subnet create
  - [b5e3c9a] BSN: Allow concurrent reads to consistency DB
  - [b201432] Big Switch: Retry on 503 errors from backend
  - [f6c47ee] NSX: log request body to NSX as debug
  - [97d622a] Fix metadata agent's auth info caching
  - [255df45] NSX: Correct allowed_address_pair return value on create_port
  - [5bea041] Neutron should not use the neutronclient utils module for import_class
  - [d5314e2] Cisco N1kv plugin to send subtype on network profile creation
  - [f32d1ce] Pass object to policy when finding fields to strip
  - [8b5f6be] Call policy.init() once per API request
  - [9a6d811] Perform policy checks only once on list responses
  - [c48db90] Datacenter moid should not be tuple
  - [161d465] Allow unsharing a network used as gateway/floatingip
  - [9574a2f] Add support for router scheduling in Cisco N1kv Plugin
  - [6f54565] Fix func job hook script permission problems
  - [ea43103] Add hook scripts for the functional infra job
  - [8161cb7] Fixes Hyper-V agent issue on Hyper-V 2008 R2
  - [8e99cfd] Fixes Hyper-V issue due to ML2 RPC versioning
  - [69f9121] Ensure ip6tables are used only if ipv6 is enabled in kernel
  - [399b809] Remove explicit dependency on amqplib
  - [a872143] Clear entries in Cisco N1KV specific tables on rollback
  - [ad82fad] Verify ML2 type driver exists before calling del
  - [af2cc98] Big Switch: Only update hash header on success
  - [b1e5eec] Ignore variable column widths in ovsdb functional tests
  - [4a0210e] VMWare: don't notify on disassociate_floatingips()

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
"""
19
19
Policy engine for neutron.  Largely copied from nova.
20
20
"""
 
21
 
 
22
import collections
21
23
import itertools
22
24
import re
23
25
 
24
26
from oslo.config import cfg
25
27
 
26
28
from neutron.api.v2 import attributes
 
29
from neutron.common import constants as const
27
30
from neutron.common import exceptions
28
31
import neutron.common.utils as utils
29
32
from neutron import manager
119
122
    policy.set_rules(policies)
120
123
 
121
124
 
122
 
def _is_attribute_explicitly_set(attribute_name, resource, target):
123
 
    """Verify that an attribute is present and has a non-default value."""
 
125
def _is_attribute_explicitly_set(attribute_name, resource, target, action):
 
126
    """Verify that an attribute is present and is explicitly set."""
 
127
    if 'update' in action:
 
128
        # In the case of update, the function should not pay attention to a
 
129
        # default value of an attribute, but check whether it was explicitly
 
130
        # marked as being updated instead.
 
131
        return (attribute_name in target[const.ATTRIBUTES_TO_UPDATE] and
 
132
                target[attribute_name] is not attributes.ATTR_NOT_SPECIFIED)
124
133
    return ('default' in resource[attribute_name] and
125
134
            attribute_name in target and
126
135
            target[attribute_name] is not attributes.ATTR_NOT_SPECIFIED and
127
136
            target[attribute_name] != resource[attribute_name]['default'])
128
137
 
129
138
 
 
139
def _should_validate_sub_attributes(attribute, sub_attr):
 
140
    """Verify that sub-attributes are iterable and should be validated."""
 
141
    validate = attribute.get('validate')
 
142
    return (validate and isinstance(sub_attr, collections.Iterable) and
 
143
            any([k.startswith('type:dict') and
 
144
                 v for (k, v) in validate.iteritems()]))
 
145
 
 
146
 
130
147
def _build_subattr_match_rule(attr_name, attr, action, target):
131
148
    """Create the rule to match for sub-attribute policy checks."""
132
149
    # TODO(salv-orlando): Instead of relying on validator info, introduce
164
181
       action is being executed
165
182
       (e.g.: create_router:external_gateway_info:network_id)
166
183
    """
167
 
 
168
184
    match_rule = policy.RuleCheck('rule', action)
169
185
    resource, is_write = get_resource_and_action(action)
170
186
    # Attribute-based checks shall not be enforced on GETs
175
191
            for attribute_name in res_map[resource]:
176
192
                if _is_attribute_explicitly_set(attribute_name,
177
193
                                                res_map[resource],
178
 
                                                target):
 
194
                                                target, action):
179
195
                    attribute = res_map[resource][attribute_name]
180
196
                    if 'enforce_policy' in attribute:
181
197
                        attr_rule = policy.RuleCheck('rule', '%s:%s' %
182
198
                                                     (action, attribute_name))
183
 
                        # Build match entries for sub-attributes, if present
184
 
                        validate = attribute.get('validate')
185
 
                        if (validate and any([k.startswith('type:dict') and v
186
 
                                              for (k, v) in
187
 
                                              validate.iteritems()])):
 
199
                        # Build match entries for sub-attributes
 
200
                        if _should_validate_sub_attributes(
 
201
                                attribute, target[attribute_name]):
188
202
                            attr_rule = policy.AndCheck(
189
203
                                [attr_rule, _build_subattr_match_rule(
190
204
                                    attribute_name, attribute,
317
331
 
318
332
def _prepare_check(context, action, target):
319
333
    """Prepare rule, target, and credentials for the policy engine."""
320
 
    init()
321
334
    # Compare with None to distinguish case in which target is {}
322
335
    if target is None:
323
336
        target = {}
326
339
    return match_rule, target, credentials
327
340
 
328
341
 
329
 
def check(context, action, target, plugin=None):
 
342
def check(context, action, target, plugin=None, might_not_exist=False):
330
343
    """Verifies that the action is valid on the target in this context.
331
344
 
332
345
    :param context: neutron context
337
350
        location of the object e.g. ``{'project_id': context.project_id}``
338
351
    :param plugin: currently unused and deprecated.
339
352
        Kept for backward compatibility.
 
353
    :param might_not_exist: If True the policy check is skipped (and the
 
354
        function returns True) if the specified policy does not exist.
 
355
        Defaults to false.
340
356
 
341
357
    :return: Returns True if access is permitted else False.
342
358
    """
343
 
    return policy.check(*(_prepare_check(context, action, target)))
344
 
 
345
 
 
346
 
def check_if_exists(context, action, target):
347
 
    """Verify if the action can be authorized, and raise if it is unknown.
348
 
 
349
 
    Check whether the action can be performed on the target within this
350
 
    context, and raise a PolicyRuleNotFound exception if the action is
351
 
    not defined in the policy engine.
352
 
    """
353
 
    # TODO(salvatore-orlando): Consider modifying oslo policy engine in
354
 
    # order to allow to raise distinct exception when check fails and
355
 
    # when policy is missing
356
 
    # Raise if there's no match for requested action in the policy engine
357
 
    if not policy._rules or action not in policy._rules:
358
 
        raise exceptions.PolicyRuleNotFound(rule=action)
 
359
    if might_not_exist and not (policy._rules and action in policy._rules):
 
360
        return True
359
361
    return policy.check(*(_prepare_check(context, action, target)))
360
362
 
361
363
 
374
376
    :raises neutron.exceptions.PolicyNotAuthorized: if verification fails.
375
377
    """
376
378
 
377
 
    init()
378
379
    rule, target, credentials = _prepare_check(context, action, target)
379
380
    result = policy.check(rule, target, credentials, action=action)
380
381
    if not result: