Modernize policy checker
Without this patch, the policy checker issues a 'failed' result when checking a system-scoped sample token against a policy string like "role:admin and system_scope:all", because the policy checker does not understand the 'system_scope' attribute that is now in oslo.context[1] and wasn't parsing the "system" scope object from the sample token. Similarly, it fails on a string like "user_id:%(user_id)s" because it never looked up the user_id from the sample token. This change updates the policy checker to understand token contexts and policies like these so that more of the policy defaults in keystone, and soon other projects, will pass. This also adds a new system-scoped sample token to check against. [1] https://review.opendev.org/530509 Change-Id: I02fbbc99d28aa5c787133f530f6e968341107bf7
This commit is contained in:
parent
e433a3cbec
commit
99daead510
@ -74,7 +74,11 @@ def tool(policy_file, access_file, apply_rule, is_admin=False,
|
||||
|
||||
access_data = jsonutils.loads(access)['token']
|
||||
access_data['roles'] = [role['name'] for role in access_data['roles']]
|
||||
access_data['user_id'] = access_data['user']['id']
|
||||
if access_data.get('project'):
|
||||
access_data['project_id'] = access_data['project']['id']
|
||||
if access_data.get('system'):
|
||||
access_data['system_scope'] = 'all'
|
||||
access_data['is_admin'] = is_admin
|
||||
|
||||
with open(policy_file, "rb", 0) as p:
|
||||
@ -90,7 +94,9 @@ def tool(policy_file, access_file, apply_rule, is_admin=False,
|
||||
|
||||
target_data = flatten(jsonutils.loads(target))
|
||||
else:
|
||||
target_data = {"project_id": access_data['project_id']}
|
||||
target_data = {'user_id': access_data['user']['id']}
|
||||
if access_data.get('project_id'):
|
||||
target_data['project_id'] = access_data['project_id']
|
||||
|
||||
if apply_rule:
|
||||
key = apply_rule
|
||||
|
@ -185,19 +185,19 @@ class GenericCheckTestCase(base.PolicyBaseTestCase):
|
||||
check = _checks.GenericCheck(
|
||||
'token.catalog.endpoints.id',
|
||||
token_fixture.REGION_ONE_PUBLIC_KEYSTONE_ENDPOINT_ID)
|
||||
credentials = token_fixture.SCOPED_TOKEN_FIXTURE
|
||||
credentials = token_fixture.PROJECT_SCOPED_TOKEN_FIXTURE
|
||||
self.assertTrue(check({}, credentials, self.enforcer))
|
||||
|
||||
def test_generic_role_check_matches(self):
|
||||
check = _checks.GenericCheck(
|
||||
'token.roles.name', 'role1')
|
||||
credentials = token_fixture.SCOPED_TOKEN_FIXTURE
|
||||
credentials = token_fixture.PROJECT_SCOPED_TOKEN_FIXTURE
|
||||
self.assertTrue(check({}, credentials, self.enforcer))
|
||||
|
||||
def test_generic_missing_role_does_not_matches(self):
|
||||
check = _checks.GenericCheck(
|
||||
'token.roles.name', 'missing')
|
||||
credentials = token_fixture.SCOPED_TOKEN_FIXTURE
|
||||
credentials = token_fixture.PROJECT_SCOPED_TOKEN_FIXTURE
|
||||
self.assertFalse(check({}, credentials, self.enforcer))
|
||||
|
||||
def test_multiple_nested_lists_accepted(self):
|
||||
|
@ -34,6 +34,15 @@ class CheckerTestCase(base.PolicyBaseTestCase):
|
||||
"sampleservice:sample_rule2": ""
|
||||
"sampleservice:sample_rule0": ""
|
||||
"sampleservice:sample_rule1": ""
|
||||
'''
|
||||
|
||||
SAMPLE_POLICY_SCOPED = '''---
|
||||
"sampleservice:sample_rule": "role:role1"
|
||||
"sampleservice:scoped_rule": "role:role1 and system_scope:all"
|
||||
'''
|
||||
|
||||
SAMPLE_POLICY_OWNER = '''---
|
||||
"sampleservice:owner_rule": "user_id:%(user_id)s"
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
@ -41,7 +50,7 @@ class CheckerTestCase(base.PolicyBaseTestCase):
|
||||
self.create_config_file("policy.yaml", self.SAMPLE_POLICY)
|
||||
self.create_config_file(
|
||||
"access.json",
|
||||
jsonutils.dumps(token_fixture.SCOPED_TOKEN_FIXTURE))
|
||||
jsonutils.dumps(token_fixture.PROJECT_SCOPED_TOKEN_FIXTURE))
|
||||
|
||||
@mock.patch("oslo_policy._checks.TrueCheck.__call__")
|
||||
def test_pass_rule_parameters(self, call_mock):
|
||||
@ -53,12 +62,14 @@ class CheckerTestCase(base.PolicyBaseTestCase):
|
||||
stdout = self._capture_stdout()
|
||||
|
||||
access_data = copy.deepcopy(
|
||||
token_fixture.SCOPED_TOKEN_FIXTURE["token"])
|
||||
token_fixture.PROJECT_SCOPED_TOKEN_FIXTURE["token"])
|
||||
target = {
|
||||
"project_id": access_data['project']['id']
|
||||
'user_id': access_data['user']['id'],
|
||||
'project_id': access_data['project']['id']
|
||||
}
|
||||
access_data['roles'] = [
|
||||
role['name'] for role in access_data['roles']]
|
||||
access_data['user_id'] = access_data['user']['id']
|
||||
access_data['project_id'] = access_data['project']['id']
|
||||
access_data['is_admin'] = is_admin
|
||||
|
||||
@ -71,6 +82,56 @@ class CheckerTestCase(base.PolicyBaseTestCase):
|
||||
'''
|
||||
self.assertEqual(expected, stdout.getvalue())
|
||||
|
||||
def test_pass_rule_parameters_with_scope(self):
|
||||
self.create_config_file("policy.yaml", self.SAMPLE_POLICY_SCOPED)
|
||||
self.create_config_file(
|
||||
"access.json",
|
||||
jsonutils.dumps(token_fixture.SYSTEM_SCOPED_TOKEN_FIXTURE))
|
||||
policy_file = self.get_config_file_fullname('policy.yaml')
|
||||
access_file = self.get_config_file_fullname('access.json')
|
||||
apply_rule = None
|
||||
is_admin = False
|
||||
stdout = self._capture_stdout()
|
||||
|
||||
access_data = copy.deepcopy(
|
||||
token_fixture.SYSTEM_SCOPED_TOKEN_FIXTURE["token"])
|
||||
access_data['roles'] = [
|
||||
role['name'] for role in access_data['roles']]
|
||||
access_data['user_id'] = access_data['user']['id']
|
||||
access_data['is_admin'] = is_admin
|
||||
|
||||
shell.tool(policy_file, access_file, apply_rule, is_admin)
|
||||
|
||||
expected = '''passed: sampleservice:sample_rule
|
||||
passed: sampleservice:scoped_rule
|
||||
'''
|
||||
self.assertEqual(expected, stdout.getvalue())
|
||||
|
||||
def test_pass_rule_parameters_with_owner(self):
|
||||
self.create_config_file("policy.yaml", self.SAMPLE_POLICY_OWNER)
|
||||
self.create_config_file(
|
||||
"access.json",
|
||||
jsonutils.dumps(token_fixture.PROJECT_SCOPED_TOKEN_FIXTURE))
|
||||
policy_file = self.get_config_file_fullname('policy.yaml')
|
||||
access_file = self.get_config_file_fullname('access.json')
|
||||
apply_rule = None
|
||||
is_admin = False
|
||||
stdout = self._capture_stdout()
|
||||
|
||||
access_data = copy.deepcopy(
|
||||
token_fixture.PROJECT_SCOPED_TOKEN_FIXTURE["token"])
|
||||
access_data['roles'] = [
|
||||
role['name'] for role in access_data['roles']]
|
||||
access_data['user_id'] = access_data['user']['id']
|
||||
access_data['project_id'] = access_data['project']['id']
|
||||
access_data['is_admin'] = is_admin
|
||||
|
||||
shell.tool(policy_file, access_file, apply_rule, is_admin)
|
||||
|
||||
expected = '''passed: sampleservice:owner_rule
|
||||
'''
|
||||
self.assertEqual(expected, stdout.getvalue())
|
||||
|
||||
def test_pass_rule_parameters_sorted(self):
|
||||
self.create_config_file("policy.yaml", self.SAMPLE_POLICY_UNSORTED)
|
||||
|
||||
@ -81,9 +142,10 @@ class CheckerTestCase(base.PolicyBaseTestCase):
|
||||
stdout = self._capture_stdout()
|
||||
|
||||
access_data = copy.deepcopy(
|
||||
token_fixture.SCOPED_TOKEN_FIXTURE["token"])
|
||||
token_fixture.PROJECT_SCOPED_TOKEN_FIXTURE["token"])
|
||||
access_data['roles'] = [
|
||||
role['name'] for role in access_data['roles']]
|
||||
access_data['user_id'] = access_data['user']['id']
|
||||
access_data['project_id'] = access_data['project']['id']
|
||||
access_data['is_admin'] = is_admin
|
||||
|
||||
@ -100,9 +162,10 @@ passed: sampleservice:sample_rule2
|
||||
apply_rule = None
|
||||
is_admin = False
|
||||
access_data = copy.deepcopy(
|
||||
token_fixture.SCOPED_TOKEN_FIXTURE["token"])
|
||||
token_fixture.PROJECT_SCOPED_TOKEN_FIXTURE["token"])
|
||||
access_data['roles'] = [
|
||||
role['name'] for role in access_data['roles']]
|
||||
access_data['user_id'] = access_data['user']['id']
|
||||
access_data['project_id'] = access_data['project']['id']
|
||||
access_data['is_admin'] = is_admin
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
REGION_ONE_PUBLIC_KEYSTONE_ENDPOINT_ID = '8cd4b957090f4ca5842a22e9a74099cd'
|
||||
|
||||
|
||||
SCOPED_TOKEN_FIXTURE = {
|
||||
PROJECT_SCOPED_TOKEN_FIXTURE = {
|
||||
"token": {
|
||||
"methods": [
|
||||
"password"
|
||||
@ -162,3 +162,143 @@ SCOPED_TOKEN_FIXTURE = {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SYSTEM_SCOPED_TOKEN_FIXTURE = {
|
||||
"token": {
|
||||
"methods": [
|
||||
"password"
|
||||
],
|
||||
"expires_at": "2038-01-18T21:14:07Z",
|
||||
"issued_at": "2000-01-18T21:14:07Z",
|
||||
"roles": [
|
||||
{
|
||||
"id": "41b1af9bb39241e8b8b79fae5906abcc",
|
||||
"name": "role1"
|
||||
},
|
||||
{
|
||||
"id": "ac9add6b3c5a46dcaaf21390c4657949",
|
||||
"name": "role2"
|
||||
}
|
||||
],
|
||||
"system": {
|
||||
"all": True
|
||||
},
|
||||
"catalog": [
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"id": "3b5e554bcf114f2483e8a1be7a0506d1",
|
||||
"interface": "admin",
|
||||
"url": "http://127.0.0.1:8776/v1/" +
|
||||
"64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "54abd2dc463c4ba4a72915498f8ecad1",
|
||||
"interface": "internal",
|
||||
"url": "http://127.0.0.1:8776/v1/" +
|
||||
"64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "70a7efa4b1b941968357cc43ae1419ee",
|
||||
"interface": "public",
|
||||
"url": "http://127.0.0.1:8776/v1/" +
|
||||
"64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
}
|
||||
],
|
||||
"id": "5707c3fc0a294703a3c638e9cf6a6c3a",
|
||||
"type": "volume",
|
||||
"name": "volume"
|
||||
},
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"id": "92217a3b95394492859bc49fd474382f",
|
||||
"interface": "admin",
|
||||
"url": "http://127.0.0.1:9292/v1",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "f20563bdf66f4efa8a1f11d99b672be1",
|
||||
"interface": "internal",
|
||||
"url": "http://127.0.0.1:9292/v1",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "375f9ba459a447738fb60fe5fc26e9aa",
|
||||
"interface": "public",
|
||||
"url": "http://127.0.0.1:9292/v1",
|
||||
"region": "regionOne"
|
||||
}
|
||||
],
|
||||
"id": "15c21aae6b274a8da52e0a068e908aac",
|
||||
"type": "image",
|
||||
"name": "glance"
|
||||
},
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"id": "edbd9f50f66746ae9ed11dc3b1ae35da",
|
||||
"interface": "admin",
|
||||
"url": "http://127.0.0.1:8774/v1.1/" +
|
||||
"64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "9e03c46c80a34a159cb39f5cb0498b92",
|
||||
"interface": "internal",
|
||||
"url": "http://127.0.0.1:8774/v1.1/" +
|
||||
"64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "1df0b44d92634d59bd0e0d60cf7ce432",
|
||||
"interface": "public",
|
||||
"url":
|
||||
"http://127.0.0.1:8774/v1.1/" +
|
||||
"64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
}
|
||||
],
|
||||
"id": "2f404fdb89154c589efbc10726b029ec",
|
||||
"type": "compute",
|
||||
"name": "nova"
|
||||
},
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"id": "a4501e141a4b4e14bf282e7bffd81dc5",
|
||||
"interface": "admin",
|
||||
"url": "http://127.0.0.1:35357/v3",
|
||||
"region": "RegionOne"
|
||||
},
|
||||
{
|
||||
"id": "3d17e3227bfc4483b58de5eaa584e360",
|
||||
"interface": "internal",
|
||||
"url": "http://127.0.0.1:35357/v3",
|
||||
"region": "RegionOne"
|
||||
},
|
||||
{
|
||||
"id": REGION_ONE_PUBLIC_KEYSTONE_ENDPOINT_ID,
|
||||
"interface": "public",
|
||||
"url": "http://127.0.0.1:5000/v3",
|
||||
"region": "RegionOne"
|
||||
}
|
||||
],
|
||||
"id": "c5d926d566424e4fba4f80c37916cde5",
|
||||
"type": "identity",
|
||||
"name": "keystone"
|
||||
}
|
||||
],
|
||||
"user": {
|
||||
"domain": {
|
||||
"id": "domain_id1",
|
||||
"name": "domain_name1"
|
||||
},
|
||||
"name": "user_name1",
|
||||
"id": "user_id1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
136
sample_data/auth_v3_token_system_admin.json
Normal file
136
sample_data/auth_v3_token_system_admin.json
Normal file
@ -0,0 +1,136 @@
|
||||
{
|
||||
"token": {
|
||||
"methods": [
|
||||
"password"
|
||||
],
|
||||
"expires_at": "2038-01-18T21:14:07Z",
|
||||
"issued_at": "2000-01-18T21:14:07Z",
|
||||
"roles": [
|
||||
{
|
||||
"id":"41b1af9bb39241e8b8b79fae5906abcc",
|
||||
"name": "admin"
|
||||
},
|
||||
{
|
||||
"id": "ac9add6b3c5a46dcaaf21390c4657949",
|
||||
"name": "member"
|
||||
},
|
||||
{
|
||||
"id": "b0cb8117845f4fd489865d498b80bab3",
|
||||
"name": "reader"
|
||||
}
|
||||
],
|
||||
"system": {
|
||||
"all": true
|
||||
},
|
||||
"catalog": [
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"id": "f84e070735e54914b41e2b5cfa94dcf7",
|
||||
"interface": "admin",
|
||||
"url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "8220bba1d2844e0b81b171c6ede1155f",
|
||||
"interface": "internal",
|
||||
"url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "719b92ea82a04e7a9ff1107c62da10da",
|
||||
"interface": "public",
|
||||
"url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
}
|
||||
],
|
||||
"type": "volume",
|
||||
"name": "volume",
|
||||
"id":"547e9195d1914b5eb087bedbc98fccc3"
|
||||
},
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"id": "44752324c0d44375bc854168ea22f1fc",
|
||||
"interface": "admin",
|
||||
"url": "http://127.0.0.1:9292/v1",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "a59b3734f57449078f1637c10f96c8e8",
|
||||
"interface": "internal",
|
||||
"url": "http://127.0.0.1:9292/v1",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "16c3ab1a4df640569812e432c98b2a48",
|
||||
"interface": "public",
|
||||
"url": "http://127.0.0.1:9292/v1",
|
||||
"region": "regionOne"
|
||||
}
|
||||
],
|
||||
"type": "image",
|
||||
"name": "glance",
|
||||
"id": "22c15d232e55419eb4aeb3ebbd12aac2"
|
||||
},
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"id": "9c2fdc2d45bb45c5a7f973e235e0f998",
|
||||
"interface": "admin",
|
||||
"url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "88ccfa8cbb7743998b38b998f4e6a720",
|
||||
"interface": "internal",
|
||||
"url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
},
|
||||
{
|
||||
"id": "113ee928c6934c92b9a12bd4e456c804",
|
||||
"interface": "public",
|
||||
"url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a",
|
||||
"region": "regionOne"
|
||||
}
|
||||
],
|
||||
"type": "compute",
|
||||
"name": "nova",
|
||||
"id": "fbf2afcdeb10473392636df9785d3fb5"
|
||||
},
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"id": "c10a5cda00784049953296d18464aa38",
|
||||
"interface": "admin",
|
||||
"url": "http://127.0.0.1:35357/v3",
|
||||
"region": "RegionOne"
|
||||
},
|
||||
{
|
||||
"id": "334650263e064428bb2f0b7c3c7a743c",
|
||||
"interface": "internal",
|
||||
"url": "http://127.0.0.1:35357/v3",
|
||||
"region": "RegionOne"
|
||||
},
|
||||
{
|
||||
"id": "52ff54addc38430d9b656c7164e2caf8",
|
||||
"interface": "public",
|
||||
"url": "http://127.0.0.1:5000/v3",
|
||||
"region": "RegionOne"
|
||||
}
|
||||
],
|
||||
"type": "identity",
|
||||
"name": "keystone",
|
||||
"id": "a0d9913a4bca4d5699e151804e0b5172"
|
||||
}
|
||||
],
|
||||
"user": {
|
||||
"domain": {
|
||||
"id": "domain_id1",
|
||||
"name": "domain_name1"
|
||||
},
|
||||
"name": "user_name1",
|
||||
"id": "user_id1"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user