49
53
reload_func=_set_brain)
56
def get_resource_and_action(action):
57
""" Extract resource and action (write, read) from api operation """
58
data = action.split(':', 1)[0].split('_', 1)
59
return ("%ss" % data[-1], data[0] != 'get')
52
62
def _set_brain(data):
53
63
default_rule = 'default'
54
64
policy.set_brain(policy.Brain.load_json(data, default_rule))
57
def _get_resource_and_action(action):
58
data = action.split(':', 1)[0].split('_', 1)
59
return ("%ss" % data[-1], data[0] != 'get')
62
67
def _is_attribute_explicitly_set(attribute_name, resource, target):
63
68
"""Verify that an attribute is present and has a non-default value"""
64
69
if ('default' in resource[attribute_name] and
76
81
"parent" resource of the targeted one.
78
83
target = original_target.copy()
79
resource, _w = _get_resource_and_action(action)
84
resource, _a = get_resource_and_action(action)
80
85
hierarchy_info = attributes.RESOURCE_HIERARCHY_MAP.get(resource, None)
81
86
if hierarchy_info and plugin:
82
87
# use the 'singular' version of the resource name
93
def _create_access_rule_match(resource, is_write, shared):
94
if shared == resource[attributes.SHARED]:
95
return ('rule:%s:%s:%s' % (resource,
96
shared and 'shared' or 'private',
97
is_write and 'write' or 'read'), )
100
def _build_perm_match(action, target):
101
"""Create the permission rule match.
103
Given the current access right on a network (shared/private), and
104
the type of the current operation (read/write), builds a match
105
rule of the type <resource>:<sharing_mode>:<operation_type>
107
resource, is_write = _get_resource_and_action(action)
108
res_map = attributes.RESOURCE_ATTRIBUTE_MAP
109
if (resource in res_map and
110
attributes.SHARED in res_map[resource] and
111
attributes.SHARED in target):
112
return ('rule:%s:%s:%s' % (resource,
113
target[attributes.SHARED]
114
and 'shared' or 'private',
115
is_write and 'write' or 'read'), )
118
98
def _build_match_list(action, target):
119
99
"""Create the list of rules to match for a given action.
129
109
match_list = ('rule:%s' % action,)
130
resource, is_write = _get_resource_and_action(action)
131
# assigning to variable with short name for improving readability
132
res_map = attributes.RESOURCE_ATTRIBUTE_MAP
133
if resource in res_map:
134
for attribute_name in res_map[resource]:
135
if _is_attribute_explicitly_set(attribute_name,
138
attribute = res_map[resource][attribute_name]
139
if 'enforce_policy' in attribute and is_write:
140
match_list += ('rule:%s:%s' % (action,
142
# add permission-based rule (for shared resources)
143
perm_match = _build_perm_match(action, target)
145
match_list += perm_match
146
# the policy engine must AND between all the rules
110
resource, is_write = get_resource_and_action(action)
112
# assigning to variable with short name for improving readability
113
res_map = attributes.RESOURCE_ATTRIBUTE_MAP
114
if resource in res_map:
115
for attribute_name in res_map[resource]:
116
if _is_attribute_explicitly_set(attribute_name,
119
attribute = res_map[resource][attribute_name]
120
if 'enforce_policy' in attribute and is_write:
121
match_list += ('rule:%s:%s' % (action,
147
123
return [match_list]
126
@policy.register('field')
127
def check_field(brain, match_kind, match, target_dict, cred_dict):
128
# If this method is invoked for the wrong kind of match
129
# which should never happen, just skip the check and don't
130
# fail the policy evaluation
131
if match_kind != 'field':
132
LOG.warning("Field check function invoked with wrong match_kind:%s",
135
resource, field_value = match.split(':', 1)
136
field, value = field_value.split('=', 1)
137
target_value = target_dict.get(field)
138
# target_value might be a boolean, explicitly compare with None
139
if target_value is None:
140
LOG.debug("Unable to find requested field: %s in target: %s",
143
# Value migth need conversion - we need help from the attribute map
144
conv_func = attributes.RESOURCE_ATTRIBUTE_MAP[resource][field].get(
145
'convert_to', lambda x: x)
146
if target_value != conv_func(value):
147
LOG.debug("%s does not match the value in the target object:%s",
148
conv_func(value), target_value)
150
# If we manage to get here, the policy check is successful
150
154
def check(context, action, target, plugin=None):
151
155
"""Verifies that the action is valid on the target in this context.
188
191
real_target = _build_target(action, target, plugin, context)
189
192
match_list = _build_match_list(action, real_target)
190
193
credentials = context.to_dict()
192
194
policy.enforce(match_list, real_target, credentials,
193
195
exceptions.PolicyNotAuthorized, action=action)