summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Waldon <bcwaldon@gmail.com>2012-01-16 15:28:49 -0800
committerBrian Waldon <bcwaldon@gmail.com>2012-01-16 16:07:40 -0800
commit85518a93ef01ae997ecfc0687d89ba87f7607f54 (patch)
tree9d7928af887d05d8b1052ea5c9cabee82247f4bb
parent1fd26203b29d6432325ae1365e3dcbecc9d97864 (diff)
downloadnova-85518a93ef01ae997ecfc0687d89ba87f7607f54.tar.gz
Add default policy rule
If a specific rule is not found, we will check the rule defined in FLAGS.policy_default_action. Change-Id: Ib1b1aa4bbeec74bdb1562d0fc649d33838076f01
-rw-r--r--etc/nova/policy.json86
-rw-r--r--nova/common/policy.py13
-rw-r--r--nova/policy.py12
-rw-r--r--nova/tests/test_policy.py38
-rw-r--r--nova/volume/api.py7
5 files changed, 63 insertions, 93 deletions
diff --git a/etc/nova/policy.json b/etc/nova/policy.json
index 00140886bf..78003d2e32 100644
--- a/etc/nova/policy.json
+++ b/etc/nova/policy.json
@@ -1,95 +1,17 @@
{
"admin_or_owner": [["role:admin"], ["project_id:%(project_id)s"]],
+ "default": [["rule:admin_or_owner"]],
- "compute:create": [["rule:admin_or_owner"]],
- "compute:create:attach_network": [["rule:admin_or_owner"]],
- "compute:create:attach_volume": [["rule:admin_or_owner"]],
-
- "compute:get": [["rule:admin_or_owner"]],
+ "compute:create": [],
+ "compute:create:attach_network": [],
+ "compute:create:attach_volume": [],
"compute:get_all" :[],
- "compute:update": [["rule:admin_or_owner"]],
-
- "compute:get_instance_metadata": [["rule:admin_or_owner"]],
- "compute:update_instance_metadata": [["rule:admin_or_owner"]],
- "compute:delete_instance_metadata": [["rule:admin_or_owner"]],
-
- "compute:get_instance_faults": [["rule:admin_or_owner"]],
- "compute:get_actions": [["rule:admin_or_owner"]],
- "compute:get_diagnostics": [["rule:admin_or_owner"]],
-
- "compute:get_lock": [["rule:admin_or_owner"]],
- "compute:lock": [["rule:admin_or_owner"]],
- "compute:unlock": [["rule:admin_or_owner"]],
-
- "compute:get_ajax_console": [["rule:admin_or_owner"]],
- "compute:get_vnc_console": [["rule:admin_or_owner"]],
- "compute:get_console_output": [["rule:admin_or_owner"]],
-
- "compute:associate_floating_ip": [["rule:admin_or_owner"]],
- "compute:reset_network": [["rule:admin_or_owner"]],
- "compute:inject_network_info": [["rule:admin_or_owner"]],
- "compute:add_fixed_ip": [["rule:admin_or_owner"]],
- "compute:remove_fixed_ip": [["rule:admin_or_owner"]],
-
- "compute:attach_volume": [["rule:admin_or_owner"]],
- "compute:detach_volume": [["rule:admin_or_owner"]],
-
- "compute:inject_file": [["rule:admin_or_owner"]],
-
- "compute:set_admin_password": [["rule:admin_or_owner"]],
-
- "compute:rescue": [["rule:admin_or_owner"]],
- "compute:unrescue": [["rule:admin_or_owner"]],
-
- "compute:suspend": [["rule:admin_or_owner"]],
- "compute:resume": [["rule:admin_or_owner"]],
-
- "compute:pause": [["rule:admin_or_owner"]],
- "compute:unpause": [["rule:admin_or_owner"]],
-
- "compute:start": [["rule:admin_or_owner"]],
- "compute:stop": [["rule:admin_or_owner"]],
-
- "compute:resize": [["rule:admin_or_owner"]],
- "compute:confirm_resize": [["rule:admin_or_owner"]],
- "compute:revert_resize": [["rule:admin_or_owner"]],
-
- "compute:rebuild": [["rule:admin_or_owner"]],
-
- "compute:reboot": [["rule:admin_or_owner"]],
-
- "compute:snapshot": [["rule:admin_or_owner"]],
- "compute:backup": [["rule:admin_or_owner"]],
-
- "compute:add_security_group": [["rule:admin_or_owner"]],
- "compute:remove_security_group": [["rule:admin_or_owner"]],
-
- "compute:delete": [["rule:admin_or_owner"]],
- "compute:soft_delete": [["rule:admin_or_owner"]],
- "compute:force_delete": [["rule:admin_or_owner"]],
- "compute:restore": [["rule:admin_or_owner"]],
-
"volume:create": [],
- "volume:get": [],
"volume:get_all": [],
"volume:get_volume_metadata": [],
- "volume:delete": [],
- "volume:update": [],
- "volume:delete_volume_metadata": [],
- "volume:update_volume_metadata": [],
-
- "volume:attach": [],
- "volume:detach": [],
- "volume:check_attach": [],
- "volume:check_detach": [],
- "volume:initialize_connection": [],
- "volume:terminate_connection": [],
-
- "volume:create_snapshot": [],
- "volume:delete_snapshot": [],
"volume:get_snapshot": [],
"volume:get_all_snapshots": []
}
diff --git a/nova/common/policy.py b/nova/common/policy.py
index b7cd3cf417..d8d29d6b05 100644
--- a/nova/common/policy.py
+++ b/nova/common/policy.py
@@ -104,13 +104,14 @@ def enforce(match_list, target_dict, credentials_dict):
class Brain(object):
"""Implements policy checking."""
@classmethod
- def load_json(cls, data):
+ def load_json(cls, data, default_rule=None):
"""Init a brain using json instead of a rules dictionary."""
rules_dict = json.loads(data)
- return cls(rules=rules_dict)
+ return cls(rules=rules_dict, default_rule=default_rule)
- def __init__(self, rules=None):
+ def __init__(self, rules=None, default_rule=None):
self.rules = rules or {}
+ self.default_rule = default_rule
def add_rule(self, key, match):
self.rules[key] = match
@@ -154,7 +155,11 @@ class Brain(object):
try:
new_match_list = self.rules[match]
except KeyError:
- return False
+ if self.default_rule and match != self.default_rule:
+ new_match_list = ('rule:%s' % self.default_rule,)
+ else:
+ return False
+
return self.check(new_match_list, target_dict, cred_dict)
def _check_role(self, match, target_dict, cred_dict):
diff --git a/nova/policy.py b/nova/policy.py
index 1b3d77996b..22551d6a40 100644
--- a/nova/policy.py
+++ b/nova/policy.py
@@ -25,6 +25,8 @@ from nova import utils
FLAGS = flags.FLAGS
flags.DEFINE_string('policy_file', 'policy.json',
_('JSON file representing policy'))
+flags.DEFINE_string('policy_default_rule', 'default',
+ _('Rule checked when requested rule is not found'))
_POLICY_PATH = None
_POLICY_CACHE = {}
@@ -48,7 +50,8 @@ def init():
def _set_brain(data):
- policy.set_brain(policy.HttpBrain.load_json(data))
+ default_rule = FLAGS.policy_default_rule
+ policy.set_brain(policy.HttpBrain.load_json(data, default_rule))
def enforce(context, action, target):
@@ -69,10 +72,11 @@ def enforce(context, action, target):
"""
init()
+
match_list = ('rule:%s' % action,)
- target_dict = target
- credentials_dict = context.to_dict()
+ credentials = context.to_dict()
+
try:
- policy.enforce(match_list, target_dict, credentials_dict)
+ policy.enforce(match_list, target, credentials)
except policy.NotAuthorized:
raise exception.PolicyNotAuthorized(action=action)
diff --git a/nova/tests/test_policy.py b/nova/tests/test_policy.py
index fd3a05e764..d65371ea11 100644
--- a/nova/tests/test_policy.py
+++ b/nova/tests/test_policy.py
@@ -25,6 +25,7 @@ from nova.common import policy as common_policy
from nova import context
from nova import exception
from nova import flags
+import nova.common.policy
from nova import policy
from nova import test
@@ -137,3 +138,40 @@ class PolicyTestCase(test.TestCase):
def test_early_OR_enforcement(self):
action = "example:early_or_success"
policy.enforce(self.context, action, self.target)
+
+
+class DefaultPolicyTestCase(test.TestCase):
+
+ def setUp(self):
+ super(DefaultPolicyTestCase, self).setUp()
+ policy.reset()
+ policy.init()
+
+ self.rules = {
+ "default": [],
+ "example:exist": [["false:false"]]
+ }
+
+ self._set_brain('default')
+
+ self.context = context.RequestContext('fake', 'fake')
+
+ def _set_brain(self, default_rule):
+ brain = nova.common.policy.HttpBrain(self.rules, default_rule)
+ nova.common.policy.set_brain(brain)
+
+ def tearDown(self):
+ super(DefaultPolicyTestCase, self).setUp()
+ policy.reset()
+
+ def test_policy_called(self):
+ self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
+ self.context, "example:exist", {})
+
+ def test_not_found_policy_calls_default(self):
+ policy.enforce(self.context, "example:noexist", {})
+
+ def test_default_not_found(self):
+ self._set_brain("default_noexist")
+ self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
+ self.context, "example:noexist", {})
diff --git a/nova/volume/api.py b/nova/volume/api.py
index 6f5921f7ca..cc9cac019b 100644
--- a/nova/volume/api.py
+++ b/nova/volume/api.py
@@ -146,9 +146,10 @@ class API(base.Base):
self.db.volume_update(context, volume['id'], fields)
def get(self, context, volume_id):
- check_policy(context, 'get', {'id': volume_id})
rv = self.db.volume_get(context, volume_id)
- return dict(rv.iteritems())
+ volume = dict(rv.iteritems())
+ check_policy(context, 'get', volume)
+ return volume
def get_all(self, context, search_opts={}):
check_policy(context, 'get_all')
@@ -262,7 +263,7 @@ class API(base.Base):
def _create_snapshot(self, context, volume, name, description,
force=False):
- check_policy(context, 'create_snapshot')
+ check_policy(context, 'create_snapshot', volume)
if ((not force) and (volume['status'] != "available")):
raise exception.ApiError(_("Volume status must be available"))