summaryrefslogtreecommitdiffstats
path: root/openstack
diff options
context:
space:
mode:
authorKevin L. Mitchell <kevin.mitchell@rackspace.com>2012-10-09 20:14:08 +0100
committerMark McLoughlin <markmc@redhat.com>2012-10-09 21:16:19 +0100
commit21b69d86fc2aaf2aa0316c0e0b099a91bcf6937a (patch)
treeb51775d34aaf707f2ba8687f9404b45007c62928 /openstack
parentfa7dc58b7f0a5de137b30299bfc4d3f3aaa8d0cf (diff)
downloadoslo-21b69d86fc2aaf2aa0316c0e0b099a91bcf6937a.tar.gz
oslo-21b69d86fc2aaf2aa0316c0e0b099a91bcf6937a.tar.xz
oslo-21b69d86fc2aaf2aa0316c0e0b099a91bcf6937a.zip
Add a 'not' operator to the policy langage
Implements blueprint fine-grained-policy Inverting the sense of a check was not possible with the list-of-lists syntax, but it clearly makes sense to support it. Change-Id: Ibd92cd75a279efdafec16a26f9aec33f39614b5c
Diffstat (limited to 'openstack')
-rw-r--r--openstack/common/policy.py42
1 files changed, 41 insertions, 1 deletions
diff --git a/openstack/common/policy.py b/openstack/common/policy.py
index f3efe55..f3b4be1 100644
--- a/openstack/common/policy.py
+++ b/openstack/common/policy.py
@@ -43,6 +43,11 @@ In the policy language, this becomes::
role:admin or (project_id:%(project_id)s and role:projectadmin)
+The policy language also has the "not" operator, allowing a richer
+policy rule::
+
+ project_id:%(project_id)s and not role:dunce
+
Finally, two special policy checks should be mentioned; the policy
check "@" will always accept an access, and the policy check "!" will
always reject an access. (Note that if a rule is either the empty
@@ -259,6 +264,35 @@ class Check(BaseCheck):
return "%s:%s" % (self.kind, self.match)
+class NotCheck(BaseCheck):
+ """
+ A policy check that inverts the result of another policy check.
+ Implements the "not" operator.
+ """
+
+ def __init__(self, rule):
+ """
+ Initialize the 'not' check.
+
+ :param rule: The rule to negate. Must be a Check.
+ """
+
+ self.rule = rule
+
+ def __str__(self):
+ """Return a string representation of this check."""
+
+ return "not %s" % self.rule
+
+ def __call__(self, target, cred):
+ """
+ Check the policy. Returns the logical inverse of the wrapped
+ check.
+ """
+
+ return not self.rule(target, cred)
+
+
class AndCheck(BaseCheck):
"""
A policy check that requires that a list of other checks all
@@ -447,7 +481,7 @@ def _parse_tokenize(rule):
# Yield the cleaned token
lowered = clean.lower()
- if lowered in ('and', 'or'):
+ if lowered in ('and', 'or', 'not'):
# Special tokens
yield lowered, clean
elif clean:
@@ -616,6 +650,12 @@ class ParseState(object):
return [('or_expr', or_expr.add_check(check))]
+ @reducer('not', 'check')
+ def _make_not_expr(self, _not, check):
+ """Invert the result of another check."""
+
+ return [('check', NotCheck(check))]
+
def _parse_text_rule(rule):
"""