summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLance Bragstad <lbragstad@gmail.com>2018-10-17 21:11:14 +0000
committerLance Bragstad <lbragstad@gmail.com>2018-11-30 14:52:36 +0000
commit7a2d79eafcc902a57f270522e6bfc71876836688 (patch)
treeeb90c63911ed682f6b0d1894428869f4d2a6997b
parentfe898122c8cbf8b00e35307c719a04724bfecf46 (diff)
downloadoslo-policy-7a2d79eafcc902a57f270522e6bfc71876836688.tar.gz
Add domain scope support for scope types
This commit makes it easier for services to protect APIs meant for domain-only operations. It does this by making "domain-scope" an official scope type to check for during policy enforcement. A good example of where this would be useful is protecting the user API in keystone, since user's are technically owned by domains. This commit bumps the version of oslo.context to 2.22.0, which also has domain support. Depends-On: https://review.openstack.org/#/c/613635/ Change-Id: Ifc83a5f261bc823060eca5c4d0a4bf07966794c4
-rw-r--r--lower-constraints.txt2
-rw-r--r--oslo_policy/policy.py9
-rw-r--r--oslo_policy/tests/test_policy.py103
-rw-r--r--requirements.txt2
-rw-r--r--test-requirements.txt2
5 files changed, 108 insertions, 10 deletions
diff --git a/lower-constraints.txt b/lower-constraints.txt
index 765b06a..997ddc4 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -28,7 +28,7 @@ netifaces==0.10.4
openstackdocstheme==1.18.1
os-client-config==1.28.0
oslo.config==5.2.0
-oslo.context==2.21.0
+oslo.context==2.22.0
oslo.i18n==3.15.3
oslo.serialization==2.18.0
oslo.utils==3.33.0
diff --git a/oslo_policy/policy.py b/oslo_policy/policy.py
index 1758579..49e1c01 100644
--- a/oslo_policy/policy.py
+++ b/oslo_policy/policy.py
@@ -864,12 +864,11 @@ class Enforcer(object):
# attributes provided in `creds`.
if creds.get('system'):
token_scope = 'system'
+ elif creds.get('domain_id'):
+ token_scope = 'domain'
else:
- # If the token isn't system-scoped then we're dealing with
- # either a domain-scoped token or a project-scoped token.
- # From a policy perspective, both are "project" operations.
- # Whether or not the project is a domain depends on where
- # it sits in the hierarchy.
+ # If the token isn't system-scoped or domain-scoped then
+ # we're dealing with a project-scoped token.
token_scope = 'project'
registered_rule = self.registered_rules.get(rule)
diff --git a/oslo_policy/tests/test_policy.py b/oslo_policy/tests/test_policy.py
index d5e6686..51d6b7b 100644
--- a/oslo_policy/tests/test_policy.py
+++ b/oslo_policy/tests/test_policy.py
@@ -790,6 +790,105 @@ class EnforcerTest(base.PolicyBaseTestCase):
target_dict = {}
self.enforcer.enforce('fake_rule', target_dict, policy_values)
+ def test_enforcer_understands_system_scope(self):
+ self.conf.set_override('enforce_scope', True, group='oslo_policy')
+ rule = policy.RuleDefault(
+ name='fake_rule', check_str='role:test', scope_types=['system']
+ )
+ self.enforcer.register_default(rule)
+
+ ctx = context.RequestContext(system_scope='all')
+ target_dict = {}
+ self.enforcer.enforce('fake_rule', target_dict, ctx)
+
+ def test_enforcer_raises_invalid_scope_with_system_scope_type(self):
+ self.conf.set_override('enforce_scope', True, group='oslo_policy')
+ rule = policy.RuleDefault(
+ name='fake_rule', check_str='role:test', scope_types=['system']
+ )
+ self.enforcer.register_default(rule)
+
+ # model a domain-scoped token, which should fail enforcement
+ ctx = context.RequestContext(domain_id='fake')
+ target_dict = {}
+ self.assertRaises(
+ policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
+ target_dict, ctx
+ )
+
+ # model a project-scoped token, which should fail enforcement
+ ctx = context.RequestContext(project_id='fake')
+ self.assertRaises(
+ policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
+ target_dict, ctx
+ )
+
+ def test_enforcer_understands_domain_scope(self):
+ self.conf.set_override('enforce_scope', True, group='oslo_policy')
+ rule = policy.RuleDefault(
+ name='fake_rule', check_str='role:test', scope_types=['domain']
+ )
+ self.enforcer.register_default(rule)
+
+ ctx = context.RequestContext(domain_id='fake')
+ target_dict = {}
+ self.enforcer.enforce('fake_rule', target_dict, ctx)
+
+ def test_enforcer_raises_invalid_scope_with_domain_scope_type(self):
+ self.conf.set_override('enforce_scope', True, group='oslo_policy')
+ rule = policy.RuleDefault(
+ name='fake_rule', check_str='role:test', scope_types=['domain']
+ )
+ self.enforcer.register_default(rule)
+
+ # model a system-scoped token, which should fail enforcement
+ ctx = context.RequestContext(system_scope='all')
+ target_dict = {}
+ self.assertRaises(
+ policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
+ target_dict, ctx
+ )
+
+ # model a project-scoped token, which should fail enforcement
+ ctx = context.RequestContext(project_id='fake')
+ self.assertRaises(
+ policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
+ target_dict, ctx
+ )
+
+ def test_enforcer_understands_project_scope(self):
+ self.conf.set_override('enforce_scope', True, group='oslo_policy')
+ rule = policy.RuleDefault(
+ name='fake_rule', check_str='role:test', scope_types=['project']
+ )
+ self.enforcer.register_default(rule)
+
+ ctx = context.RequestContext(project_id='fake')
+ target_dict = {}
+ self.enforcer.enforce('fake_rule', target_dict, ctx)
+
+ def test_enforcer_raises_invalid_scope_with_project_scope_type(self):
+ self.conf.set_override('enforce_scope', True, group='oslo_policy')
+ rule = policy.RuleDefault(
+ name='fake_rule', check_str='role:test', scope_types=['project']
+ )
+ self.enforcer.register_default(rule)
+
+ # model a system-scoped token, which should fail enforcement
+ ctx = context.RequestContext(system_scope='all')
+ target_dict = {}
+ self.assertRaises(
+ policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
+ target_dict, ctx
+ )
+
+ # model a domain-scoped token, which should fail enforcement
+ ctx = context.RequestContext(domain_id='fake')
+ self.assertRaises(
+ policy.InvalidScope, self.enforcer.enforce, 'fake_rule',
+ target_dict, ctx
+ )
+
class EnforcerNoPolicyFileTest(base.PolicyBaseTestCase):
def setUp(self):
@@ -1013,10 +1112,10 @@ class RuleDefaultTestCase(base.PolicyBaseTestCase):
opt = policy.RuleDefault(
name='foo',
check_str='role:bar',
- scope_types=['project', 'system']
+ scope_types=['project', 'domain', 'system']
)
- self.assertEqual(opt.scope_types, ['project', 'system'])
+ self.assertEqual(opt.scope_types, ['project', 'domain', 'system'])
def test_ensure_scope_types_are_unique(self):
self.assertRaises(
diff --git a/requirements.txt b/requirements.txt
index 86517fd..204db1f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,7 @@
requests>=2.14.2 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0
-oslo.context>=2.21.0 # Apache-2.0
+oslo.context>=2.22.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
PyYAML>=3.12 # MIT
diff --git a/test-requirements.txt b/test-requirements.txt
index aea29ba..deb4d41 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -5,7 +5,7 @@ hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
oslotest>=3.2.0 # Apache-2.0
requests-mock>=1.1.0 # Apache-2.0
stestr>=2.0.0 # Apache-2.0
-oslo.context>=2.21.0 # Apache-2.0
+oslo.context>=2.22.0 # Apache-2.0
# computes code coverage percentages
coverage!=4.4,>=4.0 # Apache-2.0