Browse Source

Add RBAC tests

This change leverages the nine default personas available in tempest[1]
to demonstrate a potential framework for testing default policies. An
abstract base class is created that helps set up credentials and
outlines every policy that needs to be tested, then nine subclasses are
created to test every persona. Each test represents one policy rule, and
some tests make multiple requests in order to test the policy from
different approaches, for example, to check what happens if a different
domain is specified, or what happens if the resource does not exist.

The idea here is to be very verbose and explicit about what is being
tested: every policy gets one test in the base class, and each persona
is tested in a subclass. The layout should be easy to understand and
someone reading the code should not be left guessing whether a case is
missing or if there is magic happening in the background that is causing
a false positive or false negative.

This is intended to replace the unittest protection tests currently
in place.

[1] https://review.opendev.org/686306 (this will require additional
devstack and keystone configuration to work properly in CI)

Depends-on: https://review.opendev.org/686306
Depends-on: https://review.opendev.org/699051
Depends-on: https://review.opendev.org/699519
Depends-on: https://review.opendev.org/700826
Depends-on: https://review.opendev.org/743853
Depends-on: https://review.opendev.org/744087
Depends-on: https://review.opendev.org/744268
Depends-on: https://review.opendev.org/731087

Change-Id: Icb5317b9297230490bd783fe9b07c8db244c06f8
changes/05/686305/48 0.7.0
Colleen Murphy 1 year ago
committed by Lance Bragstad
parent
commit
a6d4ceaf57
37 changed files with 16024 additions and 4 deletions
  1. +38
    -0
      .zuul.yaml
  2. +5
    -1
      keystone_tempest_plugin/config.py
  3. +2
    -2
      keystone_tempest_plugin/plugin.py
  4. +0
    -0
      keystone_tempest_plugin/tests/rbac/__init__.py
  5. +0
    -0
      keystone_tempest_plugin/tests/rbac/v3/__init__.py
  6. +41
    -0
      keystone_tempest_plugin/tests/rbac/v3/base.py
  7. +487
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_access_rule.py
  8. +551
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_application_credential.py
  9. +196
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_consumer.py
  10. +490
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_credential.py
  11. +223
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_domain.py
  12. +381
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_domain_config.py
  13. +544
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_ec2_credential.py
  14. +245
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_endpoint.py
  15. +521
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_endpoint_group.py
  16. +3799
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_grant.py
  17. +1152
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_group.py
  18. +283
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_identity_provider.py
  19. +257
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_implied_role.py
  20. +391
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_limit.py
  21. +255
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_mapping.py
  22. +232
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_policy.py
  23. +469
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_policy_association.py
  24. +467
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_project.py
  25. +251
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_project_endpoint.py
  26. +599
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_project_tag.py
  27. +302
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_protocol.py
  28. +209
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_region.py
  29. +222
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_registered_limit.py
  30. +390
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_role.py
  31. +1130
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_role_assignment.py
  32. +233
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_service.py
  33. +250
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_service_provider.py
  34. +309
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_token.py
  35. +559
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_trust.py
  36. +540
    -0
      keystone_tempest_plugin/tests/rbac/v3/test_user.py
  37. +1
    -1
      tox.ini

+ 38
- 0
.zuul.yaml View File

@ -1,3 +1,39 @@
- job:
name: keystone-protection-functional
parent: keystone-dsvm-py3-functional
vars:
tempest_test_regex: 'keystone_tempest_plugin.tests.rbac'
devstack_localrc:
KEYSTONE_ENFORCE_SCOPE: True
devstack_plugins:
keystone: https://opendev.org/openstack/keystone
devstack_services:
g-api: false
g-reg: false
n-api: false
n-api-meta: false
n-cond: false
n-cpu: false
n-novnc: false
n-sch: false
placement-api: false
q-agt: false
q-dhcp: false
q-l3: false
q-meta: false
q-metering: false
s-account: false
s-container: false
s-object: false
s-proxy: false
c-api: false
c-bak: false
c-sch: false
c-vol: false
cinder: false
devstack_local_conf:
post-config: {}
- project:
templates:
- check-requirements
@ -11,10 +47,12 @@
- keystone-dsvm-py3-functional-ussuri
- keystone-dsvm-py3-functional-train
- keystone-dsvm-py3-functional-stein
- keystone-protection-functional
gate:
jobs:
- keystone-dsvm-py3-functional
- keystone-dsvm-py3-functional-federation-ubuntu-focal-k2k
- keystone-protection-functional
- job:
name: keystone-dsvm-py3-functional-ussuri


+ 5
- 1
keystone_tempest_plugin/config.py View File

@ -15,7 +15,7 @@
from oslo_config import cfg
identity_feature_option = [
identity_feature_options = [
cfg.BoolOpt('federation',
default=False,
help='Does the environment support the Federated Identity '
@ -25,6 +25,10 @@ identity_feature_option = [
help='Whether to test federated scenarios against an external '
'identity provider. If disabled, only '
'Keystone-to-Keystone tests will be enabled.'),
cfg.BoolOpt('enforce_scope',
default=False,
help='Does the keystone service enforce scope and use '
'scope-aware policies?'),
]
fed_scenario_group = cfg.OptGroup(name='fed_scenario',


+ 2
- 2
keystone_tempest_plugin/plugin.py View File

@ -32,12 +32,12 @@ class KeystoneTempestPlugin(plugins.TempestPlugin):
def register_opts(self, conf):
config.register_opt_group(conf, config.identity_feature_group,
project_config.identity_feature_option)
project_config.identity_feature_options)
config.register_opt_group(conf, project_config.fed_scenario_group,
project_config.FedScenarioGroup)
def get_opt_lists(self):
return [(config.identity_feature_group.name,
project_config.identity_feature_option),
project_config.identity_feature_options),
(project_config.fed_scenario_group.name,
project_config.FedScenarioGroup)]

+ 0
- 0
keystone_tempest_plugin/tests/rbac/__init__.py View File


+ 0
- 0
keystone_tempest_plugin/tests/rbac/v3/__init__.py View File


+ 41
- 0
keystone_tempest_plugin/tests/rbac/v3/base.py View File

@ -0,0 +1,41 @@
# Copyright 2020 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from tempest import config
CONF = config.CONF
class IdentityV3RbacBaseTests(object):
identity_version = 'v3'
@classmethod
def skip_checks(cls):
super(IdentityV3RbacBaseTests, cls).skip_checks()
if not CONF.identity_feature_enabled.enforce_scope:
raise cls.skipException("enforce_scope is not enabled for "
"keystone, skipping RBAC tests")
def do_request(self, method, expected_status=200, client=None, **payload):
if not client:
client = self.client
if isinstance(expected_status, type(Exception)):
self.assertRaises(expected_status,
getattr(client, method),
**payload)
else:
response = getattr(client, method)(**payload)
self.assertEqual(response.response.status, expected_status)
return response

+ 487
- 0
keystone_tempest_plugin/tests/rbac/v3/test_access_rule.py View File

@ -0,0 +1,487 @@
# Copyright 2020 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import abc
from tempest.api.identity import base
from tempest import clients
from tempest.lib import auth
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
from keystone_tempest_plugin.tests.rbac.v3 import base as rbac_base
class IdentityV3RbacAccessRuleTest(rbac_base.IdentityV3RbacBaseTests,
metaclass=abc.ABCMeta):
identity_version = 'v3'
@classmethod
def setup_clients(cls):
super(IdentityV3RbacAccessRuleTest, cls).setup_clients()
cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
cls.client = cls.persona.access_rules_client
cls.admin_client = cls.os_system_admin
def user(self):
user = {}
name = data_utils.rand_name('user')
user['name'] = name
user['password'] = data_utils.rand_password()
return user
def app_cred(self):
app_cred = {}
app_cred['name'] = data_utils.rand_name('app_cred')
app_cred['access_rules'] = [
{
'path': '/servers',
'method': 'GET',
'service': 'compute',
}
]
return app_cred
@classmethod
def setup_user_client(cls, domain_id=None):
"""Set up project user with its own client.
This is to enable the project user to create its own app cred.
Returns a client object and the user's ID.
"""
user_dict = {
'name': data_utils.rand_name('user'),
'password': data_utils.rand_password(),
}
if domain_id:
user_dict['domain_id'] = domain_id
user_id = cls.admin_client.users_v3_client.create_user(
**user_dict)['user']['id']
def try_delete_user():
# delete user if not deleted by domain deletion
try:
cls.admin_client.users_v3_client.delete_user(user_id)
except exceptions.NotFound:
pass
cls.addClassResourceCleanup(try_delete_user)
project_id = cls.admin_client.projects_client.create_project(
data_utils.rand_name())['project']['id']
cls.addClassResourceCleanup(
cls.admin_client.projects_client.delete_project, project_id)
member_role_id = cls.admin_client.roles_v3_client.list_roles(
name='member')['roles'][0]['id']
cls.admin_client.roles_v3_client.create_user_role_on_project(
project_id, user_id, member_role_id)
creds = auth.KeystoneV3Credentials(
user_id=user_id,
password=user_dict['password'],
project_id=project_id)
auth_provider = clients.get_auth_provider(creds)
creds = auth_provider.fill_credentials()
client = clients.Manager(credentials=creds)
return client, user_id
@abc.abstractmethod
def test_identity_get_access_rule(self):
"""Test identity:get_access_rule policy
This test must check:
* whether the persona can retrieve an access rule they own
* whether the persona can retrieve an access rule they do not own
* whether the persona can retrieve an access rule that does not exist
* whether the persona can retrieve an access rule for a user in their
own domain (if applicable)
* whether the persona can retrieve an access rule for a user in
another domain (if applicable)
"""
pass
@abc.abstractmethod
def test_identity_list_access_rules(self):
"""Test identity:list_access_rules policy
This test must check:
* whether the persona can list their own access rules
* whether the persona can list the access rules for another user
* whether the persona can list the access rules for a user in their
own domain
* whether the persona can list the access rules for a user in another
domain
"""
pass
@abc.abstractmethod
def test_identity_delete_access_rule(self):
"""Test identity:delete_access_rule policy.
This test must check
* whether the persona can delete an access rule they own
* whether the persona can delete an access rule for an arbitrary user
* whether the persona can delete an access rule that does not exist
* whether the persona can delete an access rule for a user in another
domain (if applicable)
* whether the persona can delete an access rule for a user in their
own domain (if applicable)
* whether the persona can delete an access rule that does not exist
"""
pass
class SystemAdminTests(IdentityV3RbacAccessRuleTest, base.BaseIdentityTest):
credentials = ['system_admin']
@classmethod
def setup_clients(cls):
super(SystemAdminTests, cls).setup_clients()
cls.test_user_client, cls.test_user_id = cls.setup_user_client()
def setUp(self):
# create app cred for other user
super(SystemAdminTests, self).setUp()
app_cred_client = self.test_user_client.application_credentials_client
app_cred = app_cred_client.create_application_credential(
user_id=self.test_user_id, **self.app_cred()
)['application_credential']
self.app_cred_id = app_cred['id']
self.access_rule_id = app_cred['access_rules'][0]['id']
def try_delete_app_cred(id):
app_cred_client = self.admin_client.application_credentials_client
try:
app_cred_client.delete_application_credential(
user_id=self.test_user_id,
application_credential_id=id)
except exceptions.NotFound:
pass
def try_delete_access_rule(id):
try:
self.admin_client.access_rules_client.delete_access_rule(
user_id=self.test_user_id,
access_rule_id=id)
except exceptions.NotFound:
pass
self.addCleanup(try_delete_access_rule, self.access_rule_id)
self.addCleanup(try_delete_app_cred, self.app_cred_id)
def test_identity_get_access_rule(self):
# system admin cannot create app creds and therefore cannot create
# access rules, so skip retrieval of own access rule
# retrieve other user's access rules
self.do_request(
'show_access_rule',
user_id=self.test_user_id, access_rule_id=self.access_rule_id)
# retrieving a non-existent access rule should return a 404
self.do_request(
'show_access_rule', expected_status=exceptions.NotFound,
user_id=self.test_user_id,
access_rule_id=data_utils.rand_uuid_hex())
def test_identity_list_access_rules(self):
# system admin cannot create app creds and therefore cannot create
# access rules, so skip listing of own access rule
# list other user's access rules
self.do_request('list_access_rules', user_id=self.test_user_id)
def test_identity_delete_access_rule(self):
# system admin cannot create app creds and therefore cannot create
# access rules, so skip deletion of own access rule
# delete other user's access rules
app_cred_client = self.admin_client.application_credentials_client
app_cred_client.delete_application_credential(
user_id=self.test_user_id,
application_credential_id=self.app_cred_id)
self.do_request(
'delete_access_rule', expected_status=204,
user_id=self.test_user_id, access_rule_id=self.access_rule_id)
# deleting a non-existent access rule should return a 404
self.do_request(
'delete_access_rule', expected_status=exceptions.NotFound,
user_id=self.test_user_id,
access_rule_id=data_utils.rand_uuid_hex())
class SystemMemberTests(SystemAdminTests):
credentials = ['system_member', 'system_admin']
def test_identity_delete_access_rule(self):
app_cred_client = self.admin_client.application_credentials_client
app_cred_client.delete_application_credential(
user_id=self.test_user_id,
application_credential_id=self.app_cred_id)
self.do_request(
'delete_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_id, access_rule_id=self.access_rule_id)
# retrieving a non-existent access rule should return a 404
self.do_request(
'show_access_rule', expected_status=exceptions.NotFound,
user_id=self.test_user_id,
access_rule_id=data_utils.rand_uuid_hex())
class SystemReaderTests(SystemMemberTests):
credentials = ['system_reader', 'system_admin']
class DomainAdminTests(IdentityV3RbacAccessRuleTest, base.BaseIdentityTest):
# Domain admins cannot create their own app creds (app creds can only be
# scoped to projects) and domain admins have no special privileges over the
# app creds own by users in their domains.
credentials = ['domain_admin', 'system_admin']
@classmethod
def setup_clients(cls):
super(DomainAdminTests, cls).setup_clients()
own_domain_id = cls.persona.credentials.domain_id
cls.test_client_1, cls.test_user_1 = cls.setup_user_client(
domain_id=own_domain_id)
def setUp(self):
super(DomainAdminTests, self).setUp()
self.other_domain_id = self.admin_client.domains_client.create_domain(
name=data_utils.rand_name())['domain']['id']
self.addCleanup(self.admin_client.domains_client.delete_domain,
self.other_domain_id)
self.addCleanup(self.admin_client.domains_client.update_domain,
domain_id=self.other_domain_id, enabled=False)
self.test_client_2, self.test_user_2 = self.setup_user_client(
domain_id=self.other_domain_id)
client = self.test_client_1.application_credentials_client
app_cred_1 = client.create_application_credential(
user_id=self.test_user_1, **self.app_cred()
)['application_credential']
self.access_rule_1 = app_cred_1['access_rules'][0]['id']
self.addCleanup(
self.test_client_1.access_rules_client.delete_access_rule,
self.test_user_1,
self.access_rule_1)
self.addCleanup(
client.delete_application_credential,
self.test_user_1,
app_cred_1['id'])
client = self.test_client_2.application_credentials_client
app_cred_2 = client.create_application_credential(
user_id=self.test_user_2, **self.app_cred()
)['application_credential']
self.access_rule_2 = app_cred_2['access_rules'][0]['id']
self.addCleanup(
self.test_client_2.access_rules_client.delete_access_rule,
self.test_user_2,
self.access_rule_2)
self.addCleanup(
client.delete_application_credential,
self.test_user_2,
app_cred_2['id'])
def test_identity_get_access_rule(self):
# accessing access rules should be forbidden no matter whether the
# owner is in the domain or outside of it
# retrieve access rule from user in own domain
self.do_request(
'show_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_1, access_rule_id=self.access_rule_1)
# retrieve access rule from user in other domain
self.do_request(
'show_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_2, access_rule_id=self.access_rule_2)
# retrieving a non-existent access rule should return a 403
self.do_request(
'show_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_1,
access_rule_id=data_utils.rand_uuid_hex())
self.do_request(
'show_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_2,
access_rule_id=data_utils.rand_uuid_hex())
def test_identity_list_access_rules(self):
# listing access rules should be forbidden no matter whether the
# owner is in the domain or outside of it
self.do_request(
'list_access_rules', expected_status=exceptions.Forbidden,
user_id=self.test_user_1)
self.do_request(
'list_access_rules', expected_status=exceptions.Forbidden,
user_id=self.test_user_2)
def test_identity_delete_access_rule(self):
# deleting access rules should be forbidden no matter whether the
# owner is in the domain or outside of it
# delete access rule from user in own domain
self.do_request(
'delete_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_1, access_rule_id=self.access_rule_1)
# delete access rule from user in other domain
self.do_request(
'delete_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_2, access_rule_id=self.access_rule_2)
# deleting a non-existent access rule should return a 403
self.do_request(
'delete_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_1,
access_rule_id=data_utils.rand_uuid_hex())
self.do_request(
'delete_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_2,
access_rule_id=data_utils.rand_uuid_hex())
class DomainMemberTests(DomainAdminTests):
credentials = ['domain_member', 'system_admin']
class DomainReaderTests(DomainAdminTests):
credentials = ['domain_reader', 'system_admin']
class ProjectAdminTests(IdentityV3RbacAccessRuleTest, base.BaseIdentityTest):
credentials = ['project_admin', 'system_admin']
@classmethod
def setup_clients(cls):
super(ProjectAdminTests, cls).setup_clients()
cls.test_user_client, cls.test_user_id = cls.setup_user_client()
def setUp(self):
super(ProjectAdminTests, self).setUp()
app_cred_client = self.persona.application_credentials_client
user_id = self.persona.credentials.user_id
self.app_cred_1 = app_cred_client.create_application_credential(
user_id, **self.app_cred())['application_credential']
self.access_rule_1 = self.app_cred_1['access_rules'][0]['id']
def try_delete_own_app_cred(id):
app_cred_client = self.persona.application_credentials_client
try:
app_cred_client.delete_application_credential(
self.persona.credentials.user_id, id)
except exceptions.NotFound:
pass
def try_delete_own_access_rule(id):
try:
self.persona.access_rules_client.delete_access_rule(
self.persona.credentials.user_id, id)
except exceptions.NotFound:
pass
self.addCleanup(try_delete_own_access_rule, self.access_rule_1)
self.addCleanup(try_delete_own_app_cred, self.app_cred_1['id'])
app_cred_client = self.test_user_client.application_credentials_client
self.app_cred_2 = app_cred_client.create_application_credential(
self.test_user_id, **self.app_cred())['application_credential']
self.access_rule_2 = self.app_cred_2['access_rules'][0]['id']
self.addCleanup(
self.test_user_client.access_rules_client.delete_access_rule,
self.test_user_id, self.access_rule_2)
self.addCleanup(
app_cred_client.delete_application_credential,
self.test_user_id, self.app_cred_2['id'])
def test_identity_get_access_rule(self):
# should be able to access own credential
self.do_request(
'show_access_rule',
user_id=self.persona.credentials.user_id,
access_rule_id=self.access_rule_1)
# retrieving non-existent access rule for self should return 404
self.do_request(
'show_access_rule', expected_status=exceptions.NotFound,
user_id=self.persona.credentials.user_id,
access_rule_id=data_utils.rand_uuid_hex())
# should not be able to access another user's credential
self.do_request(
'show_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_id, access_rule_id=self.access_rule_2)
# retrieving non-existent access rule for other user should return 403
self.do_request(
'show_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_id,
access_rule_id=data_utils.rand_uuid_hex())
def test_identity_list_access_rules(self):
# should be able to list own credentials
self.do_request(
'list_access_rules', user_id=self.persona.credentials.user_id)
# should not be able to list another user's credentials
self.do_request(
'list_access_rules', expected_status=exceptions.Forbidden,
user_id=self.test_user_id)
def test_identity_delete_access_rule(self):
# should be able to delete own credential
app_cred_client = self.persona.application_credentials_client
app_cred_client.delete_application_credential(
user_id=self.persona.credentials.user_id,
application_credential_id=self.app_cred_1['id'])
self.do_request(
'delete_access_rule', expected_status=204,
user_id=self.persona.credentials.user_id,
access_rule_id=self.access_rule_1)
# deleting non-existent access rule for self should return 404
self.do_request(
'delete_access_rule', expected_status=exceptions.NotFound,
user_id=self.persona.credentials.user_id,
access_rule_id=data_utils.rand_uuid_hex())
# should not be able to delete another user's credential
self.do_request(
'delete_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_id, access_rule_id=self.access_rule_2)
# deleting non-existent access rule for other user should return 403
self.do_request(
'delete_access_rule', expected_status=exceptions.Forbidden,
user_id=self.test_user_id,
access_rule_id=data_utils.rand_uuid_hex())
class ProjectMemberTests(ProjectAdminTests):
credentials = ['project_member', 'system_admin']
class ProjectReaderTests(ProjectAdminTests):
credentials = ['project_reader', 'system_admin']

+ 551
- 0
keystone_tempest_plugin/tests/rbac/v3/test_application_credential.py View File

@ -0,0 +1,551 @@
# Copyright 2020 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import abc
from tempest.api.identity import base
from tempest import clients
from tempest.lib import auth
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
from keystone_tempest_plugin.tests.rbac.v3 import base as rbac_base
class IdentityV3RbacApplicationCredentialTest(
rbac_base.IdentityV3RbacBaseTests, metaclass=abc.ABCMeta):
@classmethod
def setup_clients(cls):
super(IdentityV3RbacApplicationCredentialTest, cls).setup_clients()
cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
cls.client = cls.persona.application_credentials_client
cls.admin_client = cls.os_system_admin
@classmethod
def setup_user_client(cls, domain_id=None):
"""Set up project user with its own client.
This is to enable the project user to create its own app cred.
Returns a client object and the user's ID.
"""
user_dict = {
'name': data_utils.rand_name('user'),
'password': data_utils.rand_password(),
}
if domain_id:
user_dict['domain_id'] = domain_id
user_id = cls.admin_client.users_v3_client.create_user(
**user_dict)['user']['id']
def try_cleanup_user():
# if domain is cleaned up first, user will already be deleted
try:
cls.admin_client.users_v3_client.delete_user(user_id)
except exceptions.NotFound:
pass
cls.addClassResourceCleanup(try_cleanup_user)
project_id = cls.admin_client.projects_client.create_project(
data_utils.rand_name())['project']['id']
cls.addClassResourceCleanup(
cls.admin_client.projects_client.delete_project, project_id)
member_role_id = cls.admin_client.roles_v3_client.list_roles(
name='member')['roles'][0]['id']
cls.admin_client.roles_v3_client.create_user_role_on_project(
project_id, user_id, member_role_id)
creds = auth.KeystoneV3Credentials(
user_id=user_id,
password=user_dict['password'],
project_id=project_id)
auth_provider = clients.get_auth_provider(creds)
creds = auth_provider.fill_credentials()
client = clients.Manager(credentials=creds)
return client, user_id
def app_cred(self):
app_cred = {}
app_cred['name'] = data_utils.rand_name('app_cred')
return app_cred
@abc.abstractmethod
def test_identity_create_application_credential(self):
"""Test identity:create_application_credential policy.
This test must check:
* whether the persona can create an application credential for
themself
* whether the persona can create an application credential for
another user
"""
pass
@abc.abstractmethod
def test_identity_get_application_credential(self):
"""Test identity:get_application_credential policy.
This test must check:
* whether the persona can get their own application credential
* whether the persona can get an application credential for another
user
* whether the persona can get an application credential for a user in
another domain (if applicable)
* whether the persona can get an application credential for a user in
their own domain (if applicable)
* whether the persona can get an application credential that does not
exist
"""
pass
@abc.abstractmethod
def test_identity_list_application_credentials(self):
"""Test identity:list_application_credentials policy.
This test must check:
* whether the persona can list all application credentials for
themself
* whether the persona can list all application credentials for
another user
* whether the persona can list application credentials for a user in
their own domain
* whether the persona can list application credentials for a user in
another domain
"""
pass
@abc.abstractmethod
def test_identity_delete_application_credential(self):
"""Test identity:delete_application_credential policy.
This test must check
* whether the persona can delete their own application credential
* whether the persona can delete an application credential for
another user
* whether the persona can delete an application credential for a user
in another domain (if applicable)
* whether the persona can delete an application credential for a user
in their own domain (if applicable)
* whether the persona can delete an application credential that does
not exist
"""
pass
class SystemAdminTests(
IdentityV3RbacApplicationCredentialTest, base.BaseIdentityTest):
credentials = ['system_admin']
@classmethod
def setup_clients(cls):
super(SystemAdminTests, cls).setup_clients()
cls.test_user_client, cls.test_user_id = cls.setup_user_client()
def test_identity_create_application_credential(self):
# Creating an application credential requires a project ID in the
# token, therefore system-scoped users cannot create app creds.
raise self.skipException(
"Skipping identity:create_application_credential test for "
"system user")
def test_identity_get_application_credential(self):
# Creating an application credential requires a project ID in the
# token, therefore system-scoped users cannot create app creds, so skip
# check for showing user's own app creds
# retrieve other user's app cred
user_app_cred_client = \
self.test_user_client.application_credentials_client
app_cred = user_app_cred_client.create_application_credential(
user_id=self.test_user_id, **self.app_cred()
)['application_credential']
self.addCleanup(
user_app_cred_client.delete_application_credential,
self.test_user_id,
app_cred['id'])
self.do_request(
'show_application_credential',
user_id=self.test_user_id,
application_credential_id=app_cred['id'])
# retrieve app cred that does not exist
self.do_request(
'show_application_credential',
expected_status=exceptions.NotFound,
user_id=self.test_user_id,
application_credential_id=data_utils.rand_uuid_hex())
def test_identity_list_application_credentials(self):
# Creating an application credential requires a project ID in the
# token, therefore system-scoped users cannot create app creds, so skip
# check for listing user's own app creds
# list other user's app creds
user_app_cred_client = \
self.test_user_client.application_credentials_client
app_cred = user_app_cred_client.create_application_credential(
user_id=self.test_user_id, **self.app_cred()
)['application_credential']
self.addCleanup(
user_app_cred_client.delete_application_credential,
self.test_user_id,
app_cred['id'])
resp = self.do_request(
'list_application_credentials',
user_id=self.test_user_id)
self.assertEqual(
resp['application_credentials'][0]['id'],
app_cred['id'])
def test_identity_delete_application_credential(self):
# Creating an application credential requires a project ID in the
# token, therefore system-scoped users cannot create app creds, so skip
# check for deleting user's own app creds
# delete other user's app cred
user_app_cred_client = \
self.test_user_client.application_credentials_client
app_cred = user_app_cred_client.create_application_credential(
user_id=self.test_user_id, **self.app_cred()
)['application_credential']
self.do_request(
'delete_application_credential',
expected_status=204,
user_id=self.test_user_id,
application_credential_id=app_cred['id'])
# delete app cred that does not exist
self.do_request(
'delete_application_credential',
expected_status=exceptions.NotFound,
user_id=self.test_user_id,
application_credential_id=data_utils.rand_uuid_hex())
class SystemMemberTests(SystemAdminTests):
credentials = ['system_member', 'system_admin']
def test_identity_delete_application_credential(self):
# Creating an application credential requires a project ID in the
# token, therefore system-scoped users cannot create app creds, so skip
# check for deleting user's own app creds
# delete other user's app cred
user_app_cred_client = \
self.test_user_client.application_credentials_client
app_cred = user_app_cred_client.create_application_credential(
user_id=self.test_user_id, **self.app_cred()
)['application_credential']
self.addCleanup(
user_app_cred_client.delete_application_credential,
self.test_user_id,
app_cred['id'])
self.do_request(
'delete_application_credential',
expected_status=exceptions.Forbidden,
user_id=self.test_user_id,
application_credential_id=app_cred['id'])
# delete app cred that does not exist
self.do_request(
'delete_application_credential',
expected_status=exceptions.Forbidden,
user_id=self.test_user_id,
application_credential_id=data_utils.rand_uuid_hex())
class SystemReaderTests(SystemMemberTests):
credentials = ['system_reader', 'system_admin']
class DomainAdminTests(
IdentityV3RbacApplicationCredentialTest, base.BaseIdentityTest):
# Domain admins cannot create their own app creds (app creds can only be
# scoped to projects) and domain admins have no special privileges over the
# app creds own by users in their domains.
credentials = ['domain_admin', 'system_admin']
@classmethod
def setup_clients(cls):
super(DomainAdminTests, cls).setup_clients()
own_domain_id = cls.persona.credentials.domain_id
cls.test_client_1, cls.test_user_1 = cls.setup_user_client(
domain_id=own_domain_id)
def setUp(self):
super(DomainAdminTests, self).setUp()
self.other_domain_id = self.admin_client.domains_client.create_domain(
name=data_utils.rand_name())['domain']['id']
self.addCleanup(self.admin_client.domains_client.delete_domain,
self.other_domain_id)
self.addCleanup(self.admin_client.domains_client.update_domain,
domain_id=self.other_domain_id, enabled=False)
self.test_client_2, self.test_user_2 = self.setup_user_client(
domain_id=self.other_domain_id)
client = self.test_client_1.application_credentials_client
self.app_cred_1 = client.create_application_credential(
user_id=self.test_user_1, **self.app_cred()
)['application_credential']
self.addCleanup(
client.delete_application_credential,
self.test_user_1,
self.app_cred_1['id'])
client = self.test_client_2.application_credentials_client
self.app_cred_2 = client.create_application_credential(
user_id=self.test_user_2, **self.app_cred()
)['application_credential']
self.addCleanup(
client.delete_application_credential,
self.test_user_2,
self.app_cred_2['id'])
def test_identity_create_application_credential(self):
# Creating an application credential requires a project ID in the
# token, therefore system-scoped users cannot create app creds.
raise self.skipException(
"Skipping identity:create_application_credential test for "
"domain user")
def test_identity_get_application_credential(self):
# Creating an application credential requires a project ID in the
# token, therefore domain-scoped users cannot create app creds, so skip
# check for showing user's own app creds
# accessing application credentials should be forbidden no matter
# whether the owner is in the domain or outside of it
# retrieve app cred from user in own domain
self.do_request(
'show_application_credential',
expected_status=exceptions.Forbidden,
user_id=self.test_user_1,
application_credential_id=self.app_cred_1['id'])
# retrieve app cred from user in other domain
self.do_request(
'show_application_credential',
expected_status=exceptions.Forbidden,
user_id=self.test_user_2,
application_credential_id=self.app_cred_2['id'])
# retrieve app cred that does not exist
self.do_request(
'show_application_credential',
expected_status=exceptions.Forbidden,
user_id=self.test_user_1,
application_credential_id=data_utils.rand_uuid_hex())
def test_identity_list_application_credentials(self):
# Creating an application credential requires a project ID in the
# token, therefore domain-scoped users cannot create app creds, so skip
# check for listing user's own app creds
# listing application credentials should be forbidden no matter
# whether the owner is in the domain or outside of it
# list app creds from user in own domain
self.do_request(
'list_application_credentials',
expected_status=exceptions.Forbidden,
user_id=self.test_user_1)
# list app creds from user in other domain
self.do_request(
'list_application_credentials',
expected_status=exceptions.Forbidden,
user_id=self.test_user_2)
def test_identity_delete_application_credential(self):
# Creating an application credential requires a project ID in the
# token, therefore domain-scoped users cannot create app creds, so skip
# check for deleting user's own app creds
# deleting application credentials should be forbidden no matter
# whether the owner is in the domain or outside of it
# delete app cred from user in own domain
self.do_request(
'delete_application_credential',
expected_status=exceptions.Forbidden,
user_id=self.test_user_1,
application_credential_id=self.app_cred_1['id'])
# delete app cred from user in other domain
self.do_request(
'delete_application_credential',
expected_status=exceptions.Forbidden,
user_id=self.test_user_2,
application_credential_id=self.app_cred_2['id'])
# delete app cred that does not exist
self.do_request(
'delete_application_credential',
expected_status=exceptions.Forbidden,
user_id=self.test_user_1,
application_credential_id=data_utils.rand_uuid_hex())
class DomainMemberTests(DomainAdminTests):
credentials = ['domain_member', 'system_admin']
class DomainReaderTests(DomainAdminTests):
credentials = ['domain_reader', 'system_admin']
class ProjectAdminTests(IdentityV3RbacApplicationCredentialTest,
base.BaseIdentityTest):
credentials = ['project_admin', 'system_admin']
@classmethod
def setup_clients(cls):
super(ProjectAdminTests, cls).setup_clients()
cls.test_user_client, cls.test_user_id = cls.setup_user_client()
def test_identity_create_application_credential(self):
# user can create their own app cred
user_id = self.persona.credentials.user_id
resp = self.do_request(
'create_application_credential',
expected_status=201,
user_id=user_id,
**self.app_cred())['application_credential']
self.addCleanup(
self.client.delete_application_credential,
user_id, resp['id'])
# user cannot create app cred for another user
user_id = self.test_user_id
self.do_request(
'create_application_credential',
expected_status=exceptions.Forbidden,
user_id=user_id,
**self.app_cred())
def test_identity_get_application_credential(self):
# user can retrieve their own app cred
user_id = self.persona.credentials.user_id
app_cred = self.client.create_application_credential(
user_id=user_id, **self.app_cred())['application_credential']
self.addCleanup(
self.client.delete_application_credential,
user_id=user_id, application_credential_id=app_cred['id'])
self.do_request(
'show_application_credential',
user_id=user_id, application_credential_id=app_cred['id'])
# retrieving non-existent app cred for self should return 404
self.do_request(
'show_application_credential',
expected_status=exceptions.NotFound,
user_id=user_id,
application_credential_id=data_utils.rand_uuid_hex())
# user cannot retrieve another user's app cred
user_id = self.test_user_id
client = self.test_user_client.application_credentials_client
app_cred = client.create_application_credential(
user_id=user_id, **self.app_cred())['application_credential']
self.addCleanup(
client.delete_application_credential,
user_id=user_id, application_credential_id=app_cred['id'])
self.do_request(
'show_application_credential',
expected_status=exceptions.Forbidden,
user_id=user_id, application_credential_id=app_cred['id'])
# retrieving non-existent app cred for another user should return 403
self.do_request(
'show_application_credential',
expected_status=exceptions.Forbidden,
user_id=user_id,
application_credential_id=data_utils.rand_uuid_hex())
def test_identity_list_application_credentials(self):
# user can list their own app creds
user_id = self.persona.credentials.user_id
app_cred = self.client.create_application_credential(
user_id=user_id, **self.app_cred())['application_credential']
self.addCleanup(
self.client.delete_application_credential,
user_id=user_id, application_credential_id=app_cred['id'])
self.do_request(
'list_application_credentials', user_id=user_id)
# user cannot list another user's app creds
user_id = self.test_user_id
client = self.test_user_client.application_credentials_client
app_cred = client.create_application_credential(
user_id=user_id, **self.app_cred())['application_credential']
self.addCleanup(
client.delete_application_credential,
user_id=user_id, application_credential_id=app_cred['id'])
self.do_request(
'list_application_credentials',
expected_status=exceptions.Forbidden, user_id=user_id)
def test_identity_delete_application_credential(self):
# user can delete their own app cred
user_id = self.persona.credentials.user_id
app_cred = self.client.create_application_credential(
user_id=user_id, **self.app_cred())['application_credential']
self.do_request(
'delete_application_credential',
expected_status=204,
user_id=user_id, application_credential_id=app_cred['id'])
# deleting non-existent app cred for self should return 404
self.do_request(
'delete_application_credential',
expected_status=exceptions.NotFound,
user_id=user_id,
application_credential_id=data_utils.rand_uuid_hex())
# user cannot delete another user's app cred
user_id = self.test_user_id
client = self.test_user_client.application_credentials_client
app_cred = client.create_application_credential(
user_id=user_id, **self.app_cred())['application_credential']
self.addCleanup(
client.delete_application_credential,
user_id=user_id, application_credential_id=app_cred['id'])
self.do_request(
'delete_application_credential',
expected_status=exceptions.Forbidden,
user_id=user_id, application_credential_id=app_cred['id'])
# deleting non-existent app cred for another user should return 403
self.do_request(
'delete_application_credential',
expected_status=exceptions.Forbidden,
user_id=user_id,
application_credential_id=data_utils.rand_uuid_hex())
class ProjectMemberTests(ProjectAdminTests):
credentials = ['project_member', 'system_admin']
class ProjectReaderTests(ProjectAdminTests):
credentials = ['project_reader', 'system_admin']

+ 196
- 0
keystone_tempest_plugin/tests/rbac/v3/test_consumer.py View File

@ -0,0 +1,196 @@
# Copyright 2020 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import abc
from tempest.api.identity import base
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
from keystone_tempest_plugin.tests.rbac.v3 import base as rbac_base
class IdentityV3RbacOauth1ConsumerTest(rbac_base.IdentityV3RbacBaseTests,
metaclass=abc.ABCMeta):
@classmethod
def setup_clients(cls):
super(IdentityV3RbacOauth1ConsumerTest, cls).setup_clients()
cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
cls.client = cls.persona.oauth_consumers_client
cls.admin_client = cls.os_system_admin.oauth_consumers_client
def consumer(self):
return {"description": data_utils.arbitrary_string()}
@abc.abstractmethod
def test_identity_create_consumer(self):
"""Test identity:create_consumer policy.
This test must check:
* whether the persona can create a consumer
"""
pass
@abc.abstractmethod
def test_identity_get_consumer(self):
"""Test identity:get_consumer policy.
This test must check:
* whether the persona can get a consumer
"""
pass
@abc.abstractmethod
def test_identity_list_consumers(self):
"""Test identity:list_consumers policy.
This test must check:
* whether the persona can list all consumers
"""
pass
@abc.abstractmethod
def test_identity_update_consumer(self):
"""Test identity:update_consumer policy.
This test must check:
* whether the persona can update a
"""
pass
@abc.abstractmethod
def test_identity_delete_consumer(self):
"""Test identity:delete_consumer policy.
This test must check
* whether the persona can delete a consumer
"""
pass
class SystemAdminTests(
IdentityV3RbacOauth1ConsumerTest, base.BaseIdentityTest):
credentials = ['system_admin']
def test_identity_create_consumer(self):
resp = self.do_request('create_consumer',
expected_status=201,
**self.consumer())
self.addCleanup(self.client.delete_consumer,
resp['consumer']['id'])
def test_identity_get_consumer(self):
consumer = self.admin_client.create_consumer(
**self.consumer())['consumer']
self.addCleanup(self.admin_client.delete_consumer, consumer['id'])
resp = self.do_request('show_consumer', consumer_id=consumer['id'])
self.assertEqual(resp['consumer']['id'], consumer['id'])
def test_identity_list_consumers(self):
consumer = self.admin_client.create_consumer(
**self.consumer())['consumer']
self.addCleanup(self.admin_client.delete_consumer, consumer['id'])
resp = self.do_request('list_consumers')
self.assertIn(consumer['id'], set(c['id'] for c in resp['consumers']))
def test_identity_update_consumer(self):
consumer = self.client.create_consumer(**self.consumer())['consumer']
self.addCleanup(self.client.delete_consumer, consumer['id'])
self.do_request('update_consumer',
consumer_id=consumer['id'],
description=data_utils.arbitrary_string())
def test_identity_delete_consumer(self):
consumer = self.client.create_consumer(**self.consumer())['consumer']
self.do_request('delete_consumer',
expected_status=204,
consumer_id=consumer['id'])
class SystemMemberTests(SystemAdminTests):
credentials = ['system_member', 'system_admin']
def test_identity_create_consumer(self):
self.do_request('create_consumer',
expected_status=exceptions.Forbidden,
**self.consumer())
def test_identity_update_consumer(self):
consumer = self.admin_client.create_consumer(
**self.consumer())['consumer']
self.addCleanup(self.admin_client.delete_consumer, consumer['id'])
self.do_request('update_consumer',
expected_status=exceptions.Forbidden,
consumer_id=consumer['id'],
description=data_utils.arbitrary_string())
def test_identity_delete_consumer(self):
consumer = self.admin_client.create_consumer(
**self.consumer())['consumer']
self.do_request('delete_consumer',
expected_status=exceptions.Forbidden,
consumer_id=consumer['id'])
class SystemReaderTests(SystemMemberTests):
credentials = ['system_reader', 'system_admin']
class DomainAdminTests(SystemMemberTests):
credentials = ['domain_admin', 'system_admin']
def test_identity_get_consumer(self):
consumer = self.admin_client.create_consumer(
**self.consumer())['consumer']
self.addCleanup(self.admin_client.delete_consumer, consumer['id'])
self.do_request('show_consumer',
expected_status=exceptions.Forbidden,
consumer_id=consumer['id'])
def test_identity_list_consumers(self):
consumer = self.admin_client.create_consumer(
**self.consumer())['consumer']
self.addCleanup(self.admin_client.delete_consumer, consumer['id'])
self.do_request('list_consumers',
expected_status=exceptions.Forbidden)
class DomainMemberTests(DomainAdminTests):
credentials = ['domain_member', 'system_admin']
class DomainReaderTests(DomainMemberTests):
credentials = ['domain_reader', 'system_admin']
class ProjectAdminTests(DomainReaderTests):
credentials = ['project_admin', 'system_admin']
class ProjectMemberTests(ProjectAdminTests):
credentials = ['project_member', 'system_admin']
class ProjectReaderTests(ProjectAdminTests):
credentials = ['project_reader', 'system_admin']

+ 490
- 0
keystone_tempest_plugin/tests/rbac/v3/test_credential.py View File

@ -0,0 +1,490 @@
# Copyright 2020 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import abc
from tempest.api.identity import base
from tempest import clients
from tempest.lib import auth
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
from keystone_tempest_plugin.tests.rbac.v3 import base as rbac_base
class IdentityV3RbacCredentialTest(rbac_base.IdentityV3RbacBaseTests,
metaclass=abc.ABCMeta):
@classmethod
def setup_clients(cls):
super(IdentityV3RbacCredentialTest, cls).setup_clients()
cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
cls.client = cls.persona.credentials_client
cls.admin_client = cls.os_system_admin
cls.admin_credentials_client = cls.admin_client.credentials_client
# personas in own or other domains
own_domain_id = cls.persona.credentials.domain_id
cls.test_client_1, cls.test_user_1 = cls.setup_user_client(
domain_id=own_domain_id)
cls.other_domain_id = cls.admin_client.domains_client.create_domain(
name=data_utils.rand_name())['domain']['id']
cls.addClassResourceCleanup(
cls.admin_client.domains_client.delete_domain, cls.other_domain_id)
cls.addClassResourceCleanup(
cls.admin_client.domains_client.update_domain,
domain_id=cls.other_domain_id, enabled=False)
cls.test_client_2, cls.test_user_2 = cls.setup_user_client(
domain_id=cls.other_domain_id)
@classmethod
def setup_user_client(cls, domain_id=None):
"""Set up project user with its own client.
This is to enable the project user to create its own credential.
Returns a client object and the user's ID.
"""
user_dict = {
'name': data_utils.rand_name('user'),
'password': data_utils.rand_password(),
}
if domain_id:
user_dict['domain_id'] = domain_id
user_id = cls.admin_client.users_v3_client.create_user(
**user_dict)['user']['id']
def try_cleanup_user():
# if domain is cleaned up first, user will already be deleted
try:
cls.admin_client.users_v3_client.delete_user(user_id)
except exceptions.NotFound:
pass
cls.addClassResourceCleanup(try_cleanup_user)
project_id = cls.admin_client.projects_client.create_project(
data_utils.rand_name())['project']['id']
cls.addClassResourceCleanup(
cls.admin_client.projects_client.delete_project, project_id)
member_role_id = cls.admin_client.roles_v3_client.list_roles(
name='member')['roles'][0]['id']
cls.admin_client.roles_v3_client.create_user_role_on_project(
project_id, user_id, member_role_id)
creds = auth.KeystoneV3Credentials(
user_id=user_id,
password=user_dict['password'],
project_id=project_id)
auth_provider = clients.get_auth_provider(creds)
creds = auth_provider.fill_credentials()
client = clients.Manager(credentials=creds)
return client, user_id
def credential(self, user_id):
cred = {
'blob': data_utils.rand_uuid_hex(),
'type': data_utils.rand_uuid_hex(),
'user_id': user_id,
}
return cred
@abc.abstractmethod
def test_identity_create_credential(self):
"""Test identity:create_credential policy.
This test must check:
* whether the persona can create a credential for themself
* whether the persona can create acredential for another user in
their own domain
* whether the persona can create acredential for another user in
another domain
"""
pass
@abc.abstractmethod
def test_identity_get_credential(self):
"""Test identity:get_credential policy.
This test must check:
* whether the persona can get their own credential
* whether the persona can get a credential for a user in another
domain
* whether the persona can get a credential for a user in their own
domain
* whether the persona can get a credential that does not exist
"""
pass
@abc.abstractmethod
def test_identity_list_credentials(self):
"""Test identity:list_credentials policy.
This test must check:
* whether the persona can list all credentials for themself
* whether the persona can list credentials for a user in their own
domain
* whether the persona can list credentials for a user in another
domain
"""
pass
@abc.abstractmethod
def test_identity_update_credential(self):
"""Test identity:update_credential policy.
This test must check:
* whether the persona can update their own credential
* whether the persona can update a credential for a user in another
domain
* whether the persona can update a credential for a user in their own
domain
* whether the persona can update a credential that does not exist
"""
pass
@abc.abstractmethod
def test_identity_delete_credential(self):
"""Test identity:delete_credential policy.
This test must check
* whether the persona can delete their own credential
* whether the persona can delete a credential for a user in another
domain
* whether the persona can delete a credential for a user in their own
domain
* whether the persona can delete a credential that does not exist
"""
pass
class SystemAdminTests(IdentityV3RbacCredentialTest, base.BaseIdentityTest):
credentials = ['system_admin']
def test_identity_create_credential(self):
# user can create their own credential
user_id = self.persona.credentials.user_id
resp = self.do_request(
'create_credential',
expected_status=201,
**self.credential(user_id=user_id))['credential']
self.addCleanup(self.client.delete_credential, resp['id'])
# user can create credential for other user in own domain
resp = self.do_request(
'create_credential',
expected_status=201,
**self.credential(user_id=self.test_user_1))['credential']
self.addCleanup(self.client.delete_credential, resp['id'])
# user can create credential for other user in other domain
resp = self.do_request(
'create_credential',
expected_status=201,
**self.credential(user_id=self.test_user_2))['credential']
self.addCleanup(self.client.delete_credential, resp['id'])
def test_identity_get_credential(self):
# user can get their own credential, credential for user in own domain,
# or credential for user in other domain
user_id = self.persona.credentials.user_id
for u in [user_id, self.test_user_1, self.test_user_2]:
cred = self.admin_credentials_client.create_credential(
**self.credential(user_id=u))['credential']
self.addCleanup(
self.admin_credentials_client.delete_credential, cred['id'])
self.do_request('show_credential', credential_id=cred['id'])
# non-existent credential is Not Found
self.do_request(
'show_credential',
expected_status=exceptions.NotFound,
credential_id=data_utils.rand_uuid_hex())
def test_identity_list_credentials(self):
# user can list their own credentials, credentials for user in own
# domain, or credentials for user in other domain
user_id = self.persona.credentials.user_id
for u in [user_id, self.test_user_1, self.test_user_2]:
cred = self.admin_credentials_client.create_credential(
**self.credential(user_id=u))['credential']
self.addCleanup(
self.admin_credentials_client.delete_credential, cred['id'])
resp = self.do_request('list_credentials')['credentials']
self.assertIn(cred['id'], [c['id'] for c in resp])
def test_identity_update_credential(self):
# user can update their own credential, credential for user in own
# domain, or credential for user in other domain
user_id = self.persona.credentials.user_id
for u in [user_id, self.test_user_1, self.test_user_2]:
cred = self.credential(user_id=u)