Implement basic protection testing jobs
This commit lays down a basic structure for protection tests. These are useful for testing various secure RBAC personas, but leveraging all the dynamic credential work in tempest's authentication libraries to provision clients for testing. We're also adding a non-voting protection test job so that we can integrate protection testing into the cinder gate as we work through policy changes. This commit also adds some basic tests exercising the capabilities admin-only API. These tests ensure that only operators (e.g., system-administrators) or formally known as project-administrators, can access the capabilities API. Assertions and functionality in these tests may expand in the future to accomodate system-scope when cinder can properly consume system-scoped tokens from keystone. For now, the tests assume project-administrators are deployment operators, which is the legacy way of denoting "admin-ness" in OpenStack deployments. Depends-On: https://review.opendev.org/c/openstack/tempest/+/778753 Change-Id: I6d4ae6d516f4c2dda4dcb6b974857b34f2ef2254
This commit is contained in:
parent
1a0b126246
commit
d3fddec498
23
.zuul.yaml
23
.zuul.yaml
|
@ -14,6 +14,9 @@
|
|||
- cinder-tempest-plugin-basic-victoria
|
||||
- cinder-tempest-plugin-basic-ussuri
|
||||
- cinder-tempest-plugin-basic-train
|
||||
# Set this job to voting once we have some actual tests to run
|
||||
- cinder-tempest-plugin-protection-functional:
|
||||
voting: false
|
||||
gate:
|
||||
jobs:
|
||||
- cinder-tempest-plugin-lvm-lio-barbican
|
||||
|
@ -25,6 +28,26 @@
|
|||
- cinder-tempest-plugin-cbak-ceph-ussuri
|
||||
- cinder-tempest-plugin-cbak-ceph-train
|
||||
|
||||
- job:
|
||||
name: cinder-tempest-plugin-protection-functional
|
||||
parent: devstack-tempest
|
||||
required-projects:
|
||||
- opendev.org/openstack/cinder-tempest-plugin
|
||||
- opendev.org/openstack/cinder
|
||||
vars:
|
||||
tox_envlist: all
|
||||
tempest_test_regex: 'cinder_tempest_plugin.rbac'
|
||||
devstack_local_conf:
|
||||
test-config:
|
||||
$CINDER_CONF:
|
||||
oslo_policy:
|
||||
enforce_new_defaults: True
|
||||
$TEMPEST_CONFIG:
|
||||
enforce_scope:
|
||||
cinder: True
|
||||
tempest_plugins:
|
||||
- cinder-tempest-plugin
|
||||
|
||||
- job:
|
||||
name: cinder-tempest-plugin-lvm-barbican-base-abstract
|
||||
description: |
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# 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 VolumeV3RbacBaseTests(object):
|
||||
|
||||
identity_version = 'v3'
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(VolumeV3RbacBaseTests, cls).skip_checks()
|
||||
if not CONF.enforce_scope.cinder:
|
||||
raise cls.skipException(
|
||||
"Tempest is not configured to enforce_scope for cinder, "
|
||||
"skipping RBAC tests. To enable these tests set "
|
||||
"`tempest.conf [enforce_scope] cinder=True`."
|
||||
)
|
||||
|
||||
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
|
|
@ -0,0 +1,80 @@
|
|||
# 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.lib import exceptions
|
||||
|
||||
from cinder_tempest_plugin.api.volume import base
|
||||
from cinder_tempest_plugin.rbac.v3 import base as rbac_base
|
||||
|
||||
|
||||
class VolumeV3RbacCapabilityTests(rbac_base.VolumeV3RbacBaseTests,
|
||||
metaclass=abc.ABCMeta):
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super().setup_clients()
|
||||
cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
|
||||
cls.client = cls.persona.volume_capabilities_client_latest
|
||||
# NOTE(lbragstad): This admin_client will be more useful later when
|
||||
# cinder supports system-scope and we need it for administrative
|
||||
# operations. For now, keep os_project_admin as the admin client until
|
||||
# we have system-scope.
|
||||
admin_client = cls.os_project_admin
|
||||
cls.admin_capabilities_client = (
|
||||
admin_client.volume_capabilities_client_latest)
|
||||
cls.admin_stats_client = (
|
||||
admin_client.volume_scheduler_stats_client_latest)
|
||||
|
||||
@classmethod
|
||||
def setup_credentials(cls):
|
||||
super().setup_credentials()
|
||||
cls.os_primary = getattr(cls, 'os_%s' % cls.credentials[0])
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_get_capabilities(self):
|
||||
"""Test volume_extension:capabilities policy.
|
||||
|
||||
This test must check:
|
||||
* whether the persona can fetch capabilities for a host.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class ProjectAdminTests(VolumeV3RbacCapabilityTests, base.BaseVolumeTest):
|
||||
|
||||
credentials = ['project_admin', 'system_admin']
|
||||
|
||||
def test_get_capabilities(self):
|
||||
pools = self.admin_stats_client.list_pools()['pools']
|
||||
host_name = pools[0]['name']
|
||||
self.do_request('show_backend_capabilities', expected_status=200,
|
||||
host=host_name)
|
||||
|
||||
|
||||
class ProjectMemberTests(ProjectAdminTests, base.BaseVolumeTest):
|
||||
|
||||
credentials = ['project_member', 'project_admin', 'system_admin']
|
||||
|
||||
def test_get_capabilities(self):
|
||||
pools = self.admin_stats_client.list_pools()['pools']
|
||||
host_name = pools[0]['name']
|
||||
self.do_request('show_backend_capabilities',
|
||||
expected_status=exceptions.Forbidden,
|
||||
host=host_name)
|
||||
|
||||
|
||||
class ProjectReaderTests(ProjectMemberTests, base.BaseVolumeTest):
|
||||
|
||||
credentials = ['project_reader', 'project_admin', 'system_admin']
|
Loading…
Reference in New Issue