diff --git a/airship_tempest_plugin/services/shipyard/json/actions_client.py b/airship_tempest_plugin/services/shipyard/json/actions_client.py index 5b1001c..1cd3a50 100644 --- a/airship_tempest_plugin/services/shipyard/json/actions_client.py +++ b/airship_tempest_plugin/services/shipyard/json/actions_client.py @@ -39,10 +39,10 @@ class ActionsClient(rest_client.RestClient): body = json.loads(body) return rest_client.ResponseBody(resp, body) - def create_action(self): + def create_action(self, action=None): url = 'actions' # Update post_body if functional testing is desired - post_body = json.dumps({}) + post_body = json.dumps({"name": action}) resp, body = self.post(url, post_body) self.expected_success(201, resp.status) body = json.loads(body) diff --git a/airship_tempest_plugin/services/shipyard/json/site_statuses_client.py b/airship_tempest_plugin/services/shipyard/json/site_statuses_client.py new file mode 100644 index 0000000..67146a6 --- /dev/null +++ b/airship_tempest_plugin/services/shipyard/json/site_statuses_client.py @@ -0,0 +1,34 @@ +# Copyright 2018 AT&T Corp +# 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://github.com/openstack/airship-shipyard/blob/master/docs/source/API.rst#site-statuses-api +""" + +from oslo_serialization import jsonutils as json + +from tempest.lib.common import rest_client + + +class SiteStatusesClient(rest_client.RestClient): + api_version = "v1.0" + + # Note: add support of query filters if testing beyond RBAC is desired + def get_site_statuses(self): + resp, body = self.get('site_statuses') + self.expected_success(200, resp.status) + body = json.loads(body) + return rest_client.ResponseBody(resp, body) diff --git a/airship_tempest_plugin/tests/api/common/rbac_roles.yaml b/airship_tempest_plugin/tests/api/common/rbac_roles.yaml index fd17b68..05b1742 100644 --- a/airship_tempest_plugin/tests/api/common/rbac_roles.yaml +++ b/airship_tempest_plugin/tests/api/common/rbac_roles.yaml @@ -6,6 +6,18 @@ shipyard: workflow_orchestrator:create_action: - admin - admin_ucp + workflow_orchestrator:action_deploy_site: + - admin + - admin_ucp + workflow_orchestrator:action_update_site: + - admin + - admin_ucp + workflow_orchestrator:action_update_software: + - admin + - admin_ucp + workflow_orchestrator:action_redeploy_server: + - admin + - admin_ucp workflow_orchestrator:get_action: - admin - admin_ucp @@ -51,3 +63,7 @@ shipyard: - admin - admin_ucp - admin_ucp_viewer + workflow_orchestrator:get_site_statuses: + - admin + - admin_ucp + - admin_ucp_viewer diff --git a/airship_tempest_plugin/tests/api/shipyard/base.py b/airship_tempest_plugin/tests/api/shipyard/base.py index 6414463..47fb59a 100644 --- a/airship_tempest_plugin/tests/api/shipyard/base.py +++ b/airship_tempest_plugin/tests/api/shipyard/base.py @@ -22,6 +22,8 @@ from airship_tempest_plugin.services.shipyard.json.document_staging_client \ import DocumentStagingClient from airship_tempest_plugin.services.shipyard.json.log_retrieval_client \ import LogRetrievalClient +from airship_tempest_plugin.services.shipyard.json.site_statuses_client \ + import SiteStatusesClient from tempest import config from tempest import test @@ -65,3 +67,8 @@ class BaseShipyardTest(test.BaseTestCase): CONF.shipyard.catalog_type, CONF.identity.region, CONF.shipyard.endpoint_type) + cls.shipyard_site_statuses_client = SiteStatusesClient( + cls.auth_provider, + CONF.shipyard.catalog_type, + CONF.identity.region, + CONF.shipyard.endpoint_type) diff --git a/airship_tempest_plugin/tests/api/shipyard/rbac/test_actions_rbac.py b/airship_tempest_plugin/tests/api/shipyard/rbac/test_actions_rbac.py index 3c569d7..723fce5 100644 --- a/airship_tempest_plugin/tests/api/shipyard/rbac/test_actions_rbac.py +++ b/airship_tempest_plugin/tests/api/shipyard/rbac/test_actions_rbac.py @@ -14,13 +14,19 @@ # under the License. # +import logging + from airship_tempest_plugin.tests.api.shipyard.rbac import rbac_base from patrole_tempest_plugin import rbac_rule_validation +from tempest import config from tempest.lib import decorators from tempest.lib import exceptions +CONF = config.CONF +LOG = logging.getLogger(__name__) + class ActionsRbacTest(rbac_base.BaseShipyardRbacTest): @@ -47,6 +53,84 @@ class ActionsRbacTest(rbac_base.BaseShipyardRbacTest): except (exceptions.BadRequest, exceptions.NotFound): pass + @rbac_rule_validation.action( + service="shipyard", + rules=["workflow_orchestrator:action_deploy_site"]) + @decorators.idempotent_id('e69687da-8d4e-413b-a566-c0e56b5d1087') + def test_deploy_site(self): + with self.rbac_utils.override_role(self): + LOG.warn("In this scenario, `workflow_orchestrator:create_action` " + "is enforced first and if permission is denied, then " + "there is no additional enforcement. If permission is " + "allowed to `workflow_orchestrator:create_action`, then " + "`workflow_orchestrator:action_deploy_site` is enforced. " + " If this test fails, check permissions of both actions.") + try: + self.shipyard_actions_client.create_action( + action="deploy_site") + # Ignore exceptions besides Forbidden + except (exceptions.BadRequest, exceptions.NotFound): + pass + + @rbac_rule_validation.action( + service="shipyard", + rules=["workflow_orchestrator:action_update_site"]) + @decorators.idempotent_id('95f3b377-99ae-4ac2-8ce3-1e52ca081abc') + def test_update_site(self): + with self.rbac_utils.override_role(self): + LOG.warn("In this scenario, `workflow_orchestrator:create_action` " + "is enforced first and if permission is denied, then " + "there is no additional enforcement. If permission is " + "allowed to `workflow_orchestrator:create_action`, then " + "`workflow_orchestrator:action_update_site` is enforced. " + " If this test fails, check permissions of both actions.") + try: + self.shipyard_actions_client.create_action( + action="update_site") + # Ignore exceptions besides Forbidden + except (exceptions.BadRequest, exceptions.NotFound): + pass + + @rbac_rule_validation.action( + service="shipyard", + rules=["workflow_orchestrator:action_update_software"]) + @decorators.idempotent_id('18fae927-e759-4a60-bceb-81807b9f2c10') + def test_update_software(self): + with self.rbac_utils.override_role(self): + LOG.warn("In this scenario, `workflow_orchestrator:create_action` " + "is enforced first and if permission is denied, then " + "there is no additional enforcement. If permission is " + "allowed to `workflow_orchestrator:create_action`, then " + "`workflow_orchestrator:action_update_software` is " + "enforced. If this test fails, check permissions of both " + "actions.") + try: + self.shipyard_actions_client.create_action( + action="update_software") + # Ignore exceptions besides Forbidden + except (exceptions.BadRequest, exceptions.NotFound): + pass + + @rbac_rule_validation.action( + service="shipyard", + rules=["workflow_orchestrator:action_redeploy_server"]) + @decorators.idempotent_id('bba1eb77-c350-4c3b-b62d-3eea8bc13110') + def test_redeploy_server(self): + with self.rbac_utils.override_role(self): + LOG.warn("In this scenario, `workflow_orchestrator:create_action` " + "is enforced first and if permission is denied, then " + "there is no additional enforcement. If permission is " + "allowed to `workflow_orchestrator:create_action`, then " + "`workflow_orchestrator:action_redeploy_server` is " + "enforced. If this test fails, check permissions of both " + "actions.") + try: + self.shipyard_actions_client.create_action( + action="redeploy_server") + # Ignore exceptions besides Forbidden + except (exceptions.BadRequest, exceptions.NotFound): + pass + @rbac_rule_validation.action( service="shipyard", rules=["workflow_orchestrator:get_action"]) diff --git a/airship_tempest_plugin/tests/api/shipyard/rbac/test_site_statuses.py b/airship_tempest_plugin/tests/api/shipyard/rbac/test_site_statuses.py new file mode 100644 index 0000000..cafcba1 --- /dev/null +++ b/airship_tempest_plugin/tests/api/shipyard/rbac/test_site_statuses.py @@ -0,0 +1,39 @@ +# Copyright 2018 AT&T Corp +# 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 airship_tempest_plugin.tests.api.shipyard.rbac import rbac_base + +from patrole_tempest_plugin import rbac_rule_validation + +from tempest.lib import decorators +from tempest.lib import exceptions + + +class SiteStatusesRbacTest(rbac_base.BaseShipyardRbacTest): + + @rbac_rule_validation.action( + service="shipyard", + rules=["workflow_orchestrator:get_site_statuses"]) + @decorators.idempotent_id('3fcc69f6-8e15-4062-b582-2e5c366a6dc3') + def test_get_site_statuses(self): + with self.rbac_utils.override_role(self): + # As this is a RBAC test, we only care about whether the role has + # permission or not. Role permission is checked prior to validating + # the post body, therefore we will ignore a BadRequest exception + try: + self.shipyard_site_statuses_client.get_site_statuses() + except exceptions.BadRequest: + pass