150
163
LOG.exception(_("Failed to understand rule %(match)r") % locals())
151
164
# If the rule is invalid, fail closed
154
f = getattr(self, '_check_%s' % match_kind)
169
old_func = getattr(self, '_check_%s' % match_kind)
155
170
except AttributeError:
156
if not self._check_generic(match, target_dict, cred_dict):
171
func = self._checks.get(match_kind, self._checks.get(None, None))
159
if not f(match_value, target_dict, cred_dict):
173
LOG.warning(_("Inheritance-based rules are deprecated; update "
174
"_check_%s") % match_kind)
175
func = (lambda brain, kind, value, target, cred:
176
old_func(value, target, cred))
179
LOG.error(_("No handler for matches of kind %s") % match_kind)
183
return func(self, match_kind, match_value, target_dict, cred_dict)
163
185
def check(self, match_list, target_dict, cred_dict):
164
186
"""Checks authorization of some rules against credentials.
185
def _check_rule(self, match, target_dict, cred_dict):
186
"""Recursively checks credentials based on the brains rules."""
188
new_match_list = self.rules[match]
190
if self.default_rule and match != self.default_rule:
191
new_match_list = ('rule:%s' % self.default_rule,)
195
return self.check(new_match_list, target_dict, cred_dict)
197
def _check_role(self, match, target_dict, cred_dict):
198
"""Check that there is a matching role in the cred dict."""
199
return match.lower() in [x.lower() for x in cred_dict['roles']]
201
def _check_generic(self, match, target_dict, cred_dict):
202
"""Check an individual match.
211
# TODO(termie): do dict inspection via dot syntax
212
match = match % target_dict
213
key, value = match.split(':', 1)
215
return value == cred_dict[key]
219
208
class HttpBrain(Brain):
220
209
"""A brain that can check external urls for policy.
222
211
Posts json blobs for target and credentials.
226
def _check_http(self, match, target_dict, cred_dict):
227
"""Check http: rules by calling to a remote server.
229
This example implementation simply verifies that the response is
230
exactly 'True'. A custom brain using response codes could easily
234
url = match % target_dict
235
data = {'target': jsonutils.dumps(target_dict),
236
'credentials': jsonutils.dumps(cred_dict)}
237
post_data = urllib.urlencode(data)
238
f = urllib2.urlopen(url, post_data)
239
return f.read() == "True"
213
Note that this brain is deprecated; the http check is registered
220
def register(name, func=None):
222
Register a function as a policy check.
224
:param name: Gives the name of the check type, e.g., 'rule',
225
'role', etc. If name is None, a default function
227
:param func: If given, provides the function to register. If not
228
given, returns a function taking one argument to
229
specify the function to register, allowing use as a
233
# Perform the actual decoration by registering the function.
234
# Returns the function for compliance with the decorator
237
# Register the function
238
Brain._register(name, func)
241
# If the function is given, do the registration
243
return decorator(func)
249
def _check_rule(brain, match_kind, match, target_dict, cred_dict):
250
"""Recursively checks credentials based on the brains rules."""
252
new_match_list = brain.rules[match]
254
if brain.default_rule and match != brain.default_rule:
255
new_match_list = ('rule:%s' % brain.default_rule,)
259
return brain.check(new_match_list, target_dict, cred_dict)
263
def _check_role(brain, match_kind, match, target_dict, cred_dict):
264
"""Check that there is a matching role in the cred dict."""
265
return match.lower() in [x.lower() for x in cred_dict['roles']]
269
def _check_http(brain, match_kind, match, target_dict, cred_dict):
270
"""Check http: rules by calling to a remote server.
272
This example implementation simply verifies that the response is
273
exactly 'True'. A custom brain using response codes could easily
277
url = 'http:' + (match % target_dict)
278
data = {'target': jsonutils.dumps(target_dict),
279
'credentials': jsonutils.dumps(cred_dict)}
280
post_data = urllib.urlencode(data)
281
f = urllib2.urlopen(url, post_data)
282
return f.read() == "True"
286
def _check_generic(brain, match_kind, match, target_dict, cred_dict):
287
"""Check an individual match.
296
# TODO(termie): do dict inspection via dot syntax
297
match = match % target_dict
298
if match_kind in cred_dict:
299
return match == cred_dict[match_kind]