Add Access Rules tests

Access rules for application credentials were added in the Train release
of keystone. This change adds related CRUD tests for access rules. See
the API reference for additional information[1].

[1] https://docs.openstack.org/api-ref/identity/v3/index.html#application-credentials

Change-Id: Ifd4ff2245277c2c57f5ccf450923434c0277a724
This commit is contained in:
Colleen Murphy 2019-12-17 16:31:14 -08:00
parent 3e42d81b72
commit d2cbd3ad4c
8 changed files with 284 additions and 3 deletions

View File

@ -192,6 +192,7 @@ class BaseIdentityV3Test(BaseIdentityTest):
cls.os_primary.identity_versions_v3_client
cls.non_admin_app_creds_client = \
cls.os_primary.application_credentials_client
cls.non_admin_access_rules_client = cls.os_primary.access_rules_client
class BaseIdentityV3AdminTest(BaseIdentityV3Test):

View File

@ -0,0 +1,84 @@
# Copyright 2019 SUSE LLC
#
# All Rights Reserved.
#
# 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.api.identity import base
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
CONF = config.CONF
class AccessRulesV3Test(base.BaseIdentityV3Test):
@classmethod
def skip_checks(cls):
super(AccessRulesV3Test, cls).skip_checks()
if not CONF.identity_feature_enabled.access_rules:
raise cls.skipException("Application credential access rules are "
"not available in this environment")
@classmethod
def resource_setup(cls):
super(AccessRulesV3Test, cls).resource_setup()
cls.user_id = cls.os_primary.credentials.user_id
cls.project_id = cls.os_primary.credentials.project_id
def setUp(self):
super(AccessRulesV3Test, self).setUp()
ac = self.non_admin_app_creds_client
access_rules = [
{
"path": "/v2.1/servers/*/ips",
"method": "GET",
"service": "compute"
}
]
self.app_cred = ac.create_application_credential(
self.user_id,
name=data_utils.rand_name('application_credential'),
access_rules=access_rules
)['application_credential']
@decorators.idempotent_id('2354c498-5119-4ba5-9f0d-44f16f78fb0e')
def test_list_access_rules(self):
ar = self.non_admin_access_rules_client.list_access_rules(self.user_id)
self.assertEqual(1, len(ar['access_rules']))
@decorators.idempotent_id('795dd507-ca1e-40e9-ba90-ff0a08689ba4')
def test_show_access_rule(self):
access_rule_id = self.app_cred['access_rules'][0]['id']
self.non_admin_access_rules_client.show_access_rule(
self.user_id, access_rule_id)
@decorators.idempotent_id('278757e9-e193-4bf8-adf2-0b0a229a17d0')
def test_delete_access_rule(self):
access_rule_id = self.app_cred['access_rules'][0]['id']
app_cred_id = self.app_cred['id']
self.assertRaises(
lib_exc.Forbidden,
self.non_admin_access_rules_client.delete_access_rule,
self.user_id,
access_rule_id)
self.non_admin_app_creds_client.delete_application_credential(
self.user_id, app_cred_id)
ar = self.non_admin_access_rules_client.list_access_rules(self.user_id)
self.assertEqual(1, len(ar['access_rules']))
self.non_admin_access_rules_client.delete_access_rule(
self.user_id, access_rule_id)
ar = self.non_admin_access_rules_client.list_access_rules(self.user_id)
self.assertEqual(0, len(ar['access_rules']))

View File

@ -19,8 +19,11 @@ import datetime
from oslo_utils import timeutils
from tempest.api.identity import base
from tempest import config
from tempest.lib import decorators
CONF = config.CONF
class ApplicationCredentialsV3Test(base.BaseApplicationCredentialsV3Test):
@ -62,6 +65,24 @@ class ApplicationCredentialsV3Test(base.BaseApplicationCredentialsV3Test):
expires_str = expires_at.isoformat()
self.assertEqual(expires_str, app_cred['expires_at'])
@decorators.idempotent_id('529936eb-aa5d-463d-9f79-01c113d3b88f')
def test_create_application_credential_access_rules(self):
if not CONF.identity_feature_enabled.access_rules:
raise self.skipException("Application credential access rules are "
"not available in this environment")
access_rules = [
{
"path": "/v2.1/servers/*/ips",
"method": "GET",
"service": "compute"
}
]
app_cred = self.create_application_credential(
access_rules=access_rules)
access_rule_resp = app_cred['access_rules'][0]
access_rule_resp.pop('id')
self.assertDictEqual(access_rules[0], access_rule_resp)
@decorators.idempotent_id('ff0cd457-6224-46e7-b79e-0ada4964a8a6')
def test_list_application_credentials(self):
self.create_application_credential()

View File

@ -203,6 +203,8 @@ class Manager(clients.ServiceClients):
**params_v3)
self.application_credentials_client = \
self.identity_v3.ApplicationCredentialsClient(**params_v3)
self.access_rules_client = \
self.identity_v3.AccessRulesClient(**params_v3)
# Token clients do not use the catalog. They only need default_params.
# They read auth_url, so they should only be set if the corresponding

View File

@ -252,6 +252,11 @@ IdentityFeatureGroup = [
default=False,
help='Does the environment have application credentials '
'enabled?'),
# Access rules for application credentials is a default feature in Train.
# This config option can removed once Stein is EOL.
cfg.BoolOpt('access_rules',
default=False,
help='Does the environment have access rules enabled?'),
cfg.BoolOpt('immutable_user_source',
default=False,
help='Set to True if the environment has a read-only '

View File

@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations under
# the License.
from tempest.lib.services.identity.v3.access_rules_client import \
AccessRulesClient
from tempest.lib.services.identity.v3.application_credentials_client import \
ApplicationCredentialsClient
from tempest.lib.services.identity.v3.catalog_client import \
@ -48,9 +50,10 @@ from tempest.lib.services.identity.v3.trusts_client import TrustsClient
from tempest.lib.services.identity.v3.users_client import UsersClient
from tempest.lib.services.identity.v3.versions_client import VersionsClient
__all__ = ['ApplicationCredentialsClient', 'CatalogClient',
'CredentialsClient', 'DomainsClient', 'DomainConfigurationClient',
'EndPointGroupsClient', 'EndPointsClient', 'EndPointsFilterClient',
__all__ = ['AccessRulesClient', 'ApplicationCredentialsClient',
'CatalogClient', 'CredentialsClient', 'DomainsClient',
'DomainConfigurationClient', 'EndPointGroupsClient',
'EndPointsClient', 'EndPointsFilterClient',
'GroupsClient', 'IdentityClient', 'InheritedRolesClient',
'OAUTHConsumerClient', 'OAUTHTokenClient', 'PoliciesClient',
'ProjectsClient', 'ProjectTagsClient', 'RegionsClient',

View File

@ -0,0 +1,68 @@
# Copyright 2019 SUSE LLC
#
# All Rights Reserved.
#
# 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.
"""
https://docs.openstack.org/api-ref/identity/v3/index.html#application-credentials
"""
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
from tempest.lib.common import rest_client
class AccessRulesClient(rest_client.RestClient):
api_version = "v3"
def show_access_rule(self, user_id, access_rule_id):
"""Gets details of an access rule.
For a full list of available parameters, please refer to the official
API reference:
https://docs.openstack.org/api-ref/identity/v3/index.html#show-access-rule-details
"""
resp, body = self.get('users/%s/access_rules/%s' %
(user_id, access_rule_id))
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def list_access_rules(self, user_id, **params):
"""Lists out all of a user's access rules.
For a full list of available parameters, please refer to the official
API reference:
https://docs.openstack.org/api-ref/identity/v3/index.html#list-access-rules
"""
url = 'users/%s/access_rules' % user_id
if params:
url += '?%s' % urllib.urlencode(params)
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def delete_access_rule(self, user_id, access_rule_id):
"""Deletes an access rule.
For a full list of available parameters, please refer to the official
API reference:
https://docs.openstack.org/api-ref/identity/v3/index.html#delete-access-rule
"""
resp, body = self.delete('users/%s/access_rules/%s' %
(user_id, access_rule_id))
self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp, body)

View File

@ -0,0 +1,97 @@
# Copyright 2019 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.lib.services.identity.v3 import access_rules_client
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib.services import base
class TestAccessRulesClient(base.BaseServiceTest):
FAKE_LIST_ACCESS_RULES = {
"links": {
"self": "https://example.com/identity/v3/users/" +
"3e0716ae/access_rules",
"previous": None,
"next": None
},
"access_rules": [
{
"path": "/v2.0/metrics",
"links": {
"self": "https://example.com/identity/v3/access_rules/" +
"07d719df00f349ef8de77d542edf010c"
},
"id": "07d719df00f349ef8de77d542edf010c",
"service": "monitoring",
"method": "GET"
}
]
}
FAKE_ACCESS_RULE_INFO = {
"access_rule": {
"path": "/v2.0/metrics",
"links": {
"self": "https://example.com/identity/v3/access_rules/" +
"07d719df00f349ef8de77d542edf010c"
},
"id": "07d719df00f349ef8de77d542edf010c",
"service": "monitoring",
"method": "GET"
}
}
def setUp(self):
super(TestAccessRulesClient, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = access_rules_client.AccessRulesClient(
fake_auth, 'identity', 'regionOne')
def _test_show_access_rule(self, bytes_body=False):
self.check_service_client_function(
self.client.show_access_rule,
'tempest.lib.common.rest_client.RestClient.get',
self.FAKE_ACCESS_RULE_INFO,
bytes_body,
user_id="123456",
access_rule_id="5499a186")
def _test_list_access_rules(self, bytes_body=False):
self.check_service_client_function(
self.client.list_access_rules,
'tempest.lib.common.rest_client.RestClient.get',
self.FAKE_LIST_ACCESS_RULES,
bytes_body,
user_id="123456")
def test_show_access_rule_with_str_body(self):
self._test_show_access_rule()
def test_show_access_rule_with_bytes_body(self):
self._test_show_access_rule(bytes_body=True)
def test_list_access_rule_with_str_body(self):
self._test_list_access_rules()
def test_list_access_rule_with_bytes_body(self):
self._test_list_access_rules(bytes_body=True)
def test_delete_access_rule(self):
self.check_service_client_function(
self.client.delete_access_rule,
'tempest.lib.common.rest_client.RestClient.delete',
{},
user_id="123456",
access_rule_id="5499a186",
status=204)