patrole/patrole_tempest_plugin/tests/unit/test_rbac_utils.py

236 lines
9.7 KiB
Python

# Copyright 2017 AT&T Corporation.
# 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.
import mock
import testtools
from tempest.lib import exceptions as lib_exc
from tempest import test
from tempest.tests import base
from patrole_tempest_plugin import rbac_exceptions
from patrole_tempest_plugin import rbac_utils
from patrole_tempest_plugin.tests.unit import fixtures as patrole_fixtures
class RBACUtilsTest(base.TestCase):
def setUp(self):
super(RBACUtilsTest, self).setUp()
# Reset the role history after each test run to avoid validation
# errors between tests.
rbac_utils.RbacUtils.override_role_history = {}
self.rbac_utils = self.useFixture(patrole_fixtures.RbacUtilsFixture())
def test_override_role_with_missing_admin_role(self):
self.rbac_utils.set_roles('member')
error_re = (".*Following roles were not found: admin. Available "
"roles: member.")
self.assertRaisesRegex(rbac_exceptions.RbacResourceSetupFailed,
error_re, self.rbac_utils.override_role)
def test_override_role_with_missing_rbac_role(self):
self.rbac_utils.set_roles('admin')
error_re = (".*Following roles were not found: member. Available "
"roles: admin.")
self.assertRaisesRegex(rbac_exceptions.RbacResourceSetupFailed,
error_re, self.rbac_utils.override_role)
def test_override_role_to_admin_role(self):
self.rbac_utils.override_role()
mock_test_obj = self.rbac_utils.mock_test_obj
roles_client = self.rbac_utils.admin_roles_client
mock_time = self.rbac_utils.mock_time
roles_client.create_user_role_on_project.assert_called_once_with(
self.rbac_utils.PROJECT_ID, self.rbac_utils.USER_ID, 'admin_id')
mock_test_obj.get_auth_providers()[0].clear_auth\
.assert_called_once_with()
mock_test_obj.get_auth_providers()[0].set_auth\
.assert_called_once_with()
mock_time.sleep.assert_called_once_with(1)
def test_override_role_to_admin_role_avoids_role_switch(self):
self.rbac_utils.set_roles(['admin', 'member'], 'admin')
self.rbac_utils.override_role()
roles_client = self.rbac_utils.admin_roles_client
mock_time = self.rbac_utils.mock_time
roles_client.create_user_role_on_project.assert_not_called()
mock_time.sleep.assert_not_called()
def test_override_role_to_member_role(self):
self.rbac_utils.override_role(True)
mock_test_obj = self.rbac_utils.mock_test_obj
roles_client = self.rbac_utils.admin_roles_client
mock_time = self.rbac_utils.mock_time
roles_client.create_user_role_on_project.assert_has_calls([
mock.call(self.rbac_utils.PROJECT_ID, self.rbac_utils.USER_ID,
'admin_id'),
mock.call(self.rbac_utils.PROJECT_ID, self.rbac_utils.USER_ID,
'member_id')
])
mock_test_obj.get_auth_providers()[0].clear_auth.assert_has_calls(
[mock.call()] * 2)
mock_test_obj.get_auth_providers()[0].set_auth.assert_has_calls(
[mock.call()] * 2)
mock_time.sleep.assert_has_calls([mock.call(1)] * 2)
def test_override_role_to_member_role_avoids_role_switch(self):
self.rbac_utils.set_roles(['admin', 'member'], 'member')
self.rbac_utils.override_role(True)
roles_client = self.rbac_utils.admin_roles_client
mock_time = self.rbac_utils.mock_time
roles_client.create_user_role_on_project.assert_has_calls([
mock.call(self.rbac_utils.PROJECT_ID, self.rbac_utils.USER_ID,
'admin_id')
])
mock_time.sleep.assert_called_once_with(1)
def test_override_role_to_member_role_then_admin_role(self):
self.rbac_utils.override_role(True, False)
mock_test_obj = self.rbac_utils.mock_test_obj
roles_client = self.rbac_utils.admin_roles_client
mock_time = self.rbac_utils.mock_time
roles_client.create_user_role_on_project.assert_has_calls([
mock.call(self.rbac_utils.PROJECT_ID, self.rbac_utils.USER_ID,
'admin_id'),
mock.call(self.rbac_utils.PROJECT_ID, self.rbac_utils.USER_ID,
'member_id'),
mock.call(self.rbac_utils.PROJECT_ID, self.rbac_utils.USER_ID,
'admin_id')
])
mock_test_obj.get_auth_providers()[0].clear_auth.assert_has_calls(
[mock.call()] * 3)
mock_test_obj.get_auth_providers()[0].set_auth.assert_has_calls(
[mock.call()] * 3)
mock_time.sleep.assert_has_calls([mock.call(1)] * 3)
def test_clear_user_roles(self):
# NOTE(felipemonteiro): Set the user's roles on the project to
# include 'random' to coerce a role switch, or else it will be
# skipped.
self.rbac_utils.set_roles(['admin', 'member'], ['member', 'random'])
self.rbac_utils.override_role()
roles_client = self.rbac_utils.admin_roles_client
roles_client.list_user_roles_on_project.assert_called_once_with(
self.rbac_utils.PROJECT_ID, self.rbac_utils.USER_ID)
roles_client.delete_role_from_user_on_project.\
assert_has_calls([
mock.call(mock.sentinel.project_id, mock.sentinel.user_id,
'member_id'),
mock.call(mock.sentinel.project_id, mock.sentinel.user_id,
'random_id')])
@mock.patch.object(rbac_utils.RbacUtils, '_override_role', autospec=True)
def test_override_role_context_manager_simulate_pass(self,
mock_override_role):
"""Validate that expected override_role calls are made when switching
to admin role for success path.
"""
test_obj = mock.MagicMock()
_rbac_utils = rbac_utils.RbacUtils(test_obj)
# Validate constructor called _override_role with False.
mock_override_role.assert_called_once_with(_rbac_utils, test_obj,
False)
mock_override_role.reset_mock()
with _rbac_utils.override_role(test_obj):
# Validate `override_role` public method called private method
# `_override_role` with True.
mock_override_role.assert_called_once_with(_rbac_utils, test_obj,
True)
mock_override_role.reset_mock()
# Validate that `override_role` switched back to admin role after
# contextmanager.
mock_override_role.assert_called_once_with(_rbac_utils, test_obj,
False)
@mock.patch.object(rbac_utils.RbacUtils, '_override_role',
autospec=True)
def test_override_role_context_manager_simulate_fail(self,
mock_override_role):
"""Validate that expected override_role calls are made when switching
to admin role for failure path (i.e. when test raises exception).
"""
test_obj = mock.MagicMock()
_rbac_utils = rbac_utils.RbacUtils(test_obj)
# Validate constructor called _override_role with False.
mock_override_role.assert_called_once_with(_rbac_utils, test_obj,
False)
mock_override_role.reset_mock()
def _do_test():
with _rbac_utils.override_role(test_obj):
# Validate `override_role` public method called private method
# `_override_role` with True.
mock_override_role.assert_called_once_with(
_rbac_utils, test_obj, True)
mock_override_role.reset_mock()
# Raise exc to verify role switch works for negative case.
raise lib_exc.Forbidden()
# Validate that role is switched back to admin, despite test failure.
with testtools.ExpectedException(lib_exc.Forbidden):
_do_test()
mock_override_role.assert_called_once_with(_rbac_utils, test_obj,
False)
class RBACUtilsMixinTest(base.TestCase):
def setUp(self):
super(RBACUtilsMixinTest, self).setUp()
class FakeRbacTest(rbac_utils.RbacUtilsMixin, test.BaseTestCase):
@classmethod
def setup_clients(cls):
super(FakeRbacTest, cls).setup_clients()
cls.setup_rbac_utils()
def runTest(self):
pass
self.parent_class = FakeRbacTest
def test_setup_rbac_utils(self):
"""Validate that the child class has the `rbac_utils` attribute after
running parent class's `cls.setup_rbac_utils`.
"""
class ChildRbacTest(self.parent_class):
pass
child_test = ChildRbacTest()
with mock.patch.object(rbac_utils.RbacUtils, '__init__',
lambda *args: None):
child_test.setUpClass()
self.assertTrue(hasattr(child_test, 'rbac_utils'))
self.assertIsInstance(child_test.rbac_utils, rbac_utils.RbacUtils)