diff --git a/oslo_policy/shell.py b/oslo_policy/shell.py index 365a514e..7ffb5ea4 100644 --- a/oslo_policy/shell.py +++ b/oslo_policy/shell.py @@ -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['project_id'] = access_data['project']['id'] + 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 diff --git a/oslo_policy/tests/test_checks.py b/oslo_policy/tests/test_checks.py index 1cd08ec5..8c2f143b 100644 --- a/oslo_policy/tests/test_checks.py +++ b/oslo_policy/tests/test_checks.py @@ -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): diff --git a/oslo_policy/tests/test_shell.py b/oslo_policy/tests/test_shell.py index 09a07c71..32dad51b 100644 --- a/oslo_policy/tests/test_shell.py +++ b/oslo_policy/tests/test_shell.py @@ -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 diff --git a/oslo_policy/tests/token_fixture.py b/oslo_policy/tests/token_fixture.py index 6695efe2..683f1b17 100644 --- a/oslo_policy/tests/token_fixture.py +++ b/oslo_policy/tests/token_fixture.py @@ -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" + } + } +} diff --git a/sample_data/auth_v3_token_system_admin.json b/sample_data/auth_v3_token_system_admin.json new file mode 100644 index 00000000..bbf963f1 --- /dev/null +++ b/sample_data/auth_v3_token_system_admin.json @@ -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" + } + } +}