policy-in-code support in neutron-lib

policy-in-code will be supported by the main neutron repo
because the neutron API layer uses the policy code in the neutron repo.
However, neutron_lib.context refers to its own policy enforcer,
so we need a small code to support policy-in-code in neutron-lib side.

Part of blueprint get-policy-from-neutron-lib
Change-Id: I4923a069f4080dc53a8fb359f5a1518de06feb2f
This commit is contained in:
Akihiro Motoki 2018-07-24 06:03:29 +09:00
parent c436b10e56
commit bede782630
5 changed files with 72 additions and 2 deletions

View File

@ -10,6 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import sys
from oslo_config import cfg
from oslo_policy import policy
@ -19,6 +21,18 @@ _ADMIN_CTX_POLICY = 'context_is_admin'
_ADVSVC_CTX_POLICY = 'context_is_advsvc'
_BASE_RULES = [
policy.RuleDefault(
_ADMIN_CTX_POLICY,
'role:admin',
description='Rule for cloud admin access'),
policy.RuleDefault(
_ADVSVC_CTX_POLICY,
'role:advsvc',
description='Rule for advanced service role access'),
]
def init(conf=cfg.CONF, policy_file=None):
"""Initialize the global enforcer if not already initialized.
@ -35,6 +49,7 @@ def init(conf=cfg.CONF, policy_file=None):
global _ROLE_ENFORCER
if not _ROLE_ENFORCER:
_ROLE_ENFORCER = policy.Enforcer(conf, policy_file=policy_file)
_ROLE_ENFORCER.register_defaults(_BASE_RULES)
_ROLE_ENFORCER.load_rules(True)
@ -65,3 +80,30 @@ def check_is_advsvc(context):
enforcer) and False otherwise.
"""
return _check_rule(context, _ADVSVC_CTX_POLICY)
def list_rules():
return _BASE_RULES
def get_enforcer():
# NOTE(amotoki): This was borrowed from nova/policy.py.
# This method is for use by oslo.policy CLI scripts. Those scripts need the
# 'output-file' and 'namespace' options, but having those in sys.argv means
# loading the neutron config options will fail as those are not expected to
# be present. So we pass in an arg list with those stripped out.
conf_args = []
# Start at 1 because cfg.CONF expects the equivalent of sys.argv[1:]
i = 1
while i < len(sys.argv):
if sys.argv[i].strip('-') in ['namespace', 'output-file']:
i += 2
continue
conf_args.append(sys.argv[i])
i += 1
# 'project' must be 'neutron' so that get_enforcer looks at
# /etc/neutron/policy.json by default.
cfg.CONF(conf_args, project='neutron')
init()
return _ROLE_ENFORCER

View File

@ -0,0 +1,4 @@
{
"context_is_admin": "role:dummy",
"context_is_advsvc": "role:dummy"
}

View File

@ -39,11 +39,16 @@ class TestPolicyEnforcer(base.BaseTestCase):
self.assertTrue(policy.check_is_admin(ctx))
def test_check_is_admin_no_roles_no_admin(self):
policy.init(policy_file='no_policy.json')
policy.init(policy_file='dummy_policy.json')
ctx = context.Context('me', 'my_project', roles=['user']).elevated()
# With no admin role, elevated() should not work.
self.assertFalse(policy.check_is_admin(ctx))
def test_check_user_elevated_is_admin_with_default_policy(self):
policy.init(policy_file='no_policy.json')
ctx = context.Context('me', 'my_project', roles=['user']).elevated()
self.assertTrue(policy.check_is_admin(ctx))
def test_check_is_advsvc_role(self):
ctx = context.Context('me', 'my_project', roles=['advsvc'])
self.assertTrue(policy.check_is_advsvc(ctx))
@ -58,7 +63,12 @@ class TestPolicyEnforcer(base.BaseTestCase):
self.assertFalse(policy.check_is_advsvc(ctx))
def test_check_is_advsvc_no_roles_no_advsvc(self):
policy.init(policy_file='no_policy.json')
policy.init(policy_file='dummy_policy.json')
ctx = context.Context('me', 'my_project', roles=['advsvc'])
# No advsvc role in the policy file, so cannot assume the role.
self.assertFalse(policy.check_is_advsvc(ctx))
def test_check_is_advsvc_role_with_default_policy(self):
policy.init(policy_file='no_policy.json')
ctx = context.Context('me', 'my_project', roles=['advsvc'])
self.assertTrue(policy.check_is_advsvc(ctx))

View File

@ -0,0 +1,8 @@
---
features:
- |
policy-in-code support in neutron-lib is added.
The default policies for 'context_is_admin' and 'context_is_advsvc' are
now implemented as embeded policies.
(Note that the main policy-in-code support will be implemented
in the main neutron codebase.)

View File

@ -22,6 +22,12 @@ classifier =
packages =
neutron_lib
[entry_points]
oslo.policy.enforcer =
neutron_lib = neutron_lib._policy:get_enforcer
oslo.policy.policies =
neutron_lib = neutron_lib._policy:list_rules
[compile_catalog]
directory = neutron_lib/locale
domain = neutron_lib