Merge "Change rbac_utils.RbacUtils is_admin to function"
diff --git a/HACKING.rst b/HACKING.rst
index 5281b53..f89910b 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -1,15 +1,15 @@
Patrole Style Commandments
==========================
-- Step 1: Read the OpenStack Style Commandments: `<https://docs.openstack.org/developer/hacking/>`__
-- Step 2: Review Tempest's Style Commandments: `<https://docs.openstack.org/developer/tempest/HACKING.html>`__
+- Step 1: Read the OpenStack Style Commandments: `<https://docs.openstack.org/hacking/latest/>`__
+- Step 2: Review Tempest's Style Commandments: `<https://docs.openstack.org/tempest/latest/HACKING.html>`__
- Step 3: Read on
Patrole Specific Commandments
------------------------------
Patrole borrows the following commandments from Tempest; refer to
-`Tempest's Commandments <https://docs.openstack.org/developer/tempest/HACKING.html>`__
+`Tempest's Commandments <https://docs.openstack.org/tempest/latest/HACKING.html>`__
for more information:
.. note::
diff --git a/doc/source/sampleconf.rst b/doc/source/sampleconf.rst
index c262f2d..43933db 100644
--- a/doc/source/sampleconf.rst
+++ b/doc/source/sampleconf.rst
@@ -36,7 +36,7 @@
# are.
test_custom_requirements = False
- File path of the yaml file that defines your RBAC requirements. This
+ # File path of the yaml file that defines your RBAC requirements. This
# file must be located on the same host that Patrole runs on. The yaml
# file should be written as follows:
custom_requirements_file = patrole/requirements.txt
diff --git a/patrole_tempest_plugin/tests/api/compute/test_instance_actions_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_instance_actions_rbac.py
deleted file mode 100644
index b81d2ab..0000000
--- a/patrole_tempest_plugin/tests/api/compute/test_instance_actions_rbac.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# 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.
-
-from tempest.lib import decorators
-from tempest import test
-
-from patrole_tempest_plugin import rbac_exceptions
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.compute import rbac_base
-
-
-class InstanceActionsRbacTest(rbac_base.BaseV2ComputeRbacTest):
-
- @classmethod
- def skip_checks(cls):
- super(InstanceActionsRbacTest, cls).skip_checks()
- if not test.is_extension_enabled('os-instance-actions', 'compute'):
- raise cls.skipException(
- '%s skipped as os-instance-actions not enabled' % cls.__name__)
-
- @classmethod
- def resource_setup(cls):
- super(InstanceActionsRbacTest, cls).resource_setup()
- cls.server = cls.create_test_server(wait_until='ACTIVE')
- cls.request_id = cls.server.response['x-compute-request-id']
-
- @decorators.idempotent_id('9d1b131d-407e-4fa3-8eef-eb2c4526f1da')
- @rbac_rule_validation.action(
- service="nova",
- rule="os_compute_api:os-instance-actions")
- def test_list_instance_actions(self):
- self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.list_instance_actions(self.server['id'])
-
- @decorators.idempotent_id('eb04c439-4215-4029-9ccb-5b3c041bfc25')
- @rbac_rule_validation.action(
- service="nova",
- rule="os_compute_api:os-instance-actions:events")
- def test_get_instance_action(self):
- self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- instance_action = self.servers_client.show_instance_action(
- self.server['id'], self.request_id)['instanceAction']
- if 'events' not in instance_action:
- raise rbac_exceptions.RbacActionFailed
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py
index 1866119..e942f08 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py
@@ -49,21 +49,30 @@
@classmethod
def resource_setup(cls):
super(MiscPolicyActionsRbacTest, cls).resource_setup()
- cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id']
+ cls.server = cls.create_test_server(wait_until='ACTIVE')
def setUp(self):
super(MiscPolicyActionsRbacTest, self).setUp()
try:
waiters.wait_for_server_status(self.servers_client,
- self.server_id, 'ACTIVE')
+ self.server['id'], 'ACTIVE')
except lib_exc.NotFound:
# If the server was found to be deleted by a previous test,
# a new one is built
- server = self.create_test_server(wait_until='ACTIVE')
- self.__class__.server_id = server['id']
+ self.__class__.server = self.create_test_server(
+ wait_until='ACTIVE')
except Exception:
# Rebuilding the server in case something happened during a test
- self.__class__.server_id = self.rebuild_server(self.server_id)
+ self.__class__.server = self._rebuild_server(self.server['id'])
+
+ def _rebuild_server(self, server_id):
+ # Destroy an existing server and creates a new one.
+ if server_id:
+ self.delete_server(server_id)
+
+ self.password = data_utils.rand_password()
+ return self.create_test_server(
+ wait_until='ACTIVE', adminPass=self.password)
@test.requires_ext(extension='os-admin-actions', service='compute')
@rbac_rule_validation.action(
@@ -73,8 +82,8 @@
def test_reset_server_state(self):
"""Test reset server state, part of os-admin-actions."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.reset_state(self.server_id, state='error')
- self.addCleanup(self.servers_client.reset_state, self.server_id,
+ self.servers_client.reset_state(self.server['id'], state='error')
+ self.addCleanup(self.servers_client.reset_state, self.server['id'],
state='active')
@test.requires_ext(extension='os-admin-actions', service='compute')
@@ -85,7 +94,7 @@
def test_inject_network_info(self):
"""Test inject network info, part of os-admin-actions."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.inject_network_info(self.server_id)
+ self.servers_client.inject_network_info(self.server['id'])
@decorators.attr(type=['slow'])
@test.requires_ext(extension='os-admin-actions', service='compute')
@@ -96,7 +105,7 @@
def test_reset_network(self):
"""Test reset network, part of os-admin-actions."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.reset_network(self.server_id)
+ self.servers_client.reset_network(self.server['id'])
@testtools.skipUnless(CONF.compute_feature_enabled.change_password,
'Change password not available.')
@@ -106,15 +115,16 @@
@decorators.idempotent_id('908a7d59-3a66-441c-94cf-38e57ed14956')
def test_change_server_password(self):
"""Test change admin password, part of os-admin-password."""
- original_password = self.servers_client.show_password(self.server_id)
+ original_password = self.servers_client.show_password(
+ self.server['id'])
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
self.servers_client.change_password(
- self.server_id, adminPass=data_utils.rand_password())
- self.addCleanup(self.servers_client.change_password, self.server_id,
+ self.server['id'], adminPass=data_utils.rand_password())
+ self.addCleanup(self.servers_client.change_password, self.server['id'],
adminPass=original_password)
waiters.wait_for_server_status(
- self.os_admin.servers_client, self.server_id, 'ACTIVE')
+ self.os_admin.servers_client, self.server['id'], 'ACTIVE')
@test.requires_ext(extension='os-config-drive', service='compute')
@decorators.idempotent_id('2c82e819-382d-4d6f-87f0-a45954cbbc64')
@@ -138,7 +148,7 @@
def test_show_server_config_drive(self):
"""Test show server with config_drive property in response body."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- body = self.servers_client.show_server(self.server_id)['server']
+ body = self.servers_client.show_server(self.server['id'])['server']
if 'config_drive' not in body:
raise rbac_exceptions.RbacActionFailed(
'"config_drive" attribute not found in response body.')
@@ -152,7 +162,44 @@
"""Test force delete server, part of os-deferred-delete."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
# Force-deleting a server enforces os-deferred-delete.
- self.servers_client.force_delete_server(self.server_id)
+ self.servers_client.force_delete_server(self.server['id'])
+
+ @test.requires_ext(extension='os-instance-actions', service='compute')
+ @decorators.idempotent_id('9d1b131d-407e-4fa3-8eef-eb2c4526f1da')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-instance-actions")
+ def test_list_instance_actions(self):
+ """Test list instance actions, part of os-instance-actions."""
+ self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+ self.servers_client.list_instance_actions(self.server['id'])
+
+ @test.requires_ext(extension='os-instance-actions', service='compute')
+ @decorators.idempotent_id('eb04c439-4215-4029-9ccb-5b3c041bfc25')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-instance-actions:events")
+ def test_show_instance_action(self):
+ """Test show instance action, part of os-instance-actions.
+
+ Expect "events" details to be included in the response body.
+ """
+ # NOTE: "os_compute_api:os-instance-actions" is also enforced.
+ request_id = self.server.response['x-compute-request-id']
+
+ self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+ instance_action = self.servers_client.show_instance_action(
+ self.server['id'], request_id)['instanceAction']
+
+ if 'events' not in instance_action:
+ raise rbac_exceptions.RbacActionFailed(
+ '"%s" attribute not found in response body.' % 'events')
+ # Microversion 2.51+ returns 'events' always, but not 'traceback'. If
+ # 'traceback' is also present then policy enforcement passed.
+ if 'traceback' not in instance_action['events'][0]:
+ raise rbac_exceptions.RbacActionFailed(
+ '"%s" attribute not found in response body.'
+ % 'events.traceback')
@rbac_rule_validation.action(
service="nova",
@@ -161,8 +208,8 @@
def test_lock_server(self):
"""Test lock server, part of os-lock-server."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.lock_server(self.server_id)
- self.addCleanup(self.servers_client.unlock_server, self.server_id)
+ self.servers_client.lock_server(self.server['id'])
+ self.addCleanup(self.servers_client.unlock_server, self.server['id'])
@rbac_rule_validation.action(
service="nova",
@@ -170,11 +217,11 @@
@decorators.idempotent_id('d50ef8e8-4bce-11e7-b114-b2f933d5fe66')
def test_unlock_server(self):
"""Test unlock server, part of os-lock-server."""
- self.servers_client.lock_server(self.server_id)
- self.addCleanup(self.servers_client.unlock_server, self.server_id)
+ self.servers_client.lock_server(self.server['id'])
+ self.addCleanup(self.servers_client.unlock_server, self.server['id'])
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.unlock_server(self.server_id)
+ self.servers_client.unlock_server(self.server['id'])
@rbac_rule_validation.action(
service="nova",
@@ -187,11 +234,11 @@
of the unlock policy, the server must be locked by a different
user than the one who is attempting to unlock it.
"""
- self.os_admin.servers_client.lock_server(self.server_id)
- self.addCleanup(self.servers_client.unlock_server, self.server_id)
+ self.os_admin.servers_client.lock_server(self.server['id'])
+ self.addCleanup(self.servers_client.unlock_server, self.server['id'])
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.unlock_server(self.server_id)
+ self.servers_client.unlock_server(self.server['id'])
@test.requires_ext(extension='os-rescue', service='compute')
@rbac_rule_validation.action(
@@ -201,7 +248,7 @@
def test_rescue_server(self):
"""Test rescue server, part of os-rescue."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.rescue_server(self.server_id)
+ self.servers_client.rescue_server(self.server['id'])
@test.requires_ext(extension='os-server-diagnostics', service='compute')
@rbac_rule_validation.action(
@@ -211,7 +258,7 @@
def test_show_server_diagnostics(self):
"""Test show server diagnostics, part of os-server-diagnostics."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.show_server_diagnostics(self.server_id)
+ self.servers_client.show_server_diagnostics(self.server['id'])
@test.requires_ext(extension='os-server-password', service='compute')
@decorators.idempotent_id('aaf43f78-c178-4581-ac18-14afd3f1f6ba')
@@ -221,7 +268,7 @@
def test_delete_server_password(self):
"""Test delete server password, part of os-server-password."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.delete_password(self.server_id)
+ self.servers_client.delete_password(self.server['id'])
@test.requires_ext(extension='os-server-password', service='compute')
@rbac_rule_validation.action(
@@ -231,7 +278,7 @@
def test_get_server_password(self):
"""Test show server password, part of os-server-password."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.show_password(self.server_id)
+ self.servers_client.show_password(self.server['id'])
@test.requires_ext(extension='OS-SRV-USG', service='compute')
@rbac_rule_validation.action(
@@ -245,7 +292,7 @@
test can be combined with the generic test for showing a server.
"""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.show_server(self.server_id)
+ self.servers_client.show_server(self.server['id'])
@test.requires_ext(extension='os-simple-tenant-usage', service='compute')
@rbac_rule_validation.action(
@@ -278,10 +325,10 @@
def test_suspend_server(self):
"""Test suspend server, part of os-suspend-server."""
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.suspend_server(self.server_id)
- self.addCleanup(self.servers_client.resume_server, self.server_id)
+ self.servers_client.suspend_server(self.server['id'])
+ self.addCleanup(self.servers_client.resume_server, self.server['id'])
waiters.wait_for_server_status(
- self.os_admin.servers_client, self.server_id, 'SUSPENDED')
+ self.os_admin.servers_client, self.server['id'], 'SUSPENDED')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
"Suspend compute feature is not available.")
@@ -291,14 +338,14 @@
rule="os_compute_api:os-suspend-server:resume")
def test_resume_server(self):
"""Test resume server, part of os-suspend-server."""
- self.servers_client.suspend_server(self.server_id)
- waiters.wait_for_server_status(self.servers_client, self.server_id,
+ self.servers_client.suspend_server(self.server['id'])
+ waiters.wait_for_server_status(self.servers_client, self.server['id'],
'SUSPENDED')
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- self.servers_client.resume_server(self.server_id)
+ self.servers_client.resume_server(self.server['id'])
waiters.wait_for_server_status(
- self.os_admin.servers_client, self.server_id, 'ACTIVE')
+ self.os_admin.servers_client, self.server['id'], 'ACTIVE')
class MiscPolicyActionsNetworkRbacTest(rbac_base.BaseV2ComputeRbacTest):