From b540700061b9ef415b9aea494c765ad43d75fee2 Mon Sep 17 00:00:00 2001 From: Ghanshyam Mann Date: Mon, 10 Apr 2023 22:29:00 -0500 Subject: [PATCH] Retire patrole Patrole project is not active anymore and its gate is broken. We waited for couple of cycle to see if there is any interest in this project and anyone can maintain it. But we did not get any new maintainers and current QA team does not have bandwidth/interest to continue maintaining it. This project was for RBAc testing which is moving towards unit/functional tests on service side as well as tempest plugins tests. In QA 2023.2 PTG, we decided to retire this project - https://etherpad.opendev.org/p/qa-bobcat-ptg Change-Id: I7721cf06104e5871ec27cdd87d4608dace60a8b7 --- .coveragerc | 6 - .gitignore | 65 - .mailmap | 5 - .stestr.conf | 3 - .zuul.yaml | 246 ---- CONTRIBUTING.rst | 19 - HACKING.rst | 170 --- LICENSE | 176 --- README.rst | 261 +--- REVIEWING.rst | 189 --- babel.cfg | 2 - devstack/README.rst | 25 - devstack/plugin.sh | 179 --- devstack/settings | 8 - doc/requirements.txt | 8 - doc/source/HACKING.rst | 5 - doc/source/REVIEWING.rst | 5 - doc/source/_static/.keep | 0 doc/source/conf.py | 110 -- doc/source/configuration.rst | 94 -- doc/source/contributor/contributing.rst | 57 - doc/source/field_guide/index.rst | 60 - doc/source/field_guide/rbac.rst | 118 -- doc/source/framework/overview.rst | 81 -- doc/source/framework/policy_authority.rst | 60 - doc/source/framework/rbac_authority.rst | 35 - doc/source/framework/rbac_utils.rst | 33 - doc/source/framework/rbac_validation.rst | 17 - .../framework/requirements_authority.rst | 156 --- doc/source/index.rst | 92 -- doc/source/installation.rst | 29 - doc/source/multi-policy-validation.rst | 187 --- doc/source/overview.rst | 1 - doc/source/rbac-overview.rst | 285 ----- doc/source/test_writing_guide.rst | 166 --- etc/config-generator.patrole.conf | 3 - etc/patrole.conf.sample | 172 --- lower-constraints.txt | 76 -- patrole_tempest_plugin/__init__.py | 0 patrole_tempest_plugin/config.py | 229 ---- patrole_tempest_plugin/hacking/__init__.py | 0 patrole_tempest_plugin/hacking/checks.py | 249 ---- patrole_tempest_plugin/plugin.py | 86 -- patrole_tempest_plugin/policy_authority.py | 330 ----- patrole_tempest_plugin/rbac_authority.py | 38 - patrole_tempest_plugin/rbac_exceptions.py | 119 -- .../rbac_rule_validation.py | 516 -------- patrole_tempest_plugin/rbac_utils.py | 501 -------- .../requirements_authority.py | 150 --- patrole_tempest_plugin/tests/__init__.py | 0 patrole_tempest_plugin/tests/api/README.rst | 1 - patrole_tempest_plugin/tests/api/__init__.py | 0 .../tests/api/compute/__init__.py | 0 .../tests/api/compute/rbac_base.py | 50 - .../tests/api/compute/test_agents_rbac.py | 118 -- .../tests/api/compute/test_aggregates_rbac.py | 150 --- .../compute/test_availability_zone_rbac.py | 45 - .../api/compute/test_flavor_access_rbac.py | 116 -- .../compute/test_flavor_extra_specs_rbac.py | 94 -- .../api/compute/test_flavor_manage_rbac.py | 49 - .../api/compute/test_flavor_rxtx_rbac.py | 63 - .../compute/test_floating_ip_pools_rbac.py | 54 - .../api/compute/test_floating_ips_rbac.py | 101 -- .../tests/api/compute/test_hosts_rbac.py | 64 - .../tests/api/compute/test_hypervisor_rbac.py | 138 --- .../tests/api/compute/test_images_rbac.py | 314 ----- .../test_instance_usages_audit_log_rbac.py | 64 - .../tests/api/compute/test_keypairs_rbac.py | 66 - .../tests/api/compute/test_limits_rbac.py | 35 - .../tests/api/compute/test_migrations_rbac.py | 38 - .../api/compute/test_quota_class_sets_rbac.py | 85 -- .../tests/api/compute/test_quota_sets_rbac.py | 112 -- .../api/compute/test_security_groups_rbac.py | 187 --- .../api/compute/test_server_actions_rbac.py | 422 ------- .../api/compute/test_server_consoles_rbac.py | 109 -- .../api/compute/test_server_groups_rbac.py | 64 - .../api/compute/test_server_metadata_rbac.py | 89 -- .../compute/test_server_migrations_rbac.py | 92 -- .../test_server_misc_policy_actions_rbac.py | 828 ------------- .../tests/api/compute/test_server_rbac.py | 204 --- .../api/compute/test_server_tags_rbac.py | 103 -- .../test_server_volume_attachments_rbac.py | 221 ---- .../tests/api/compute/test_services_rbac.py | 46 - .../api/compute/test_tenant_networks_rbac.py | 65 - .../tests/api/compute/test_volume_rbac.py | 167 --- .../tests/api/identity/__init__.py | 0 .../tests/api/identity/rbac_base.py | 280 ----- .../tests/api/identity/v3/__init__.py | 0 .../v3/test_application_credentials_rbac.py | 89 -- .../tests/api/identity/v3/test_auth_rbac.py | 45 - .../api/identity/v3/test_credentials_rbac.py | 96 -- .../v3/test_domain_configuration_rbac.py | 164 --- .../api/identity/v3/test_domains_rbac.py | 69 -- .../api/identity/v3/test_endpoints_rbac.py | 68 - .../identity/v3/test_ep_filter_groups_rbac.py | 109 -- .../v3/test_ep_filter_projects_rbac.py | 90 -- .../tests/api/identity/v3/test_groups_rbac.py | 121 -- .../identity/v3/test_oauth_consumers_rbac.py | 78 -- .../api/identity/v3/test_oauth_tokens_rbac.py | 138 --- .../api/identity/v3/test_policies_rbac.py | 67 - .../v3/test_policy_association_rbac.py | 152 --- .../api/identity/v3/test_project_tags_rbac.py | 96 -- .../api/identity/v3/test_projects_rbac.py | 67 - .../api/identity/v3/test_regions_rbac.py | 67 - .../identity/v3/test_role_assignments_rbac.py | 41 - .../tests/api/identity/v3/test_roles_rbac.py | 422 ------- .../api/identity/v3/test_services_rbac.py | 68 - .../identity/v3/test_tokens_negative_rbac.py | 97 -- .../tests/api/identity/v3/test_tokens_rbac.py | 67 - .../tests/api/identity/v3/test_trusts_rbac.py | 192 --- .../tests/api/identity/v3/test_users_rbac.py | 96 -- .../tests/api/image/__init__.py | 0 .../tests/api/image/rbac_base.py | 30 - .../test_image_namespace_objects_rbac.py | 106 -- .../test_image_namespace_property_rbac.py | 97 -- .../api/image/test_image_namespace_rbac.py | 75 -- .../image/test_image_namespace_tags_rbac.py | 108 -- .../image/test_image_resource_types_rbac.py | 69 -- .../api/image/test_images_member_rbac.py | 124 -- .../tests/api/image/test_images_rbac.py | 233 ---- .../tests/api/network/README.rst | 47 - .../tests/api/network/__init__.py | 0 .../tests/api/network/rbac_base.py | 84 -- .../api/network/test_address_scope_rbac.py | 154 --- .../tests/api/network/test_agents_rbac.py | 285 ----- .../test_auto_allocated_topology_rbac.py | 87 -- .../network/test_availability_zones_rbac.py | 48 - .../network/test_dscp_marking_rule_rbac.py | 121 -- .../test_flavor_service_profile_rbac.py | 77 -- .../tests/api/network/test_flavors_rbac.py | 120 -- .../api/network/test_floating_ips_rbac.py | 146 --- .../network/test_metering_label_rules_rbac.py | 120 -- .../api/network/test_metering_labels_rbac.py | 102 -- .../test_network_ip_availability_rbac.py | 64 - .../api/network/test_network_segments_rbac.py | 121 -- .../tests/api/network/test_networks_rbac.py | 479 -------- .../test_policy_bandwidth_limit_rule_rbac.py | 109 -- ...test_policy_minimum_bandwidth_rule_rbac.py | 112 -- .../tests/api/network/test_ports_rbac.py | 404 ------ .../tests/api/network/test_qos_rbac.py | 114 -- .../api/network/test_rbac_policies_rbac.py | 126 -- .../tests/api/network/test_routers_rbac.py | 418 ------- .../api/network/test_security_groups_rbac.py | 175 --- .../tests/api/network/test_segments_rbac.py | 136 -- .../api/network/test_service_profile_rbac.py | 73 -- .../network/test_service_providers_rbac.py | 29 - .../api/network/test_subnetpools_rbac.py | 180 --- .../tests/api/network/test_subnets_rbac.py | 103 -- .../tests/api/network/test_trunks_rbac.py | 201 --- .../tests/api/volume/__init__.py | 0 .../tests/api/volume/rbac_base.py | 94 -- .../api/volume/test_capabilities_rbac.py | 45 - .../api/volume/test_encryption_types_rbac.py | 119 -- .../api/volume/test_group_snapshots_rbac.py | 200 --- .../tests/api/volume/test_group_type_specs.py | 123 -- .../tests/api/volume/test_groups_rbac.py | 237 ---- .../tests/api/volume/test_limits_rbac.py | 55 - .../tests/api/volume/test_qos_rbac.py | 148 --- .../api/volume/test_quota_classes_rbac.py | 68 - .../api/volume/test_scheduler_stats_rbac.py | 44 - .../api/volume/test_snapshot_manage_rbac.py | 82 -- .../api/volume/test_snapshots_actions_rbac.py | 87 -- .../volume/test_snapshots_metadata_rbac.py | 110 -- .../api/volume/test_user_messages_rbac.py | 92 -- .../api/volume/test_volume_actions_rbac.py | 293 ----- .../api/volume/test_volume_basic_crud_rbac.py | 100 -- .../api/volume/test_volume_hosts_rbac.py | 41 - .../api/volume/test_volume_metadata_rbac.py | 168 --- .../api/volume/test_volume_quotas_rbac.py | 89 -- .../api/volume/test_volume_services_rbac.py | 47 - .../api/volume/test_volume_transfers_rbac.py | 110 -- .../volume/test_volume_types_access_rbac.py | 88 -- .../test_volume_types_extra_specs_rbac.py | 107 -- .../api/volume/test_volume_types_rbac.py | 62 - .../api/volume/test_volumes_backup_rbac.py | 256 ---- .../api/volume/test_volumes_extend_rbac.py | 40 - .../api/volume/test_volumes_manage_rbac.py | 124 -- .../api/volume/test_volumes_snapshots_rbac.py | 140 --- .../tests/scenario/__init__.py | 0 patrole_tempest_plugin/tests/unit/__init__.py | 0 patrole_tempest_plugin/tests/unit/base.py | 30 - patrole_tempest_plugin/tests/unit/fixtures.py | 158 --- .../unit/resources/admin_rbac_policy.json | 7 - .../unit/resources/alt_admin_rbac_policy.json | 5 - .../unit/resources/custom_rbac_policy.json | 14 - .../unit/resources/custom_rbac_policy.yaml | 13 - .../tests/unit/resources/rbac_roles.yaml | 10 - .../unit/resources/tenant_rbac_policy.json | 8 - .../tests/unit/test_hacking.py | 302 ----- .../tests/unit/test_policy_authority.py | 639 ---------- .../tests/unit/test_rbac_rule_validation.py | 1089 ----------------- .../tests/unit/test_rbac_utils.py | 347 ------ .../tests/unit/test_requirements_authority.py | 188 --- patrole_tempest_plugin/version.py | 18 - releasenotes/notes/.placeholder | 0 .../notes/0.1.0-pike-6590a2996b7c06d6.yaml | 14 - ...tra-hypervisor-tests-9374e5fcdb0266e2.yaml | 12 - ...e-delete-backup-test-7e896affd1471328.yaml | 11 - ...etadef-resource-type-7973621c5e8fff7f.yaml | 5 - ...mpest-plugin-clients-c031e232021b390c.yaml | 7 - ...-quota-classes-tests-3e61e671f6e131df.yaml | 5 - ...security-group-tests-ae5c07074e0ac849.yaml | 13 - ...ork-ports-rbac-tests-3f48ce1b6bda7694.yaml | 13 - ...al-router-rbac-tests-66ef013c54016326.yaml | 11 - ...ly-identity-v2-admin-6f382e38d7a690a4.yaml | 12 - ...pt_nova_new_policies-c61d1c3751ff1bf9.yaml | 18 - .../notes/agents-ca4a5e232ce242a5.yaml | 5 - ...oject-attribute-test-504f053c6ec95b85.yaml | 6 - ...le-rule-feature-flag-ebe8b44c0aa663a8.yaml | 16 - ...-discrete-exceptions-92aedb99d0a13f58.yaml | 25 - ...es-xena-feature-flag-4b799db683e2840f.yaml | 6 - ...va-policies-victoria-7a5f123238b099d9.yaml | 13 - ...nova_policies_ussuri-177582b3ded63411.yaml | 13 - ...nly-in-override-role-f7109a73f5ff70e2.yaml | 19 - ...tize-image-rbac-test-bdf1109e58a6c2e0.yaml | 5 - ...pute-snapshots-tests-86c137eb545707ee.yaml | 4 - .../config-opts-paths-01e2a5096a1579b8.yaml | 8 - .../notes/console-6db96c4e329c0ab2.yaml | 5 - ...e-enable-rbac-option-1e499bb0914cdee8.yaml | 13 - ...deprecate-rbac-group-148e222913dc74cc.yaml | 6 - ...ac-utils-switch-role-a959f7bb3ebab353.yaml | 13 - ...client-in-rbac-utils-087eda0658d18fa9.yaml | 6 - ...olicy-enforce-option-e15d2be4e753608e.yaml | 10 - ...agent-scheduler-test-842fc1df45799def.yaml | 5 - ...in-config-rbac-tests-8806ca7c159ddf94.yaml | 5 - .../notes/drop-py-2-7-d287ad9a325b132d.yaml | 6 - ...olicy-file-discovery-104cbfc64b55d605.yaml | 22 - .../encryption-types-c9a2d9a3c1996da4.yaml | 4 - ...of-support-for-stein-8b93f530ae9b7331.yaml | 12 - ...oint-filter-projects-7f64c88659ef0c30.yaml | 5 - ...er-groups-rbac-tests-bca28e9a055bbb8d.yaml | 13 - ...bility-zone-policies-2ec19e8bbb9ce158.yaml | 5 - ...ed-server-attributes-36623af87e714369.yaml | 5 - ...a-volume-types-tests-2e4538bed7348be4.yaml | 10 - ...or-manage-rbac-tests-eb78439316d67ab2.yaml | 8 - .../notes/flavor-rxtx-d7aadbb32a9f232c.yaml | 5 - ...ce-v1-api-deprecated-1aba7b6ae0b6e063.yaml | 4 - ...st-with-details-test-655e873cd881c2bb.yaml | 4 - ...mage-size-rbac-tests-545e5ace0d88ab34.yaml | 5 - .../notes/implied-roles-96a307a2b9fa2a40.yaml | 22 - ...ediate-train-release-c8f2da843a6e3809.yaml | 12 - ...diate-ussuri-release-8f7bb2140bca827c.yaml | 14 - .../notes/keypairs-c8355d9496f83f9f.yaml | 5 - ...cy_enforcement_rocky-b52fb471ac31189b.yaml | 7 - .../notes/lock-server-460767a02d15bb29.yaml | 5 - ...rbac-rule-validation-5d7c286788a95ee9.yaml | 7 - ...-volume-backup-tests-c3f10aa245df2a4b.yaml | 5 - ...multi-policy-support-4e5c8b4e9e25ad9d.yaml | 31 - .../multi-role-rbac-7f597c004a558956.yaml | 11 - ...ultiple-policy-files-9aa7f7583283739e.yaml | 17 - .../nova_volume_client-75e153a1c84e4ff8.yaml | 5 - ...s-create-backup-test-cd8037ea130c3d8d.yaml | 5 - ...le-and-validate-list-d3b80f773674a652.yaml | 37 - ...role-devstack-plugin-551c9af3325723c9.yaml | 6 - ...atrole-rocky-release-e6f36691306bec7e.yaml | 14 - ...atrole-stein-release-874b36f2fedcd2fb.yaml | 15 - ...atrole-train-release-7d493ff5039f1715.yaml | 17 - ...trole-ussuri-release-6a2ec4e5c357fb19.yaml | 16 - ...ole-victoria-release-e3dc105ed55a7c4c.yaml | 17 - ...role-wallaby-release-cbc6687e4aeff56a.yaml | 17 - ...patrole-xena-release-66df296a5d4f5e8e.yaml | 17 - ...patrole-yoga-release-1eacc82c6c1c668c.yaml | 18 - .../rbac-per-test-log-071a530e957c1c26.yaml | 28 - ...pute-extended-status-ef00256e58b66223.yaml | 11 - ...ute-extended-volumes-7f3ccab122d22737.yaml | 6 - ...s-for-network-agents-fbc899925b5948b1.yaml | 14 - ...for-quota-class-sets-20d874b185902308.yaml | 8 - ...ac-utils-refactoring-2f4f1e3b52fcae14.yaml | 49 - ...ove-admin-only-kwarg-919f1a4797318a33.yaml | 8 - ...olume-snapshot-tests-c204bc72779cb53a.yaml | 5 - ...-extensions-policies-fca3d31c7f5f1f6c.yaml | 23 - ...e-rbac-config-option-a5e46ce1053b7dea.yaml | 5 - ...d-error-codes-params-52071a83113934fd.yaml | 13 - ...precated-switch-role-148c9a5c6796857f.yaml | 6 - ...ve-identity-v2-tests-bac20fda1d85327a.yaml | 5 - ...e-named-policy-files-134f3045502e9ce9.yaml | 13 - ...ve-rbac-config-group-097c200f3db99fad.yaml | 5 - ...-strict-policy-check-480e3d664f7b2d96.yaml | 6 - ...s-stein-feature-flag-6cfebbf64ed525d7.yaml | 8 - ...wallaby-feature-flag-abf3045a0a3e3315.yaml | 7 - ...y-multi-role-support-0fe53fc49567e595.yaml | 37 - ...-metadata-rbac-tests-2404b5d13c492b62.yaml | 12 - .../service-provider-bc71da578e717c3a.yaml | 4 - ...tart-of-pike-support-360e27b4d192e3d2.yaml | 10 - ...rt-of-queens-support-6c379f2b9cafbf31.yaml | 11 - .../subnet-rbac-tests-6d3cf54e39a7b486.yaml | 10 - ...date_is_default_test-d3540a87469b6dc8.yaml | 5 - ...ort-deprecated-roles-eae9dc742cb4fa33.yaml | 7 - ...rt_requirements_yaml-a90e0188a19421ba.yaml | 12 - ...st_oauth_tokens_rbac-13e1d3b5decbaf79.yaml | 4 - .../test_tokens_rbac-63a93e507d079a03.yaml | 3 - .../test_tokens_rbac-7f36919b786e9ffc.yaml | 3 - ...te-group-volume-test-06c7475ccbe36aa8.yaml | 5 - ...e-services-rbac-test-57e69f9952c8746e.yaml | 5 - .../volume-summary-a3c3b010c1880bcb.yaml | 4 - ...n-policy-granularity-141ac283b9c0778e.yaml | 19 - ...e-upload-public-test-f8e741a838ae7607.yaml | 5 - ...v3-groups-rbac-tests-60bddf6fa509545d.yaml | 12 - ...-backup-test-cleanup-7ffa74ae3599e6df.yaml | 6 - ...volumes-client-tests-d697a4a75d3e1405.yaml | 8 - ...-policy-file-support-278d3edf64f98d69.yaml | 7 - releasenotes/source/_static/.placeholder | 0 releasenotes/source/_templates/.placeholder | 0 releasenotes/source/conf.py | 275 ----- releasenotes/source/index.rst | 21 - releasenotes/source/unreleased.rst | 5 - releasenotes/source/v0.1.0.rst | 6 - releasenotes/source/v0.10.0.rst | 6 - releasenotes/source/v0.11.0.rst | 6 - releasenotes/source/v0.12.0.rst | 6 - releasenotes/source/v0.13.0.rst | 6 - releasenotes/source/v0.2.0.rst | 6 - releasenotes/source/v0.3.0.rst | 6 - releasenotes/source/v0.4.0.rst | 6 - releasenotes/source/v0.5.0.rst | 6 - releasenotes/source/v0.6.0.rst | 6 - releasenotes/source/v0.7.0.rst | 6 - releasenotes/source/v0.8.0.rst | 6 - releasenotes/source/v0.9.0.rst | 6 - requirements.txt | 9 - setup.cfg | 32 - setup.py | 20 - test-requirements.txt | 11 - tox.ini | 134 -- 324 files changed, 10 insertions(+), 25345 deletions(-) delete mode 100644 .coveragerc delete mode 100644 .gitignore delete mode 100644 .mailmap delete mode 100644 .stestr.conf delete mode 100644 .zuul.yaml delete mode 100644 CONTRIBUTING.rst delete mode 100644 HACKING.rst delete mode 100644 LICENSE delete mode 100644 REVIEWING.rst delete mode 100644 babel.cfg delete mode 100644 devstack/README.rst delete mode 100644 devstack/plugin.sh delete mode 100644 devstack/settings delete mode 100644 doc/requirements.txt delete mode 100644 doc/source/HACKING.rst delete mode 100644 doc/source/REVIEWING.rst delete mode 100644 doc/source/_static/.keep delete mode 100755 doc/source/conf.py delete mode 100644 doc/source/configuration.rst delete mode 100644 doc/source/contributor/contributing.rst delete mode 100644 doc/source/field_guide/index.rst delete mode 100644 doc/source/field_guide/rbac.rst delete mode 100644 doc/source/framework/overview.rst delete mode 100644 doc/source/framework/policy_authority.rst delete mode 100644 doc/source/framework/rbac_authority.rst delete mode 100644 doc/source/framework/rbac_utils.rst delete mode 100644 doc/source/framework/rbac_validation.rst delete mode 100644 doc/source/framework/requirements_authority.rst delete mode 100644 doc/source/index.rst delete mode 100644 doc/source/installation.rst delete mode 100644 doc/source/multi-policy-validation.rst delete mode 120000 doc/source/overview.rst delete mode 100644 doc/source/rbac-overview.rst delete mode 100644 doc/source/test_writing_guide.rst delete mode 100644 etc/config-generator.patrole.conf delete mode 100644 etc/patrole.conf.sample delete mode 100644 lower-constraints.txt delete mode 100644 patrole_tempest_plugin/__init__.py delete mode 100644 patrole_tempest_plugin/config.py delete mode 100644 patrole_tempest_plugin/hacking/__init__.py delete mode 100644 patrole_tempest_plugin/hacking/checks.py delete mode 100644 patrole_tempest_plugin/plugin.py delete mode 100644 patrole_tempest_plugin/policy_authority.py delete mode 100644 patrole_tempest_plugin/rbac_authority.py delete mode 100644 patrole_tempest_plugin/rbac_exceptions.py delete mode 100644 patrole_tempest_plugin/rbac_rule_validation.py delete mode 100644 patrole_tempest_plugin/rbac_utils.py delete mode 100644 patrole_tempest_plugin/requirements_authority.py delete mode 100644 patrole_tempest_plugin/tests/__init__.py delete mode 120000 patrole_tempest_plugin/tests/api/README.rst delete mode 100644 patrole_tempest_plugin/tests/api/__init__.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/__init__.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/rbac_base.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_agents_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_aggregates_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_availability_zone_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_flavor_access_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_flavor_extra_specs_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_flavor_manage_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_floating_ip_pools_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_floating_ips_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_hosts_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_hypervisor_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_images_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_instance_usages_audit_log_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_limits_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_migrations_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_quota_class_sets_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_server_consoles_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_server_groups_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_server_metadata_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_server_migrations_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_server_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_server_volume_attachments_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_services_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_tenant_networks_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/compute/test_volume_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/__init__.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/rbac_base.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/__init__.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_application_credentials_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_auth_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_credentials_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_domain_configuration_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_domains_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_endpoints_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_ep_filter_groups_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_ep_filter_projects_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_groups_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_oauth_consumers_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_oauth_tokens_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_policies_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_policy_association_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_project_tags_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_projects_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_regions_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_role_assignments_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_services_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_tokens_negative_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_tokens_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_trusts_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/identity/v3/test_users_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/image/__init__.py delete mode 100644 patrole_tempest_plugin/tests/api/image/rbac_base.py delete mode 100644 patrole_tempest_plugin/tests/api/image/test_image_namespace_objects_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/image/test_image_namespace_property_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/image/test_image_namespace_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/image/test_image_namespace_tags_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/image/test_image_resource_types_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/image/test_images_member_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/image/test_images_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/README.rst delete mode 100644 patrole_tempest_plugin/tests/api/network/__init__.py delete mode 100644 patrole_tempest_plugin/tests/api/network/rbac_base.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_address_scope_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_agents_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_auto_allocated_topology_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_availability_zones_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_dscp_marking_rule_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_flavor_service_profile_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_flavors_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_floating_ips_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_metering_label_rules_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_metering_labels_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_network_ip_availability_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_network_segments_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_networks_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_policy_bandwidth_limit_rule_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_policy_minimum_bandwidth_rule_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_ports_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_qos_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_rbac_policies_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_routers_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_segments_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_service_profile_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_service_providers_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_subnets_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/network/test_trunks_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/__init__.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/rbac_base.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_capabilities_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_encryption_types_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_group_snapshots_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_group_type_specs.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_limits_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_quota_classes_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_scheduler_stats_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_snapshot_manage_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_snapshots_actions_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_snapshots_metadata_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_user_messages_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_quotas_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_services_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_types_access_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_types_extra_specs_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volume_types_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volumes_manage_rbac.py delete mode 100644 patrole_tempest_plugin/tests/api/volume/test_volumes_snapshots_rbac.py delete mode 100644 patrole_tempest_plugin/tests/scenario/__init__.py delete mode 100644 patrole_tempest_plugin/tests/unit/__init__.py delete mode 100644 patrole_tempest_plugin/tests/unit/base.py delete mode 100644 patrole_tempest_plugin/tests/unit/fixtures.py delete mode 100644 patrole_tempest_plugin/tests/unit/resources/admin_rbac_policy.json delete mode 100644 patrole_tempest_plugin/tests/unit/resources/alt_admin_rbac_policy.json delete mode 100644 patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.json delete mode 100644 patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.yaml delete mode 100644 patrole_tempest_plugin/tests/unit/resources/rbac_roles.yaml delete mode 100644 patrole_tempest_plugin/tests/unit/resources/tenant_rbac_policy.json delete mode 100644 patrole_tempest_plugin/tests/unit/test_hacking.py delete mode 100644 patrole_tempest_plugin/tests/unit/test_policy_authority.py delete mode 100644 patrole_tempest_plugin/tests/unit/test_rbac_rule_validation.py delete mode 100644 patrole_tempest_plugin/tests/unit/test_rbac_utils.py delete mode 100644 patrole_tempest_plugin/tests/unit/test_requirements_authority.py delete mode 100644 patrole_tempest_plugin/version.py delete mode 100644 releasenotes/notes/.placeholder delete mode 100644 releasenotes/notes/0.1.0-pike-6590a2996b7c06d6.yaml delete mode 100644 releasenotes/notes/add-extra-hypervisor-tests-9374e5fcdb0266e2.yaml delete mode 100644 releasenotes/notes/add-force-delete-backup-test-7e896affd1471328.yaml delete mode 100644 releasenotes/notes/add-metadef-resource-type-7973621c5e8fff7f.yaml delete mode 100644 releasenotes/notes/add-neutron-tempest-plugin-clients-c031e232021b390c.yaml delete mode 100644 releasenotes/notes/add-quota-classes-tests-3e61e671f6e131df.yaml delete mode 100644 releasenotes/notes/add-security-group-tests-ae5c07074e0ac849.yaml delete mode 100644 releasenotes/notes/additional-network-ports-rbac-tests-3f48ce1b6bda7694.yaml delete mode 100644 releasenotes/notes/additional-router-rbac-tests-66ef013c54016326.yaml delete mode 100644 releasenotes/notes/admin-only-identity-v2-admin-6f382e38d7a690a4.yaml delete mode 100644 releasenotes/notes/adopt_nova_new_policies-c61d1c3751ff1bf9.yaml delete mode 100644 releasenotes/notes/agents-ca4a5e232ce242a5.yaml delete mode 100644 releasenotes/notes/backup-project-attribute-test-504f053c6ec95b85.yaml delete mode 100644 releasenotes/notes/backwards-incompatible-rule-feature-flag-ebe8b44c0aa663a8.yaml delete mode 100644 releasenotes/notes/break-up-rbac-malformed-exception-into-discrete-exceptions-92aedb99d0a13f58.yaml delete mode 100644 releasenotes/notes/changed-cinder-policies-xena-feature-flag-4b799db683e2840f.yaml delete mode 100644 releasenotes/notes/changed-nova-policies-victoria-7a5f123238b099d9.yaml delete mode 100644 releasenotes/notes/changed_nova_policies_ussuri-177582b3ded63411.yaml delete mode 100644 releasenotes/notes/check-expected-errors-only-in-override-role-f7109a73f5ff70e2.yaml delete mode 100644 releasenotes/notes/communitize-image-rbac-test-bdf1109e58a6c2e0.yaml delete mode 100644 releasenotes/notes/compute-snapshots-tests-86c137eb545707ee.yaml delete mode 100644 releasenotes/notes/config-opts-paths-01e2a5096a1579b8.yaml delete mode 100644 releasenotes/notes/console-6db96c4e329c0ab2.yaml delete mode 100644 releasenotes/notes/deprecate-enable-rbac-option-1e499bb0914cdee8.yaml delete mode 100644 releasenotes/notes/deprecate-rbac-group-148e222913dc74cc.yaml delete mode 100644 releasenotes/notes/deprecate-rbac-utils-switch-role-a959f7bb3ebab353.yaml delete mode 100644 releasenotes/notes/deprecate-roles-client-in-rbac-utils-087eda0658d18fa9.yaml delete mode 100644 releasenotes/notes/deprecate-strict-policy-enforce-option-e15d2be4e753608e.yaml delete mode 100644 releasenotes/notes/dhcp-agent-scheduler-test-842fc1df45799def.yaml delete mode 100644 releasenotes/notes/domain-config-rbac-tests-8806ca7c159ddf94.yaml delete mode 100644 releasenotes/notes/drop-py-2-7-d287ad9a325b132d.yaml delete mode 100644 releasenotes/notes/dynamic-policy-file-discovery-104cbfc64b55d605.yaml delete mode 100644 releasenotes/notes/encryption-types-c9a2d9a3c1996da4.yaml delete mode 100644 releasenotes/notes/end-of-support-for-stein-8b93f530ae9b7331.yaml delete mode 100644 releasenotes/notes/endpoint-filter-projects-7f64c88659ef0c30.yaml delete mode 100644 releasenotes/notes/ep-filter-groups-rbac-tests-bca28e9a055bbb8d.yaml delete mode 100644 releasenotes/notes/extended-availability-zone-policies-2ec19e8bbb9ce158.yaml delete mode 100644 releasenotes/notes/extended-server-attributes-36623af87e714369.yaml delete mode 100644 releasenotes/notes/extra-volume-types-tests-2e4538bed7348be4.yaml delete mode 100644 releasenotes/notes/flavor-manage-rbac-tests-eb78439316d67ab2.yaml delete mode 100644 releasenotes/notes/flavor-rxtx-d7aadbb32a9f232c.yaml delete mode 100644 releasenotes/notes/glance-v1-api-deprecated-1aba7b6ae0b6e063.yaml delete mode 100644 releasenotes/notes/hypervisor-list-with-details-test-655e873cd881c2bb.yaml delete mode 100644 releasenotes/notes/image-size-rbac-tests-545e5ace0d88ab34.yaml delete mode 100644 releasenotes/notes/implied-roles-96a307a2b9fa2a40.yaml delete mode 100644 releasenotes/notes/intermediate-train-release-c8f2da843a6e3809.yaml delete mode 100644 releasenotes/notes/intermediate-ussuri-release-8f7bb2140bca827c.yaml delete mode 100644 releasenotes/notes/keypairs-c8355d9496f83f9f.yaml delete mode 100644 releasenotes/notes/keystone_policy_enforcement_rocky-b52fb471ac31189b.yaml delete mode 100644 releasenotes/notes/lock-server-460767a02d15bb29.yaml delete mode 100644 releasenotes/notes/merge-rbac-auth-with-rbac-rule-validation-5d7c286788a95ee9.yaml delete mode 100644 releasenotes/notes/more-volume-backup-tests-c3f10aa245df2a4b.yaml delete mode 100644 releasenotes/notes/multi-policy-support-4e5c8b4e9e25ad9d.yaml delete mode 100644 releasenotes/notes/multi-role-rbac-7f597c004a558956.yaml delete mode 100644 releasenotes/notes/multiple-policy-files-9aa7f7583283739e.yaml delete mode 100644 releasenotes/notes/nova_volume_client-75e153a1c84e4ff8.yaml delete mode 100644 releasenotes/notes/os-create-backup-test-cd8037ea130c3d8d.yaml delete mode 100644 releasenotes/notes/override-role-and-validate-list-d3b80f773674a652.yaml delete mode 100644 releasenotes/notes/patrole-devstack-plugin-551c9af3325723c9.yaml delete mode 100644 releasenotes/notes/patrole-rocky-release-e6f36691306bec7e.yaml delete mode 100644 releasenotes/notes/patrole-stein-release-874b36f2fedcd2fb.yaml delete mode 100644 releasenotes/notes/patrole-train-release-7d493ff5039f1715.yaml delete mode 100644 releasenotes/notes/patrole-ussuri-release-6a2ec4e5c357fb19.yaml delete mode 100644 releasenotes/notes/patrole-victoria-release-e3dc105ed55a7c4c.yaml delete mode 100644 releasenotes/notes/patrole-wallaby-release-cbc6687e4aeff56a.yaml delete mode 100644 releasenotes/notes/patrole-xena-release-66df296a5d4f5e8e.yaml delete mode 100644 releasenotes/notes/patrole-yoga-release-1eacc82c6c1c668c.yaml delete mode 100644 releasenotes/notes/rbac-per-test-log-071a530e957c1c26.yaml delete mode 100644 releasenotes/notes/rbac-tests-for-compute-extended-status-ef00256e58b66223.yaml delete mode 100644 releasenotes/notes/rbac-tests-for-compute-extended-volumes-7f3ccab122d22737.yaml delete mode 100644 releasenotes/notes/rbac-tests-for-network-agents-fbc899925b5948b1.yaml delete mode 100644 releasenotes/notes/rbac-tests-for-quota-class-sets-20d874b185902308.yaml delete mode 100644 releasenotes/notes/rbac-utils-refactoring-2f4f1e3b52fcae14.yaml delete mode 100644 releasenotes/notes/remove-admin-only-kwarg-919f1a4797318a33.yaml delete mode 100644 releasenotes/notes/remove-assisted-volume-snapshot-tests-c204bc72779cb53a.yaml delete mode 100644 releasenotes/notes/remove-deprecated-api-extensions-policies-fca3d31c7f5f1f6c.yaml delete mode 100644 releasenotes/notes/remove-deprecated-enable-rbac-config-option-a5e46ce1053b7dea.yaml delete mode 100644 releasenotes/notes/remove-deprecated-rules-expected-error-codes-params-52071a83113934fd.yaml delete mode 100644 releasenotes/notes/remove-deprecated-switch-role-148c9a5c6796857f.yaml delete mode 100644 releasenotes/notes/remove-identity-v2-tests-bac20fda1d85327a.yaml delete mode 100644 releasenotes/notes/remove-named-policy-files-134f3045502e9ce9.yaml delete mode 100644 releasenotes/notes/remove-rbac-config-group-097c200f3db99fad.yaml delete mode 100644 releasenotes/notes/remove-strict-policy-check-480e3d664f7b2d96.yaml delete mode 100644 releasenotes/notes/removed-keystone-policies-stein-feature-flag-6cfebbf64ed525d7.yaml delete mode 100644 releasenotes/notes/removed-nova-policies-wallaby-feature-flag-abf3045a0a3e3315.yaml delete mode 100644 releasenotes/notes/requirements-authority-multi-role-support-0fe53fc49567e595.yaml delete mode 100644 releasenotes/notes/server-metadata-rbac-tests-2404b5d13c492b62.yaml delete mode 100644 releasenotes/notes/service-provider-bc71da578e717c3a.yaml delete mode 100644 releasenotes/notes/start-of-pike-support-360e27b4d192e3d2.yaml delete mode 100644 releasenotes/notes/start-of-queens-support-6c379f2b9cafbf31.yaml delete mode 100644 releasenotes/notes/subnet-rbac-tests-6d3cf54e39a7b486.yaml delete mode 100644 releasenotes/notes/subnetpools_update_is_default_test-d3540a87469b6dc8.yaml delete mode 100644 releasenotes/notes/support-deprecated-roles-eae9dc742cb4fa33.yaml delete mode 100644 releasenotes/notes/support_requirements_yaml-a90e0188a19421ba.yaml delete mode 100644 releasenotes/notes/test_oauth_tokens_rbac-13e1d3b5decbaf79.yaml delete mode 100644 releasenotes/notes/test_tokens_rbac-63a93e507d079a03.yaml delete mode 100644 releasenotes/notes/test_tokens_rbac-7f36919b786e9ffc.yaml delete mode 100644 releasenotes/notes/update-group-volume-test-06c7475ccbe36aa8.yaml delete mode 100644 releasenotes/notes/volume-services-rbac-test-57e69f9952c8746e.yaml delete mode 100644 releasenotes/notes/volume-summary-a3c3b010c1880bcb.yaml delete mode 100644 releasenotes/notes/volume-type-encryption-policy-granularity-141ac283b9c0778e.yaml delete mode 100644 releasenotes/notes/volume-upload-public-test-f8e741a838ae7607.yaml delete mode 100644 releasenotes/notes/volume-v3-groups-rbac-tests-60bddf6fa509545d.yaml delete mode 100644 releasenotes/notes/volumes-backup-test-cleanup-7ffa74ae3599e6df.yaml delete mode 100644 releasenotes/notes/volumes-client-tests-d697a4a75d3e1405.yaml delete mode 100644 releasenotes/notes/yaml-policy-file-support-278d3edf64f98d69.yaml delete mode 100644 releasenotes/source/_static/.placeholder delete mode 100644 releasenotes/source/_templates/.placeholder delete mode 100644 releasenotes/source/conf.py delete mode 100644 releasenotes/source/index.rst delete mode 100644 releasenotes/source/unreleased.rst delete mode 100644 releasenotes/source/v0.1.0.rst delete mode 100644 releasenotes/source/v0.10.0.rst delete mode 100644 releasenotes/source/v0.11.0.rst delete mode 100644 releasenotes/source/v0.12.0.rst delete mode 100644 releasenotes/source/v0.13.0.rst delete mode 100644 releasenotes/source/v0.2.0.rst delete mode 100644 releasenotes/source/v0.3.0.rst delete mode 100644 releasenotes/source/v0.4.0.rst delete mode 100644 releasenotes/source/v0.5.0.rst delete mode 100644 releasenotes/source/v0.6.0.rst delete mode 100644 releasenotes/source/v0.7.0.rst delete mode 100644 releasenotes/source/v0.8.0.rst delete mode 100644 releasenotes/source/v0.9.0.rst delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 test-requirements.txt delete mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 4b521c72..00000000 --- a/.coveragerc +++ /dev/null @@ -1,6 +0,0 @@ -[run] -branch = True -source = patrole - -[report] -ignore_errors = True diff --git a/.gitignore b/.gitignore deleted file mode 100644 index cda7cbe8..00000000 --- a/.gitignore +++ /dev/null @@ -1,65 +0,0 @@ -*.py[cod] - -# C extensions -*.so - -# Packages -*.egg* -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg -lib -lib64 - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -cover/ -.coverage* -!.coveragerc -.tox -nosetests.xml -.testrepository -.venv - -# Translations -*.mo - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Complexity -output/*.html -output/*/index.html - -# Sphinx -doc/build -doc/source/_static/patrole.conf.sample -doc/source/framework/code/ - -# pbr generates these -AUTHORS -ChangeLog - -# Editors -*~ -.*.swp -.*sw? -*.idea - -# Files created by releasenotes build -releasenotes/build - -# Misc -.stestr -*.log diff --git a/.mailmap b/.mailmap deleted file mode 100644 index 47612b35..00000000 --- a/.mailmap +++ /dev/null @@ -1,5 +0,0 @@ -# Format is: -# -# -Felipe Monteiro -Felipe Monteiro diff --git a/.stestr.conf b/.stestr.conf deleted file mode 100644 index 76a6ac56..00000000 --- a/.stestr.conf +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -test_path=./patrole_tempest_plugin/tests/unit -group_regex=([^\.]*\.)* diff --git a/.zuul.yaml b/.zuul.yaml deleted file mode 100644 index 01f3f60d..00000000 --- a/.zuul.yaml +++ /dev/null @@ -1,246 +0,0 @@ -- job: - name: patrole-base - parent: devstack-tempest - description: | - Patrole base job for admin,member and reader roles. This job executes RBAC tests - for all the "core" services that Tempest covers, excluding Swift. - required-projects: - - name: opendev.org/openstack/tempest - - name: opendev.org/openstack/patrole - timeout: 7800 - roles: - - zuul: opendev.org/openstack/devstack - # Define common irrelevant files to use everywhere else - irrelevant-files: &patrole-irrelevant-files - - ^(test-|)requirements.txt$ - - ^.*\.rst$ - - ^doc/.* - - ^etc/.*$ - - ^patrole_tempest_plugin/tests/unit/.*$ - - ^patrole_tempest_plugin/hacking/.*$ - - ^releasenotes/.* - - ^setup.cfg$ - vars: - tempest_plugins: - - patrole - devstack_plugins: - patrole: https://opendev.org/openstack/patrole.git - devstack_services: - tempest: true - neutron: true - neutron-trunk: true - tempest_test_regex: (?!.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api) - # run the tempest all tox environment target with patrole regex - tox_envlist: all - # allows job to use the tempest version installed with devstack instead of pypi - # according to the requirements.txt - tox_extra_args: --sitepackages - -- job: - name: patrole-base-multinode - parent: tempest-multinode-full-py3 - description: |- - Patrole base job for multinode and "slow" tests where "slow" tests include: - - * Tests that take more than ~30 seconds to run. - * Tests that experience spurious failures related to servers, volumes, - backups and similar resources failing to build. - timeout: 7800 - branches: - - master - required-projects: - - opendev.org/openstack/devstack-gate - - opendev.org/openstack/tempest - - opendev.org/openstack/patrole - irrelevant-files: *patrole-irrelevant-files - vars: - tempest_plugins: - - patrole - devstack_plugins: - patrole: https://opendev.org/openstack/patrole.git - devstack_services: - tempest: true - neutron: true - tempest_concurrency: 1 - tempest_test_regex: (?=.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api) - tox_envlist: all - tox_extra_args: --sitepackages - -- job: - name: patrole-admin - parent: patrole-base - description: Patrole job for admin role. - vars: - devstack_localrc: - RBAC_TEST_ROLES: admin - # https://storyboard.openstack.org/#!/story/2009048 - tempest_exclude_regex: patrole_tempest_plugin.tests.api.volume.test_volume_actions_rbac.VolumesActionsV3RbacTest.test_force_detach_volume_from_instance - -- job: - name: patrole-member - parent: patrole-base - description: Patrole job for member role. - # This currently works from stable/pike onward. - branches: ^(?!stable/ocata).*$ - vars: - devstack_localrc: - RBAC_TEST_ROLES: member - # https://storyboard.openstack.org/#!/story/2009216 - tempest_exclude_regex: patrole_tempest_plugin.tests.api.volume.test_volume_types_extra_specs_rbac.VolumeTypesExtraSpecsRbacTest.test_show_volume_type_extra_specs - -- job: - name: patrole-reader - parent: patrole-base - description: Patrole job for reader role. - # This currently works from stable/stein onward. - branches: ^(?!stable/(ocata|pike|queens|rocky)).*$ - vars: - devstack_localrc: - RBAC_TEST_ROLES: reader - # https://storyboard.openstack.org/#!/story/2009216 - tempest_exclude_regex: patrole_tempest_plugin.tests.api.volume.test_volume_types_extra_specs_rbac.VolumeTypesExtraSpecsRbacTest.test_show_volume_type_extra_specs - -- job: - name: patrole-member-wallaby - parent: patrole-member - override-checkout: stable/wallaby - -- job: - name: patrole-member-victoria - parent: patrole-member - override-checkout: stable/victoria - -- job: - name: patrole-member-ussuri - parent: patrole-member - nodeset: openstack-single-node-bionic - override-checkout: stable/ussuri - vars: - # https://storyboard.openstack.org/#!/story/2009048 - tempest_exclude_regex: patrole_tempest_plugin.tests.api.volume.test_volume_actions_rbac.VolumesActionsV3RbacTest.test_force_detach_volume_from_instance - -- job: - name: patrole-multinode-admin - parent: patrole-base-multinode - voting: false - vars: - devstack_localrc: - RBAC_TEST_ROLES: admin - -- job: - name: patrole-multinode-member - parent: patrole-base-multinode - voting: false - vars: - devstack_localrc: - RBAC_TEST_ROLES: member - -- job: - name: patrole-multinode-reader - parent: patrole-base-multinode - voting: false - vars: - devstack_localrc: - RBAC_TEST_ROLES: reader - -- job: - name: patrole-py35-member - parent: patrole-base - description: Patrole py35 job for member role. - vars: - devstack_localrc: - # Use member for py35 because arguably negative testing is more - # important than admin, which is already covered by patrole-admin job. - RBAC_TEST_ROLES: member - USE_PYTHON3: true - devstack_services: - s-account: false - s-container: false - s-object: false - s-proxy: false - # Without Swift, c-bak cannot run (in the gate at least). - c-bak: false - -- job: - name: patrole-extension-base - parent: patrole-base - description: | - Patrole plugin job for admin and member roles which runs RBAC tests for - neutron-tempest-plugin APIs (if the plugin is installed). - - Covers Neutron extension functionality only. Should not be used for - supporting Neutron plugins like fwaas. - required-projects: - - name: opendev.org/openstack/tempest - - name: opendev.org/openstack/patrole - - name: opendev.org/openstack/neutron-tempest-plugin - vars: - tempest_plugins: - - patrole - - neutron-tempest-plugin - devstack_plugins: - neutron: https://opendev.org/openstack/neutron.git - patrole: https://opendev.org/openstack/patrole.git - neutron-tempest-plugin: https://opendev.org/openstack/neutron-tempest-plugin.git - devstack_services: - tempest: true - neutron: true - neutron-segments: true - neutron-qos: true - tempest_test_regex: (?=.*ExtRbacTest)(^patrole_tempest_plugin\.tests\.api) - -- job: - name: patrole-extension-admin - parent: patrole-extension-base - voting: false - vars: - devstack_localrc: - RBAC_TEST_ROLES: admin - -- job: - name: patrole-extension-member - parent: patrole-extension-base - voting: false - vars: - devstack_localrc: - RBAC_TEST_ROLES: member - -- job: - name: patrole-extension-reader - parent: patrole-extension-base - voting: false - vars: - devstack_localrc: - RBAC_TEST_ROLES: reader - -- project: - templates: - - openstack-cover-jobs - - openstack-python3-yoga-jobs - - check-requirements - - publish-openstack-docs-pti - - release-notes-jobs-python3 - check: - jobs: - - patrole-admin - - patrole-member - - patrole-reader - - patrole-member-wallaby - - patrole-member-victoria - - patrole-member-ussuri - - patrole-multinode-admin - - patrole-multinode-member - - patrole-multinode-reader - - patrole-extension-admin - - patrole-extension-member - - patrole-extension-reader - gate: - jobs: - - patrole-admin - - patrole-member - - patrole-reader - periodic-stable: - jobs: - - patrole-member-wallaby - - patrole-member-victoria - - patrole-member-ussuri diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index a138d666..00000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,19 +0,0 @@ -The source repository for this project can be found at: - - https://opendev.org/openstack/patrole - -Pull requests submitted through GitHub are not monitored. - -To start contributing to OpenStack, follow the steps in the contribution guide -to set up and use Gerrit: - - https://docs.openstack.org/contributors/code-and-documentation/quick-start.html - -Bugs should be filed on Storyboard: - - https://storyboard.openstack.org/#!/project/1040 - -For more specific information about contributing to this repository, see the -Patrole contributor guide: - - https://docs.openstack.org/patrole/latest/contributor/contributing.html diff --git a/HACKING.rst b/HACKING.rst deleted file mode 100644 index 5fb3faad..00000000 --- a/HACKING.rst +++ /dev/null @@ -1,170 +0,0 @@ -Patrole Coding Guide -==================== - -- Step 1: Read the OpenStack Style Commandments: ``__ -- Step 2: Review Tempest's Style Commandments: ``__ -- Step 3: Read on - -Patrole Specific Commandments ------------------------------- - -Patrole borrows the following commandments from Tempest; refer to -`Tempest's Commandments `__ -for more information: - -.. note:: - - The original Tempest Commandments do not include Patrole-specific paths. - Patrole-specific paths replace the Tempest-specific paths within Patrole's - hacking checks. - -- [T102] Cannot import OpenStack python clients in - ``patrole_tempest_plugin/tests/api`` -- [T105] Tests cannot use setUpClass/tearDownClass -- [T107] Check that a service tag isn't in the module path -- [T108] Check no hyphen at the end of rand_name() argument -- [T109] Cannot use testtools.skip decorator; instead use - ``decorators.skip_because`` from ``tempest.lib`` -- [T113] Check that tests use ``data_utils.rand_uuid()`` instead of - ``uuid.uuid4()`` -- [N322] Method's default argument shouldn't be mutable - -The following are Patrole's specific Commandments: - -- [P100] The ``rbac_rule_validation.action`` decorator must be applied to - all RBAC tests -- [P101] RBAC test filenames must end with "_rbac.py"; for example, - test_servers_rbac.py, not test_servers.py -- [P102] RBAC test class names must end in 'RbacTest' -- [P103] ``self.client`` must not be used as a client alias; this allows for - code that is more maintainable and easier to read -- [P104] RBAC `extension test class`_ names must end in 'ExtRbacTest' - -.. _extension test class: https://git.openstack.org/cgit/openstack/patrole/plain/patrole_tempest_plugin/tests/api/network/README.rst - -Supported OpenStack Components ------------------------------- - -Patrole only offers **in-tree** integration testing coverage for the following -components: - -* Cinder -* Glance -* Keystone -* Neutron -* Nova - -Patrole currently has no stable library, so reliance upon Patrole's framework -for external RBAC testing should be done with caution. Nonetheless, even when -Patrole has a stable library, it will only offer in-tree RBAC testing for -the components listed above. - -Role Overriding ---------------- - -Correct role overriding is vital to correct RBAC testing within Patrole. If a -test does not call ``self.override_role()`` within the RBAC test, followed -by the API endpoint that enforces the expected policy action, then the test is -**not** a valid Patrole test: The API endpoint under test will be performed -with admin role, which is always wrong unless ``CONF.patrole.rbac_test_role`` -is also admin. - -.. todo:: - - Patrole does not have a hacking check for role overriding, but one may be - added in the future. - -Branchless Patrole Considerations ---------------------------------- - -Like Tempest, Patrole is branchless. This is to better ensure API and RBAC -consistency between releases because API and RBAC behavior should not change -between releases. This means that the stable branches are also gated by the -Patrole master branch, which also means that proposed commits to Patrole must -work against both the master and all the currently supported stable branches -of the projects. As such there are a few special considerations that have to -be accounted for when pushing new changes to Patrole. - -1. New Tests for new features -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Patrole, like Tempest, *implicitly* tests new features because new policies -oftentimes accompany new features. The same `Tempest philosophy`_ regarding -feature flags and new features also applies to Patrole. - -.. _Tempest philosophy: https://docs.openstack.org/tempest/latest/HACKING.html#new-tests-for-new-features - -2. New Tests for new policies -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -When adding tests for new policies that were not in previous releases of the -projects, the new test must be properly skipped with a feature flag. This -involves using the ``testtools.skip(Unless|If)`` decorator above the test -to check if the required policy is enabled. Similarly, a feature flag must -be used whenever an OpenStack service covered by Patrole changes one of its -policies in a backwards-incompatible way. If there isn't a method of selecting -the new policy from the config file then there won't be a mechanism to disable -the test with older stable releases and the new test won't be able to merge. - -Introduction of a new feature flag requires specifying a default value for the -corresponding config option that is appropriate in the latest OpenStack -release. Because Patrole is branchless, the feature flag's default value will -need to be overridden to a value that is appropriate in earlier releases in -which the feature isn't available. In DevStack, this can be accomplished by -modifying Patrole's lib installation script for previous branches (because -DevStack is branched). - -3. Bug fix on core project needing Patrole changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -When trying to land a bug fix which changes a tested API you'll have to use the -following procedure: - - #. Propose change to the project, get a +2 on the change even with the - test failing Patrole side. - #. Propose skip to the relevant Patrole test which will only be approved - after the corresponding change in the project has a +2. - #. Land project change in master and all open stable branches - (if required). - #. Land changed test in Patrole. - -Otherwise the bug fix won't be able to land in the project. - -4. New Tests for existing features or policies -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The same `Tempest logic`_ regarding new tests for existing features or -policies also applies to Patrole. - -.. _Tempest logic: https://docs.openstack.org/tempest/latest/HACKING.html#new-tests-for-existing-features - - -Black Box vs. White Box Testing -------------------------------- - -Tempest is a `black box testing framework`_, meaning that it is concerned with -testing public API endpoints and doesn't concern itself with testing internal -implementation details. Patrole, as a Tempest plugin, also falls underneath -the category of black box testing. However, even with policy in code -documentation, some degree of white box testing is required in order to -correctly write RBAC tests. - -This is because :ref:`policy-in-code` documentation, while useful in many -respects, is usually quite brief and its main purpose is to help operators -understand how to customize policy configuration rather than to help -developers understand complex policy authorization work flows. For example, -policy in code documentation doesn't make deriving -:ref:`multiple policies ` easy. Such documentation also -doesn't usually mention that a specific parameter needs to be set, or that a -particular microversion must be enabled, or that a particular set of -prerequisite API or policy actions must be executed, in order for the policy -under test to be enforced by the server. This means that test writers must -account for the internal RBAC implementation in API code in order to correctly -understand the complete RBAC work flow within an API. - -Besides, as mentioned :ref:`elsewhere ` in this -documentation, not all services currently implement policy in code, making -some degree of white box testing a "necessary evil" for writing robust RBAC -tests. - -.. _black box testing framework: https://docs.openstack.org/tempest/latest/HACKING.html#negative-tests diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 68c771a0..00000000 --- a/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - diff --git a/README.rst b/README.rst index ef0ff001..e85d62c0 100644 --- a/README.rst +++ b/README.rst @@ -1,251 +1,10 @@ -Patrole - RBAC Integration Tempest Plugin -========================================= - -Patrole is a set of integration tests to be run against a live OpenStack -cluster. It has a battery of tests dedicated to validating the correctness and -integrity of the cloud's RBAC implementation. - -More importantly, Patrole is a security validation tool for verifying that -Role-Based Access Control is correctly configured and enforced in an OpenStack -cloud. It runs `Tempest`_-based API tests using specified RBAC roles, thus -allowing deployments to verify that only intended roles have access to those -APIs. - -Patrole is currently undergoing heavy development. As more projects move -toward policy in code, Patrole will align its testing with the appropriate -documentation. - -* Free software: Apache license -* Documentation: https://docs.openstack.org/patrole/latest -* Source: https://opendev.org/openstack/patrole -* Bugs: https://storyboard.openstack.org/#!/project/openstack/patrole -* Release notes: https://docs.openstack.org/releasenotes/patrole/ - -Team and repository tags ------------------------- - -.. image:: https://governance.openstack.org/tc/badges/patrole.svg - :target: https://governance.openstack.org/tc/reference/tags/index.html - -.. _design-principles: - -Design Principles ------------------ - -As a `Tempest plugin`_, Patrole borrows some design principles from `Tempest design principles`_, -but not all, as its testing scope is confined to policies. - -* *Stability*. Patrole uses OpenStack public interfaces. Tests in Patrole - should only touch public OpenStack APIs. -* *Atomicity*. Patrole tests should be atomic: they should test policies in - isolation. Unlike Tempest, a Patrole test strives to only call a single - endpoint at a time. This is because it is important to validate each policy - is authorized correctly and the best way to do that is to validate each - policy alone, to avoid test contamination. -* *Complete coverage*. Patrole should validate all policy in code defaults. For - testing, Patrole uses the API-to-policy mapping contained in each project's - `policy in code`_ documentation where applicable. - - For example, Nova's policy in code documentation is located in the - `Nova repository`_ under ``nova/policies``. Likewise, Keystone's policy in - code documentation is located in the `Keystone repository`_ under - ``keystone/common/policies``. The other OpenStack services follow the same - directory layout pattern with respect to policy in code. - - .. note:: - - Realistically this is not always possible because some services have - not yet moved to policy in code. - -* *Customizable*. Patrole should be able to validate custom policy overrides to - ensure that those overrides enhance rather than undermine the cloud's RBAC - configuration. In addition, Patrole should be able to validate any role. -* *Self-cleaning*. Patrole should attempt to clean up after itself; whenever - possible we should tear down resources when done. - - .. note:: - - Patrole modifies roles dynamically in the background, which affects - pre-provisioned credentials. Work is currently underway to clean up - modifications made to pre-provisioned credentials. - -* *Self-testing*. Patrole should be self-testing. - -.. _Tempest plugin: https://docs.openstack.org/tempest/latest/plugin.html -.. _Tempest design principles: https://docs.openstack.org/tempest/latest/overview.html#design-principles -.. _policy in code: https://specs.openstack.org/openstack/oslo-specs/specs/newton/policy-in-code.html -.. _Nova repository: https://opendev.org/openstack/nova/src/branch/master/nova/policies -.. _Keystone repository: https://opendev.org/openstack/keystone/src/branch/master/keystone/common/policies - -Features --------- -* Validation of default policy definitions located in policy.json files. -* Validation of in-code policy definitions. -* Validation of custom policy file definitions that override default policy - definitions. -* Built-in positive and negative testing. Positive and negative testing - are performed using the same tests and role-switching. -* Valdation of custom roles as well as default OpenStack roles. - -.. note:: - - Patrole does not yet support policy.yaml files, the new file format for - policy files in OpenStack. - -How It Works ------------- -Patrole leverages ``oslo.policy`` (OpenStack's policy enforcement engine) to -determine whether a given role is allowed to perform a policy action, given a -specific role and OpenStack service. The output from ``oslo.policy`` (the -expected result) and the actual result from test execution are compared to -each other: if both results match, then the test passes; else it fails. - -Terminology -^^^^^^^^^^^ -* Expected Result - The expected result of a given test. -* Actual Result - The actual result of a given test. -* Final Result - A match between both expected and actual results. A mismatch - in the expected result and the actual result will result in a test failure. - - * Expected: Pass | Actual: Pass - Test Case Success - * Expected: Pass | Actual: Fail - Test Case Under-Permission Failure - * Expected: Fail | Actual: Pass - Test Case Over-Permission Failure - * Expected: Fail | Actual: Fail (Expected exception) - Test Case Success - * Expected: Fail | Actual: Fail (Unexpected exception) - Test Case Failure - -Quickstart ----------- -To run Patrole, you must first have `Tempest`_ installed and configured -properly. Please reference `Tempest_quickstart`_ guide to do so. Follow all -the steps outlined therein. Afterward, proceed with the steps below. - -#. You first need to install Patrole. This is done with pip after you check out - the Patrole repo:: - - $ git clone https://opendev.org/openstack/patrole - $ pip install patrole/ - - This can be done within a venv. - - .. note:: - - You may also install Patrole from source code by running:: - - pip install -e patrole/ - -#. Next you must properly configure Patrole, which is relatively - straightforward. For details on configuring Patrole refer to the - `Patrole Configuration `_. - -#. Once the configuration is done you're now ready to run Patrole. This can - be done using the `tempest_run`_ command. This can be done by running:: - - $ tempest run --regex '^patrole_tempest_plugin\.tests\.api' - - There is also the option to use testr directly, or any `testr`_ based test - runner, like `ostestr`_. For example, from the workspace dir run:: - - $ stestr --regex '(?!.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api))' - - will run the same set of tests as the default gate jobs. - - You can also run Patrole tests using `tox`_, but as Patrole needs access to - global packages use ``--sitepackages`` argument. To do so, ``cd`` into the - **Tempest** directory and run:: - - $ tox -eall --sitepackages -- patrole_tempest_plugin.tests.api - - .. note:: - - It is possible to run Patrole via ``tox -eall`` in order to run Patrole - isolated from other plugins. This can be accomplished by including the - installation of services that currently use policy in code -- for example, - Nova and Keystone. For example:: - - $ tox -evenv-tempest -- pip install /opt/stack/patrole /opt/stack/keystone /opt/stack/nova - $ tox -eall -- patrole_tempest_plugin.tests.api - -#. Log information from tests is captured in ``tempest.log`` under the Tempest - repository. Some Patrole debugging information is captured in that log - related to expected test results and `Role Overriding `_. - - More detailed RBAC testing log output is emitted to ``patrole.log`` under - the Patrole repository. To configure Patrole's logging, see the - `Patrole Configuration Guide `_. - -.. _Tempest: https://opendev.org/openstack/tempest/ -.. _Tempest_quickstart: https://docs.openstack.org/tempest/latest/overview.html#quickstart -.. _tempest_run: https://docs.openstack.org/tempest/latest/run.html -.. _testr: https://testrepository.readthedocs.org/en/latest/MANUAL.html -.. _ostestr: https://docs.openstack.org/os-testr/latest/ -.. _tox: https://tox.readthedocs.io/en/latest/ - -RBAC Tests ----------- - -To change the roles that the patrole tests are being run as, edit -``rbac_test_roles`` in the ``patrole`` section of tempest.conf: :: - - [patrole] - rbac_test_roles = member,reader - ... - -.. note:: - - The ``rbac_test_roles`` is service-specific. member, for example, - is an arbitrary role, but by convention is used to designate the default - non-admin role in the system. Most Patrole tests should be run with - **admin** and **member** roles. However, other services may use entirely - different roles or role combinations. - -For more information about RBAC, reference the `rbac-overview`_ -documentation page. - -For information regarding which projects Patrole offers RBAC testing for, -reference the `HACKING`_ documentation page. - -.. _rbac-overview: https://docs.openstack.org/patrole/latest/rbac-overview.html -.. _HACKING: https://docs.openstack.org/patrole/latest/HACKING.html#supported-openstack-components - -Unit Tests ----------- - -Patrole also has a set of unit tests which test the Patrole code itself. These -tests can be run by specifying the test discovery path:: - - $ stestr --test-path ./patrole_tempest_plugin/tests/unit run - -By setting ``--test-path`` option to ``./patrole_tempest_plugin/tests/unit`` -it specifies that test discovery should only be run on the unit test directory. - -Alternatively, there are the py27 and py35 tox jobs which will run the unit -tests with the corresponding version of Python. - -One common activity is to just run a single test; you can do this with tox -simply by specifying to just run py27 or py35 tests against a single test:: - - $ tox -e py27 -- -n patrole_tempest_plugin.tests.unit.test_rbac_utils.RBACUtilsTest.test_override_role_with_missing_admin_role - -Or all tests in the test_rbac_utils.py file:: - - $ tox -e py27 -- -n patrole_tempest_plugin.tests.unit.test_rbac_utils - -You may also use regular expressions to run any matching tests:: - - $ tox -e py27 -- test_rbac_utils - -For more information on these options and details about stestr, please see the -`stestr documentation `_. - -Release Versioning ------------------- -`Patrole Release Notes `_ -shows which changes have been released for each version. - -Patrole's release versioning follows Tempest's conventions. Like Tempest, -Patrole is branchless and uses versioning instead. - -Storyboard ----------- -Bugs and enhancements are tracked via Patrole's -`Storyboard Page `_. +This project is no longer maintained. + +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". + +For any further questions, please email +openstack-discuss@lists.openstack.org or join #openstack-dev on +OFTC. diff --git a/REVIEWING.rst b/REVIEWING.rst deleted file mode 100644 index f8ea144c..00000000 --- a/REVIEWING.rst +++ /dev/null @@ -1,189 +0,0 @@ -Reviewing Patrole Code -====================== -To start read the `OpenStack Common Review Checklist -`_ - - -Ensuring code is executed -------------------------- -Any new test or change to an existing test has to be verified in the gate. This -means that the first thing to check with any change is that a gate job actually -runs it. Tests which aren't executed either because of configuration or skips -should not be accepted. - - -Execution time --------------- -Along with checking that the jobs log that a new test is actually executed, -also pay attention to the execution time of that test. Patrole already runs -hundreds of tests per job in its check and gate pipelines and it is important -that the overall runtime of the jobs be constrained as much as possible. -Consider applying the ``@decorators.attr(type='slow')`` -`test attribute decorator`_ to a test if its runtime is longer than 30 seconds. - -.. _test attribute decorator: https://docs.openstack.org/tempest/latest/HACKING.html#test-attributes - - -Unit Tests ----------- -For any change that adds new functionality to common functionality unit tests -are required. This is to ensure we don't introduce future regressions and to -test conditions which we may not hit in the gate runs. - - -API Stability -------------- -Tests should only be added for published stable APIs. If a patch contains -tests for an API which hasn't been marked as stable or for an API which -doesn't conform to the `API stability guidelines -`_ then it -should not be approved. - -Similarly, tests should only be added for policies that are covered by -`policy in code documentation -`_. -Any existing tests that test policies not covered by such documentation -are either: - -* part of a service that has not yet migrated to policy in code; or -* legacy in the sense that they were created prior to policy in code - -For the first bullet, the tests should not be considered stable, but should be -kept around to maintain coverage. These tests are a best-effort attempt at -offering RBAC test coverage for the service that has not yet migrated to -policy in code. - -For the second bullet, the tests should be updated to conform to policy in -code documentation, if applicable. - - -Reject Copy and Paste Test Code -------------------------------- -When creating new tests that are similar to existing tests it is tempting to -simply copy the code and make a few modifications. This increases code size and -the maintenance burden. Such changes should not be approved if it is easy to -abstract the duplicated code into a function or method. - - -Tests overlap -------------- -When a new test is being proposed, question whether this feature is not already -tested with Patrole. Patrole has more than 600 tests, spread amongst many -directories, so it's easy to introduce test duplication. - -Test Duplication -^^^^^^^^^^^^^^^^ - -Test duplication means: - -* testing an API endpoint in more than one test -* testing the same policy in more than one test - -For the first bullet, try to avoid calling the same API inside the -``self.override_role()`` call. - -.. note:: - - If the same API is tested against different policies, consider combining - the different tests into only 1 test, that tests the API against all - the policies it enforces. - -For the second bullet, try to avoid testing the same policies across multiple -tests. - -.. note:: - - This is not always possible since policy granularity doesn't exist for all - APIs. In cases where policy granularity doesn't exist, make sure that the - policy overlap only exists for the non-granular APIs that enforce the same - policy. - - -Being explicit --------------- -When tests are being added that depend on a configurable feature or extension, -polling the API to discover that it is enabled should not be done. This will -just result in bugs being masked because the test can be skipped automatically. -Instead the config file should be used to determine whether a test should be -skipped or not. Do not approve changes that depend on an API call to determine -whether to skip or not. - - -Multi-Policy Guidelines ------------------------ - -Care should be taken when using multiple policies in an RBAC test. The -following guidelines should be followed before deciding to add multiple -policies to a Patrole test. - -.. _general-multi-policy-guidelines: - -General Multi-policy API Code Guidelines -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The list below enumerates guidelines beginning with those with the highest -priority and ending with those with the lowest priority. A higher priority -item takes precedence over lower priority items. - -#. Order the policies in the ``rules`` parameter chronologically with respect - to the order they're called by the API endpoint under test. -#. Only use policies that map to the API by referencing the appropriate policy - in code documentation. -#. Only include the minimum number of policies needed to test the API - correctly: don't add extraneous policies. -#. If possible, only use policies that directly relate to the API. If the - policies are used across multiple APIs, try to omit it. If a "generic" - policy needs to be added to get the test to pass, then this is fair game. -#. Limit the number of policies to a reasonable number, such as 3. - -Neutron Multi-policy API Code Guidelines -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Because Neutron can raise a 403 or 404 following failed authorization, Patrole -uses the ``expected_error_codes`` parameter to accommodate this behavior. -Each policy action enumerated in ``rules`` must have a corresponding entry -in ``expected_error_codes``. Each expected error code must be either a 403 or a -404, which indicates that, when policy enforcement fails for the corresponding -policy action, that error code is expected by Patrole. For more information -about these parameters, see :ref:`rbac-validation`. - -The list below enumerates additional multi-policy guidelines that apply in -particular to Neutron. A higher priority item takes precedence over lower -priority items. - -#. Order the expected error codes in the ``expected_error_codes`` parameter - chronologically with respect to the order each corresponding policy in - ``rules`` is authorized by the API under test. -#. Ensure the :ref:`neutron-multi-policy-validation` is followed when - determining the expected error code for each corresponding policy. - -The same guidelines under :ref:`general-multi-policy-guidelines` should be -applied afterward. - - -Release Notes -------------- -Release notes are how we indicate to users and other consumers of Patrole what -has changed in a given release. There are certain types of changes that -require release notes and we should not approve them without including a release -note. These include but aren't limited to, any addition, deprecation or removal -from the framework code, any change to configuration options (including -deprecation), major feature additions, and anything backwards incompatible or -would require a user to take note or do something extra. - - -Deprecated Code ---------------- -Sometimes we have some bugs in deprecated code. Basically, we leave it. Because -we don't need to maintain it. However, if the bug is critical, we might need to -fix it. When it will happen, we will deal with it on a case-by-case basis. - - -When to approve ---------------- -* Every patch can be approved with single +2 which means single reviewer can approve. -* It's OK to hold off on an approval until a subject matter expert reviews it. -* If a patch has already been approved but requires a trivial rebase to merge, - you do not have to wait for a +2, since the patch has already had +2's. With - single +2 rule, this means that author can also approve this case if he/she has - approve rights. diff --git a/babel.cfg b/babel.cfg deleted file mode 100644 index 15cd6cb7..00000000 --- a/babel.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[python: **.py] - diff --git a/devstack/README.rst b/devstack/README.rst deleted file mode 100644 index 490f8333..00000000 --- a/devstack/README.rst +++ /dev/null @@ -1,25 +0,0 @@ -==================== -Enabling in Devstack -==================== - -.. warning:: - - The ``stack.sh`` script must be run in a disposable VM that is not - being created automatically. See the `README file`_ in the DevStack - repository for more information. - -1. Download DevStack:: - - git clone https://git.openstack.org/openstack-dev/devstack.git - cd devstack - -2. Patrole can be installed like any other DevStack plugin by including the - ``enable_plugin`` directive inside local.conf:: - - > cat local.conf - [[local|localrc]] - enable_plugin patrole https://git.openstack.org/openstack/patrole - -3. Run ``stack.sh`` found in the DevStack repo. - -.. _README file: https://git.openstack.org/cgit/openstack-dev/devstack/plain/README.rst diff --git a/devstack/plugin.sh b/devstack/plugin.sh deleted file mode 100644 index 9ccc4d73..00000000 --- a/devstack/plugin.sh +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/env bash -# Plugin file for Patrole Tempest plugin -# -------------------------------------- - -# Dependencies: -# ``functions`` file -# ``DEST`` must be defined - -# Save trace setting -XTRACE=$(set +o | grep xtrace) -set -o xtrace - -function install_patrole_tempest_plugin { - setup_package $PATROLE_DIR -e - - if [[ ${DEVSTACK_SERIES} == 'pike' ]]; then - IFS=',' read -ra roles_array <<< "$RBAC_TEST_ROLES" - RBAC_TEST_ROLES="" - for i in "${roles_array[@]}"; do - if [[ $i == "member" ]]; then - i="Member" - fi - RBAC_TEST_ROLES="$i,$RBAC_TEST_ROLES" - done - - # Policies used by Patrole testing that were changed in a backwards-incompatible way. - # TODO(felipemonteiro): Remove these once stable/pike becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled create_port_fixed_ips_ip_address_policy False - iniset $TEMPEST_CONFIG policy-feature-enabled update_port_fixed_ips_ip_address_policy False - iniset $TEMPEST_CONFIG policy-feature-enabled limits_extension_used_limits_policy False - iniset $TEMPEST_CONFIG policy-feature-enabled volume_extension_volume_actions_attach_policy False - iniset $TEMPEST_CONFIG policy-feature-enabled volume_extension_volume_actions_reserve_policy False - iniset $TEMPEST_CONFIG policy-feature-enabled volume_extension_volume_actions_unreserve_policy False - - # TODO(cl566n): Remove these once stable/pike becomes EOL. - # These policies were removed in Stein but are available in Pike. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_stein False - iniset $TEMPEST_CONFIG policy-feature-enabled removed_keystone_policies_stein False - iniset $TEMPEST_CONFIG policy-feature-enabled added_cinder_policies_stein False - - # TODO(rb560u): Remove this once stable/pike becomes EOL. - # Make the 'test_list_trusts' test backwards compatible. - # The Keystone Trust API is enforced differently depending on passed - # arguments - iniset $TEMPEST_CONFIG policy-feature-enabled keystone_policy_enforcement_train False - - # TODO(rb560u): Remove this once stable/pike becomes EOL. - # These policies were removed in Ussuri but are available in Pike. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_ussuri False - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_victoria False - - # TODO(gmann): Remove these once stable/victoria becomes EOL. - # These policies were removed in Wallaby. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_wallaby False - fi - - if [[ ${DEVSTACK_SERIES} == 'queens' ]]; then - IFS=',' read -ra roles_array <<< "$RBAC_TEST_ROLES" - RBAC_TEST_ROLES="" - for i in "${roles_array[@]}"; do - if [[ $i == "member" ]]; then - i="Member" - fi - RBAC_TEST_ROLES="$i,$RBAC_TEST_ROLES" - done - - # TODO(cl566n): Remove these once stable/queens becomes EOL. - # These policies were removed in Stein but are available in Queens. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_stein False - iniset $TEMPEST_CONFIG policy-feature-enabled removed_keystone_policies_stein False - iniset $TEMPEST_CONFIG policy-feature-enabled added_cinder_policies_stein False - - # TODO(rb560u): Remove this once stable/queens becomes EOL. - # Make the 'test_list_trusts' test backwards compatible. - # The Keystone Trust API is enforced differently depending on passed - # arguments - iniset $TEMPEST_CONFIG policy-feature-enabled keystone_policy_enforcement_train False - - # TODO(rb560u): Remove this once stable/queens becomes EOL. - # These policies were removed in Ussuri but are available in Queens. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_ussuri False - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_victoria False - - # TODO(gmann): Remove these once stable/victoria becomes EOL. - # These policies were removed in Wallaby. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_wallaby False - - # TODO(gmann): Remove these once stable/xena becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_cinder_policies_xena False - fi - - if [[ ${DEVSTACK_SERIES} == 'rocky' ]]; then - # TODO(cl566n): Policies used by Patrole testing. Remove these once stable/rocky becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_stein False - iniset $TEMPEST_CONFIG policy-feature-enabled added_cinder_policies_stein False - iniset $TEMPEST_CONFIG policy-feature-enabled removed_keystone_policies_stein False - - # TODO(rb560u): Remove this once stable/rocky becomes EOL. - # Make the 'test_list_trusts' test backwards compatible. - # The Keystone Trust API is enforced differently depending on passed - # arguments - iniset $TEMPEST_CONFIG policy-feature-enabled keystone_policy_enforcement_train False - - # TODO(rb560u): Remove this once stable/rocky becomes EOL. - # These policies were removed in Ussuri but are available in Rocky. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_ussuri False - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_victoria False - - # TODO(gmann): Remove these once stable/victoria becomes EOL. - # These policies were removed in Wallaby. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_wallaby False - - # TODO(gmann): Remove these once stable/xena becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_cinder_policies_xena False - fi - - if [[ ${DEVSTACK_SERIES} == 'stein' ]]; then - # TODO(rb560u): Remove this once stable/stein becomes EOL. - # Make the 'test_list_trusts' test backwards compatible. - # The Keystone Trust API is enforced differently depending on passed - # arguments - iniset $TEMPEST_CONFIG policy-feature-enabled keystone_policy_enforcement_train False - - # TODO(rb560u): Remove this once stable/stein becomes EOL. - # These policies were removed in Ussuri but are available in Stein. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_ussuri False - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_victoria False - - # TODO(gmann): Remove these once stable/victoria becomes EOL. - # These policies were removed in Wallaby. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_wallaby False - # TODO(gmann): Remove these once stable/xena becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_cinder_policies_xena False - fi - - if [[ ${DEVSTACK_SERIES} == 'train' ]]; then - # Remove this once stable/train becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_ussuri False - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_victoria False - # TODO(gmann): Remove these once stable/victoria becomes EOL. - # These policies were removed in Wallaby. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_wallaby False - # TODO(gmann): Remove these once stable/xena becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_cinder_policies_xena False - fi - - if [[ ${DEVSTACK_SERIES} == 'ussuri' ]]; then - # Remove this once stable/ussuri becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_nova_policies_victoria False - # TODO(gmann): Remove these once stable/victoria becomes EOL. - # These policies were removed in Wallaby. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_wallaby False - # TODO(gmann): Remove these once stable/xena becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_cinder_policies_xena False - fi - - if [[ ${DEVSTACK_SERIES} == 'victoria' ]]; then - # TODO(gmann): Remove these once stable/victoria becomes EOL. - # These policies were removed in Wallaby. - iniset $TEMPEST_CONFIG policy-feature-enabled removed_nova_policies_wallaby False - # TODO(gmann): Remove these once stable/xena becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_cinder_policies_xena False - fi - if [[ ${DEVSTACK_SERIES} == 'wallaby' ]]; then - # TODO(gmann): Remove these once stable/xena becomes EOL. - iniset $TEMPEST_CONFIG policy-feature-enabled changed_cinder_policies_xena False - fi - iniset $TEMPEST_CONFIG patrole rbac_test_roles $RBAC_TEST_ROLES -} - -if is_service_enabled tempest; then - if [[ "$1" == "stack" && "$2" == "test-config" ]]; then - echo_summary "Installing Patrole Tempest plugin" - install_patrole_tempest_plugin - fi -fi - -# Restore xtrace -$XTRACE diff --git a/devstack/settings b/devstack/settings deleted file mode 100644 index 670e878f..00000000 --- a/devstack/settings +++ /dev/null @@ -1,8 +0,0 @@ -# Settings needed for the Patrole Tempest plugin -# ---------------------------------------------- - -PATROLE_DIR=$DEST/patrole -TEMPEST_DIR=$DEST/tempest -TEMPEST_CONFIG_DIR=${TEMPEST_CONFIG_DIR:-$TEMPEST_DIR/etc} -TEMPEST_CONFIG=$TEMPEST_CONFIG_DIR/tempest.conf -RBAC_TEST_ROLE=${RBAC_TEST_ROLE:-admin} diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index ae5457e7..00000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -sphinx>=2.0.0,!=2.1.0 # BSD -openstackdocstheme>=2.2.0 # Apache-2.0 -reno>=3.1.0 # Apache-2.0 -sphinxcontrib-apidoc>=0.2.0 # BSD -sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD diff --git a/doc/source/HACKING.rst b/doc/source/HACKING.rst deleted file mode 100644 index 8777875b..00000000 --- a/doc/source/HACKING.rst +++ /dev/null @@ -1,5 +0,0 @@ -==================== -Patrole Coding Guide -==================== - -.. include:: ../../HACKING.rst diff --git a/doc/source/REVIEWING.rst b/doc/source/REVIEWING.rst deleted file mode 100644 index e8e3c1a7..00000000 --- a/doc/source/REVIEWING.rst +++ /dev/null @@ -1,5 +0,0 @@ -====================== -Reviewing Patrole Code -====================== - -.. include:: ../../REVIEWING.rst diff --git a/doc/source/_static/.keep b/doc/source/_static/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100755 index ff8c0252..00000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- -# 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 os -import sys - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('../../')) -sys.path.insert(0, os.path.abspath('../')) -sys.path.insert(0, os.path.abspath('./')) - -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.todo', - 'sphinx.ext.viewcode', - 'sphinxcontrib.rsvgconverter', - 'openstackdocstheme', - 'oslo_config.sphinxconfiggen', - 'sphinxcontrib.apidoc', -] - -# sphinxcontrib.apidoc options -apidoc_module_dir = '../../patrole_tempest_plugin' -apidoc_output_dir = 'framework/code' -apidoc_excluded_paths = [ - 'hacking', - 'hacking/*', - 'tests', - 'tests/*', - 'config.py', - 'plugin.py', - 'version.py' -] -apidoc_separate_modules = True - -config_generator_config_file = '../../etc/config-generator.patrole.conf' -sample_config_basename = '_static/patrole' - -# autodoc generation is a bit aggressive and a nuisance when doing heavy -# text edit cycles. -# execute "export SPHINX_DEBUG=1" in your terminal to disable - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. - -copyright = u'2017, Patrole Developers' - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# -- Options for HTML output -------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -# html_theme_path = ["."] -html_theme = 'openstackdocs' - -# openstackdocstheme options -openstackdocs_repo_name = 'openstack/patrole' -openstackdocs_pdf_link = True -openstackdocs_bug_project = 'patrole' -openstackdocs_bug_tag = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'patroledoc' - -# Example configuration for intersphinx: refer to the Python standard library. -#intersphinx_mapping = {'http://docs.python.org/': None} - -# -- Options for LaTeX output ------------------------------------------------- - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ('index', 'doc-patrole.tex', u'Patrole: Tempest Plugin for RBAC Testing', - u'OpenStack Foundation', 'manual'), -] - -# Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664 -latex_use_xindy = False diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst deleted file mode 100644 index 1e7fe8fb..00000000 --- a/doc/source/configuration.rst +++ /dev/null @@ -1,94 +0,0 @@ -.. _patrole-configuration: - -Patrole Configuration Guide -=========================== - -Patrole can be customized by updating Tempest's ``tempest.conf`` configuration -file. All Patrole-specific configuration options should be included under -the ``patrole`` group. - -RBAC Test Roles ---------------- - -The RBAC test roles govern the list of roles to be used when running Patrole -tests. For example, setting ``rbac_test_roles`` to "admin" will execute all -RBAC tests using admin credentials. Changing the ``rbac_test_roles`` value -will `override` Tempest's primary credentials to use that role. - -This implies that, if ``rbac_test_roles`` is "admin", regardless of the Tempest -credentials used by a client, the client will be calling APIs using the admin -role. That is, ``self.os_primary.servers_client`` will run as though it were -``self.os_admin.servers_client``. - -Similarly, setting ``rbac_test_roles`` with various roles, results in -Tempest's primary credentials being overridden by the roles specified by -``rbac_test_roles``. - -.. note:: - - Only the roles of the primary Tempest credentials ("os_primary") are - modified. The ``user_id`` and ``project_id`` remain unchanged. - -Custom Policy Files -------------------- - -Patrole supports testing custom policy file definitions, along with default -policy definitions. Default policy definitions are used if custom file -definitions are not specified. If both are specified, the custom policy -definition takes precedence (that is, replaces the default definition, -as this is the default behavior in OpenStack). - -The ``custom_policy_files`` option allows a user to specify a comma-separated -list of custom policy file locations that are on the same host as Patrole. -Each policy file must include the name of the service that is being tested: -for example, if "compute" tests are executed, then Patrole will use the first -policy file contained in ``custom_policy_files`` that contains the "nova" -keyword. - -.. note:: - - Patrole currently does not support policy files located on a host different - than the one on which it is running. - -Policy Feature Flags --------------------- - -Patrole's ``[policy-feature-enabled]`` configuration group includes one option -per supported policy feature flag. These feature flags are introduced when an -OpenStack service introduces a new policy or changes a policy in a -backwards-incompatible way. Since Patrole is branchless, it copes with the -unexpected policy change by making the relevant policy change as well, but -also introduces a new policy feature flag so that the test won't break N-1/N-2 -releases where N is the currently supported release. - -The default value for the feature flag is enabled for N and disabled for any -releases prior to N in which the feature is not available. This is done by -overriding the default value of the feature flag in DevStack's ``lib/patrole`` -installation script. The change is made in Tempest's DevStack script because -Patrole's DevStack plugin is hosted in-repo, which is branch-less (whereas -the former is branched). - -After the backwards-incompatible change no longer affects any supported -release, then the corresponding policy feature flag is removed. - -For more information on feature flags, reference the relevant -`Tempest documentation`_. - -.. _Tempest documentation: https://docs.openstack.org/tempest/latest/HACKING.html#new-tests-for-new-features - -Sample Configuration File -------------------------- - -The following is a sample Patrole configuration for adaptation and use. It is -auto-generated from Patrole when this documentation is built, so -if you are having issues with an option, please compare your version of -Patrole with the version of this documentation. - -Note that the Patrole configuration options actually live inside the Tempest -configuration file; at runtime, Tempest populates its own configuration -file with Patrole groups and options, assuming that Patrole is correctly -installed and recognized as a plugin. - -The sample configuration can also be viewed in `file form <_static/patrole.conf.sample>`_. - -.. literalinclude:: _static/patrole.conf.sample diff --git a/doc/source/contributor/contributing.rst b/doc/source/contributor/contributing.rst deleted file mode 100644 index 6d9bb86a..00000000 --- a/doc/source/contributor/contributing.rst +++ /dev/null @@ -1,57 +0,0 @@ -============================ -So You Want to Contribute... -============================ - -For general information on contributing to OpenStack, please check out the -`contributor guide `_ to get started. -It covers all the basics that are common to all OpenStack projects: the accounts -you need, the basics of interacting with our Gerrit review system, how we -communicate as a community, etc. - -Below will cover the more project specific information you need to get started -with Tempest. - -Communication -~~~~~~~~~~~~~ -* IRC channel ``#openstack-qa`` at OFTC -* Mailing list (prefix subjects with ``[qa]`` for faster responses) - http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-discuss - -Contacting the Core Team -~~~~~~~~~~~~~~~~~~~~~~~~ -Please refer to the `Patrole Core Team -`_ contacts. - -New Feature Planning -~~~~~~~~~~~~~~~~~~~~ -If you want to propose a new feature please read `Feature Proposal Process`_ -Patrole features are tracked on `Storyboard `_. - -Task Tracking -~~~~~~~~~~~~~ -We track our tasks in `Storyboard `_. - -If you're looking for some smaller, easier work item to pick up and get started -on, search for the 'low-hanging-fruit' tag. - -Reporting a Bug -~~~~~~~~~~~~~~~ -You found an issue and want to make sure we are aware of it? You can do so on -`StoryBoard `_. - -Getting Your Patch Merged -~~~~~~~~~~~~~~~~~~~~~~~~~ -All changes proposed to the Patrole requires one ``Code-Review +2`` votes from -Patrole core reviewers before one of the core reviewers can approve patch by -giving ``Workflow +1`` vote. More detailed guidelines for reviewers are available -at :doc:`../REVIEWING`. - -Project Team Lead Duties -~~~~~~~~~~~~~~~~~~~~~~~~ -All common PTL duties are enumerated in the `PTL guide -`_. - -The Release Process for QA is documented in `QA Release Process -`_. - -.. _Feature Proposal Process: https://wiki.openstack.org/wiki/QA#Feature_Proposal_.26_Design_discussions diff --git a/doc/source/field_guide/index.rst b/doc/source/field_guide/index.rst deleted file mode 100644 index ba06c423..00000000 --- a/doc/source/field_guide/index.rst +++ /dev/null @@ -1,60 +0,0 @@ -.. _patrole-field-guide: - -============================ -Patrole Field Guide Overview -============================ - -Testing Scope -============= - -Patrole testing scope is strictly confined to Role-Based Access Control -(RBAC). In OpenStack, ``oslo.policy`` is the RBAC library used by all -major services. Thus, Patrole is concerned with validating that public API -endpoints are correctly using ``oslo.policy`` for authorization. - -In other words, all tests in Patrole are RBAC tests. - -:ref:`rbac_field_guide` -======================= - -RBAC tests are `Tempest`_-like API tests plus Patrole's -:ref:`rbac-validation`. All Patrole tests are RBAC validation tests for the -OpenStack API. - -.. _Tempest: https://docs.openstack.org/tempest/latest/ - -Stable Tests -============ - -In the discussion below, "correct" means that a test is consistent with -a service's API-to-policy mapping and "stable" means that a test should -require minimal maintenance for the supported releases. - -Present -------- - -During the Queens release, a `governance spec`_ was pushed to support policy -in code, which documents the mapping between APIs and each of their policies. - -This documentation is an important prerequisite for ensuring that Patrole -tests for a given service are correct. This mapping can be referenced to -confirm that Patrole's assumed mapping for a test is correct. For -example, Nova has implemented policy in code which can be used to verify -that Patrole's Nova RBAC tests use the same mapping. - -If a given service does not have policy in code, this implies that it is -*more likely* that the RBAC tests for that service are inconsistent with the -*intended* policy mapping. Until that service implements policy in code, it -is difficult for Patrole maintainers to verify that tests for that service -are correct. - -Future ------- - -Once all services that Patrole tests have implemented policy in code -- -and once Patrole has updated all its tests in accordance with the policy in -code documentation -- then Patrole tests can guaranteed to be stable. - -This stability will be denoted with a 1.0 version release. - -.. _governance spec: https://governance.openstack.org/tc/goals/queens/policy-in-code.html diff --git a/doc/source/field_guide/rbac.rst b/doc/source/field_guide/rbac.rst deleted file mode 100644 index a3830990..00000000 --- a/doc/source/field_guide/rbac.rst +++ /dev/null @@ -1,118 +0,0 @@ -.. _rbac_field_guide: - -Patrole Field Guide to RBAC Tests -================================= - - -What are these tests? ---------------------- - -Patrole's primary responsibility is to ensure that your OpenStack cloud -has properly configured Role-Based Access Control (RBAC). All Patrole -tests cases are devoted to this responsibility. Tempest API clients -and utility functions are leveraged to accomplish this goal, but such -functionality is secondary to RBAC validation. - -Like Tempest, Patrole not only tests expected positive paths for RBAC -validation, but also -- and more importantly -- negative paths. While -Patrole could be thought of as validating RBAC, it more importantly -verifies that your OpenStack cloud is secure from the perspective of -RBAC (there are many gotchas when it comes to security, not just RBAC). - -Negative paths are arguably more important than positive paths when it -comes to RBAC and by extension security, because it is essential that -your cloud be secure from unauthorized access. For example, while it is -important to verify that the admin role has access to admin-level -functionality, it is of critical importance to verify that non-admin roles -*do not* have access to such functionality. - -Unlike Tempest, Patrole accomplishes negative testing implicitly -- by -abstracting it away in the background. Patrole dynamically determines -whether a role should have access to an API depending on your cloud's -policy configuration and then confirms whether that is true or false. - - -Why are these tests in Patrole? -------------------------------- - -These tests constitute the core mission in Patrole: to verify RBAC. These -tests are mainly intended to validate RBAC, but can also *unofficially* -be used to discover the policy-to-API mapping for an OpenStack component. - -It could be argued that some of these tests could be implemented in -the projects themselves, but that approach has the following shortcomings: - -* The projects do not validate RBAC from an integration testing perspective. -* By extension, RBAC across cross-service communication is not usually - validated. -* The projects' tests do not pass all the metadata to ``oslo.policy`` that is - in reality passed by the deployed server to that library to determine - whether a given user is authorized to perform an API action. -* The projects do not exhaustively do RBAC testing for all positive and - negative paths. -* Patrole is designed to work with any role via configuration settings, but - on the other hand the projects handpick which roles to test. - -Why not use Patrole framework on Tempest tests? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The Patrole framework can't be applied to existing Tempest tests via -:ref:`rbac-validation`, because: - -* Tempest tests aren't factored the right way: They're not granular enough. - They call too many APIs and too many policies are enforced by each test. -* Tempest tests assume default policy rules: Tempest uses ``os_admin`` - `credentials`_ for admin APIs and ``os_primary`` for non-admin APIs. - This breaks for custom policy overrides. -* Tempest doesn't have tests that enforce all the policy actions, regardless. - Some RBAC tests require that tests be written a very precise way for the - server to authorize the expected policy actions. - -Why are these tests not in Tempest? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Patrole should be a separate project that specializes in RBAC tests. This -was agreed upon during `discussion`_ that led to the approval of the RBAC -testing framework `spec`_, which was the genesis for Patrole. - -Philosophically speaking: - -* Tempest supports `API and scenario testing`_. RBAC testing is out of scope. -* The `OpenStack project structure reform`_ evolved OpenStack "to a more - decentralized model where [projects like QA] provide processes and tools to - empower projects to do the work themselves". This model resulted in the - creation of the `Tempest external plugin interface`_. -* Tempest supports `plugins`_. Why not use one for RBAC testing? - -Practically speaking: - -* The Tempest team should not be burdened with having to support Patrole, too. - Tempest is a big project and having to absorb RBAC testing is difficult. -* Tempest already has many in-tree Zuul checks/gates. If Patrole tests lived - in Tempest, then adding more Zuul checks/gates for Patrole would only make it - harder to get changes merged in Tempest. - -.. _credentials: https://docs.openstack.org/tempest/latest/write_tests.html#allocating-credentials -.. _discussion: https://review.openstack.org/#/c/382672/ -.. _spec: https://specs.openstack.org/openstack/qa-specs/specs/tempest/rbac-policy-testing.html -.. _API and scenario testing: https://docs.openstack.org/tempest/latest/overview.html#tempest-the-openstack-integration-test-suite -.. _OpenStack project structure reform: https://governance.openstack.org/tc/resolutions/20141202-project-structure-reform-spec.html#impact-for-horizontal-teams -.. _Tempest external plugin interface: https://specs.openstack.org/openstack/qa-specs/specs/tempest/implemented/tempest-external-plugin-interface.html -.. _plugins: https://docs.openstack.org/tempest/latest/plugin.html - - -Scope of these tests --------------------- - -RBAC tests should always use the Tempest implementation of the -OpenStack API, to take advantage of Tempest's stable library. - -Each test should test a specific API endpoint and the related policy. - -Each policy should be tested in isolation of one another -- or at least -as close to this rule as possible -- to ensure proper validation of RBAC. - -Each test should be able to work for positive and negative paths. - -All tests should be able to be run on their own, not depending on the -state created by a previous test. diff --git a/doc/source/framework/overview.rst b/doc/source/framework/overview.rst deleted file mode 100644 index 6f72eec7..00000000 --- a/doc/source/framework/overview.rst +++ /dev/null @@ -1,81 +0,0 @@ -RBAC Testing Validation -======================= - -.. _validation-workflow-overview: - ----------------------------- -Validation Workflow Overview ----------------------------- - -RBAC testing validation is broken up into 3 stages: - -#. "Expected" stage. Determine whether the test should be able to succeed - or fail based on the test roles defined by ``[patrole] rbac_test_roles``) - and the policy action that the test enforces. -#. "Actual" stage. Run the test by calling the API endpoint that enforces - the expected policy action using the test roles. -#. Comparing the outputs from both stages for consistency. A "consistent" - result is treated as a pass and an "inconsistent" result is treated - as a failure. "Consistent" (or successful) cases include: - - * Expected result is ``True`` and the test passes. - * Expected result is ``False`` and the test fails. - - For example, a 200 from the API call and a ``True`` result from - ``oslo.policy`` or a 403 from the API call and a ``False`` result from - ``oslo.policy`` are successful results. - - "Inconsistent" (or failing) cases include: - - * Expected result is ``False`` and the test passes. This results in an - :class:`~rbac_exceptions.RbacOverPermissionException` exception - getting thrown. - * Expected result is ``True`` and the test fails. This results in a - :class:`~rbac_exceptions.RbacOverPermissionException` exception - getting thrown. - - For example, a 200 from the API call and a ``False`` result from - ``oslo.policy`` or a 403 from the API call and a ``True`` result from - ``oslo.policy`` are failing results. - -.. warning:: - - Note that Patrole cannot currently derive the expected policy result for - service-specific ``oslo.policy`` `checks`_, like Neutron's `FieldCheck`_, - because such checks are contained within the service's code base itself, - which Patrole cannot import. - -.. _checks: https://docs.openstack.org/oslo.policy/latest/reference/api/oslo_policy.policy.html#generic-checks -.. _FieldCheck: https://docs.openstack.org/neutron/pike/contributor/internals/policy.html#fieldcheck-verify-resource-attributes - -------------------------------- -The RBAC Rule Validation Module -------------------------------- - -High-level module that provides the decorator that wraps around Tempest tests -and serves as the entry point for RBAC testing validation. The workflow -described above is ultimately carried out by the decorator. - -For more information about this module, please see :ref:`rbac-validation`. - ---------------------------- -The Policy Authority Module ---------------------------- - -Module called by :ref:`rbac-validation` to verify whether the test -roles are allowed to execute a policy action by querying ``oslo.policy`` with -required test data. The result is used by :ref:`rbac-validation` as the -"Expected" result. - -For more information about this module, please see :ref:`policy-authority`. - ---------------------- -The RBAC Utils Module ---------------------- - -This module is responsible for handling role switching, the mechanism by which -Patrole is able to set up, tear down and execute APIs using the same set -of credentials. Every RBAC test must perform a role switch even if the role -that is being switched to is admin. - -For more information about this module, please see :ref:`rbac-utils`. diff --git a/doc/source/framework/policy_authority.rst b/doc/source/framework/policy_authority.rst deleted file mode 100644 index f0396926..00000000 --- a/doc/source/framework/policy_authority.rst +++ /dev/null @@ -1,60 +0,0 @@ -.. _policy-authority: - -Policy Authority Module -======================= - -Overview --------- - -This module is only called for calculating the "Expected" result if -``[patrole] test_custom_requirements`` is ``False``. - -Using the :class:`~patrole_tempest_plugin.policy_authority.PolicyAuthority` -class, policy verification is performed by: - -#. Pooling together the default `in-code` policy rules. -#. Overriding the defaults with custom policy rules located in a policy.json, - if the policy file exists and the custom policy definition is explicitly - defined therein. -#. Confirming that the policy action -- for example, "list_users" -- exists. - (``oslo.policy`` otherwise claims that role "foo" is allowed to - perform policy action "bar", for example, because it defers to the - "default" policy rule and oftentimes the default can be "anyone allowed"). -#. Performing a call with all necessary data to ``oslo.policy`` and returning - the expected result back to ``rbac_rule_validation`` decorator. - -When to use ------------ - -This :class:`~patrole_tempest_plugin.rbac_authority.RbacAuthority` class -can be used to validate the default OpenStack policy configuration. It -is recommended that this approach be used for RBAC validation for clouds that -use little to no policy customizations or overrides. - -This validation approach should be used when: - -* Validating the out-of-the-box policy-in-code OpenStack policy configuration. - - It is important that the default OpenStack policy configuration be validated - before deploying OpenStack into production. Bugs exist in software and the - earlier they can be caught and prevented (via CI/CD, for example), the - better. Patrole continues to be used to identify default policy bugs - across OpenStack services. - -* Validating policy reliably and accurately. - - Relying on ``oslo.policy`` to compute the expected test results provides - accurate tests, without the hassle of having to reinvent the wheel. Since - OpenStack APIs use ``oslo.policy`` for policy enforcement, it makes sense - to compute expected results by using the same library, ensuring test - reliability. - -* Continuously validating policy changes to OpenStack projects under - development by gating them against Patrole CI/CD jobs run by `Zuul`_. - -.. _Zuul: https://docs.openstack.org/infra/zuul/ - -Implementation --------------- - -:py:mod:`Policy Authority Module ` diff --git a/doc/source/framework/rbac_authority.rst b/doc/source/framework/rbac_authority.rst deleted file mode 100644 index 7ffe24f8..00000000 --- a/doc/source/framework/rbac_authority.rst +++ /dev/null @@ -1,35 +0,0 @@ -.. rbac-authority: - -RBAC Authority Module -===================== - -Overview --------- - -This module implements an abstract class that is implemented by the classes -below. Each implementation is used by the :ref:`rbac-validation` framework -to determine each expected test result. - -:ref:`policy-authority` ------------------------ - -The *default* :class:`~patrole_tempest_plugin.rbac_authority.RbacAuthority` -implementation class which is used for policy validation. Uses ``oslo.policy`` -to determine the expected test result. - -All Patrole `Zuul`_ gates use this -:class:`~patrole_tempest_plugin.rbac_authority.RbacAuthority` class by default. - -.. _Zuul: https://docs.openstack.org/infra/zuul/ - -:ref:`requirements-authority` ------------------------------ - -Optional :class:`~patrole_tempest_plugin.rbac_authority.RbacAuthority` -implementation class which is used for policy validation. It uses a high-level -requirements-driven approach to validating RBAC in Patrole. - -Implementation --------------- - -:py:mod:`RBAC Authority Module ` diff --git a/doc/source/framework/rbac_utils.rst b/doc/source/framework/rbac_utils.rst deleted file mode 100644 index f7cb182f..00000000 --- a/doc/source/framework/rbac_utils.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _rbac-utils: - -RBAC Utils Module -================= - -Overview --------- - -Patrole manipulates the ``os_primary`` `Tempest credentials`_, which are the -primary set of Tempest credentials. It is necessary to use the same credentials -across the entire test setup/test execution/test teardown workflow -because otherwise 400-level errors will be thrown by OpenStack services. - -This is because many services check the request context's project scope -- and -in very rare cases, user scope. However, each set of Tempest credentials (via -`dynamic credentials`_) is allocated its own distinct project. For example, the -``os_admin`` and ``os_primary`` credentials each have a distinct project, -meaning that it is not always possible for the ``os_primary`` credentials to -access resources created by the ``os_admin`` credentials. - -The only foolproof solution is to manipulate the role for the same set of -credentials, rather than using distinct credentials for setup/teardown -and test execution, respectively. This is especially true when considering -custom policy rule definitions, which can be arbitrarily complex. - -Implementation --------------- - -:py:mod:`RBAC Utils Module ` - -.. _Tempest credentials: https://docs.openstack.org/tempest/latest/library/credential_providers.html -.. _dynamic credentials: https://docs.openstack.org/tempest/latest/configuration.html#dynamic-credentials - diff --git a/doc/source/framework/rbac_validation.rst b/doc/source/framework/rbac_validation.rst deleted file mode 100644 index 460c08c8..00000000 --- a/doc/source/framework/rbac_validation.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. _rbac-validation: - -RBAC Rule Validation Module -=========================== - -Overview --------- - -Module that implements the decorator which serves as the entry point for -RBAC validation testing. The decorator should be applied to every RBAC test -with the appropriate ``service`` (OpenStack service) and ``rule`` (OpenStack -policy name defined by the ``service``). - -Implementation --------------- - -:py:mod:`RBAC Rule Validation Module ` diff --git a/doc/source/framework/requirements_authority.rst b/doc/source/framework/requirements_authority.rst deleted file mode 100644 index daed3196..00000000 --- a/doc/source/framework/requirements_authority.rst +++ /dev/null @@ -1,156 +0,0 @@ -.. _requirements-authority: - -Requirements Authority Module -============================= - -Overview --------- - -Requirements-driven approach to declaring the expected RBAC test results -referenced by Patrole. These requirements express the *intention* behind the -policy. A high-level YAML syntax is used to concisely and clearly map each -policy action to the list of associated roles. - -.. note:: - - The :ref:`custom-requirements-file` is required to use this validation - approach and, currently, must be manually generated. - -This validation approach can be toggled on by setting the -``[patrole].test_custom_requirements`` configuration option to ``True``; -see :ref:`patrole-configuration` for more information. - -When to use ------------ - -This :class:`~patrole_tempest_plugin.rbac_authority.RbacAuthority` class -can be used to achieve a requirements-driven approach to validating an -OpenStack cloud's RBAC implementation. Using this approach, Patrole computes -expected test results by performing lookups against a -:ref:`custom-requirements-file` which precisely defines the cloud's RBAC -requirements. - -This validation approach should be used when: - -* The cloud has heavily customized policy files that require careful validation - against one's requirements. - - Heavily customized policy files can contain relatively nuanced/technical - syntax that impinges upon the goal of using a clear and concise syntax - present in the :ref:`custom-requirements-file` to drive RBAC validation. - -* The cloud has non-OpenStack services that require RBAC validation but which - don't leverage the ``oslo.policy`` framework. - - Services like `Contrail`_ that are present in an OpenStack-based cloud that - interface with OpenStack services like Neutron also require RBAC validation. - The requirements-driven approach to RBAC validation is framework-agnostic - and so can work with any policy engine. - -* Expected results are captured as clear-cut, unambiguous requirements. - - Validating a cloud's RBAC against high-level, clear-cut requirements is - a valid use case. Relying on ``oslo.policy`` validating customized policy - files is not sufficient to satisfy this use case. - -As mentioned above, the trade-off with this approach is having to manually -generate the :ref:`custom-requirements-file`. There is currently no -tooling to automatically do this. - -.. _Contrail: https://github.com/Juniper/contrail-controller/wiki/RBAC - -.. _custom-requirements-file: - -Custom Requirements File -^^^^^^^^^^^^^^^^^^^^^^^^ - -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: - - .. code-block:: yaml - - : - : - - - - - : - - , - : - : - - - -Where: - -* ``service`` - the service that is being tested (Cinder, Nova, etc.). -* ``api_action`` - the policy action that is being tested. Examples: - - * volume:create - * os_compute_api:servers:start - * add_image - -* ``allowed_role`` - the ``oslo.policy`` role that is allowed to perform the - API. - -Each item under ``logical_or_example`` is "logical OR"-ed together. Each role -in the comma-separated string under ``logical_and_example`` is "logical AND"-ed -together. And each item prefixed with "!" under ``logical_not_example`` is -"logical negated". - -.. note:: - - The custom requirements file only allows policy actions to be mapped to - the associated roles that define it. Complex ``oslo.policy`` constructs - like ``literals`` or ``GenericChecks`` are not supported. For more - information, reference the `oslo.policy documentation`_. - -.. _oslo.policy documentation: https://docs.openstack.org/oslo.policy/latest/reference/api/oslo_policy.policy.html#policy-rule-expressions - -Examples -~~~~~~~~ - -Items within ``api_action`` are considered as logical or, so you may read: - -.. code-block:: yaml - - : - # "api_action_a: allowed_role_1 or allowed_role_2 or allowed_role_3" - : - - - - - - - -as `` or or ``. - -Roles within comma-separated items are considered as logic and, so you may -read: - -.. code-block:: yaml - - : - # "api_action_a: (allowed_role_1 and allowed_role_2) or allowed_role_3" - : - - , - - - -as `` and or ``. - -Also negative roles may be defined with an exclamation mark ahead of role: - -.. code-block:: yaml - - : - # "api_action_a: (allowed_role_1 and allowed_role_2 and not - # disallowed_role_4) or allowed_role_3" - : - - , , ! - - - -This example must be read as `` and and not - or ``. - - -Implementation --------------- - -:py:mod:`Requirements Authority Module ` diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index d24f517f..00000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,92 +0,0 @@ -======================================== -Patrole: Tempest Plugin for RBAC Testing -======================================== - -Overview -======== - -.. toctree:: - :maxdepth: 2 - - overview - -RBAC Overview -------------- - -.. toctree:: - :maxdepth: 2 - - rbac-overview - multi-policy-validation - -User's Guide -============ - -Patrole Configuration Guide ---------------------------- - -.. toctree:: - :maxdepth: 2 - - configuration - -Patrole Installation Guide --------------------------- - -.. toctree:: - :maxdepth: 2 - - installation - -Field Guides -============ - -.. toctree:: - :maxdepth: 1 - - field_guide/index - field_guide/rbac - -For Contributors -================ - -* If you are a new contributor to Patrole please refer: :doc:`contributor/contributing` - -.. toctree:: - :hidden: - - contributor/contributing - -Developer's Guide -================= - -.. toctree:: - :maxdepth: 1 - - HACKING - REVIEWING - test_writing_guide - -Framework ---------- - -.. toctree:: - :maxdepth: 3 - - framework/overview - framework/rbac_validation - framework/rbac_authority - framework/policy_authority - framework/requirements_authority - framework/rbac_utils - framework/code/modules - -Search -====== - -.. only:: html - - * :ref:`Patrole document search `: Search the contents of this document. - -* `OpenStack wide search `_: Search the wider - set of OpenStack documentation, including forums. diff --git a/doc/source/installation.rst b/doc/source/installation.rst deleted file mode 100644 index 827239ff..00000000 --- a/doc/source/installation.rst +++ /dev/null @@ -1,29 +0,0 @@ -.. _patrole-installation: - -========================== -Patrole Installation Guide -========================== - -Manual Installation Information -=============================== - -At the command line:: - - $ git clone http://git.openstack.org/openstack/patrole - $ sudo pip install ./patrole - -Or, if you have virtualenvwrapper installed:: - - $ mkvirtualenv patrole_env - $ workon patrole_env - $ pip install ./patrole - -Or to install from the source:: - - $ navigate to patrole directory - $ sudo pip install -e . - -DevStack Installation -===================== - -.. include:: ../../devstack/README.rst diff --git a/doc/source/multi-policy-validation.rst b/doc/source/multi-policy-validation.rst deleted file mode 100644 index 441bd35e..00000000 --- a/doc/source/multi-policy-validation.rst +++ /dev/null @@ -1,187 +0,0 @@ -.. _multi-policy-validation: - -======================= -Multi-policy Validation -======================= - -Introduction ------------- - -Multi-policy validation exists in Patrole because if one policy were assumed, -then tests could fail because they would not consider all the policies actually -being enforced. The reasoning can be found in `this spec`_. Basically, -since Patrole derives the expected test result dynamically in order to test any -role, each policy enforced by the API under test must be considered to derive -an accurate expected test result, or else the expected and actual test -results will not always match, resulting in overall test failure. For more -information about Patrole's RBAC validation work flow, reference -:ref:`rbac-validation`. - -Multi-policy support allows Patrole to more accurately offer RBAC tests for API -endpoints that enforce multiple policy actions. - -.. _this spec: http://specs.openstack.org/openstack/qa-specs/specs/patrole/rbac-testing-multiple-policies.html - -Scope ------ - -Multiple policies should be applied only to tests that require them. Not all -API endpoints enforce multiple policies. Some services consistently enforce -1 policy per API, while on the other side of the spectrum, services like -Neutron have much more involved policy enforcement work flows. See -:ref:`neutron-multi-policy-validation` for more information. - -.. _neutron-multi-policy-validation: - -Neutron Multi-policy Validation -------------------------------- - -Neutron can raise different :ref:`policy-error-codes` following failed policy -authorization. Many endpoints in Neutron enforce multiple policies, which -complicates matters when trying to determine whether the endpoint raises a -403 or a 404 following unauthorized access. - -Multi-policy Examples ---------------------- - -General Examples -^^^^^^^^^^^^^^^^ - -Below is an example of multi-policy validation for a carefully chosen Nova API: - -.. code-block:: python - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-lock-server:unlock", - "os_compute_api:os-lock-server:unlock:unlock_override"]) - @decorators.idempotent_id('40dfeef9-73ee-48a9-be19-a219875de457') - def test_unlock_server_override(self): - """Test force unlock server, part of os-lock-server. - - In order to trigger the unlock:unlock_override policy instead - 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']) - - with self.override_role(): - self.servers_client.unlock_server(self.server['id']) - -While the ``expected_error_codes`` parameter is omitted in the example above, -Patrole automatically populates it with a 403 for each policy in ``rules``. -Therefore, in the example above, the following expected error codes/rules -relationship is observed: - -* "os_compute_api:os-lock-server:unlock" => 403 -* "os_compute_api:os-lock-server:unlock:unlock_override" => 403 - -Below is an example that uses ``expected_error_codes`` to account for the -fact that Neutron is expected to raise a ``404`` on the first policy that -is enforced server-side ("get_port"). Also, in this example, soft authorization -is performed, meaning that it is necessary to check the response body for an -attribute that is added only following successful policy authorization. - -.. code-block:: python - - @utils.requires_ext(extension='binding', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_port", - "get_port:binding:vif_type"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('125aff0b-8fed-4f8e-8410-338616594b06') - def test_show_port_binding_vif_type(self): - - # Verify specific fields of a port - fields = ['binding:vif_type'] - - with self.override_role(): - retrieved_port = self.ports_client.show_port( - self.port['id'], fields=fields)['port'] - - # Rather than throwing a 403, the field is not present, so raise exc. - if fields[0] not in retrieved_port: - raise rbac_exceptions.RbacMalformedResponse( - attribute='binding:vif_type') - -Note that in the example above, failure to authorize -"get_port:binding:vif_type" results in the response body getting successfully -returned by the server, but without additional dictionary keys. If Patrole -fails to find those expected keys, it *acts as though* a 403 was thrown (by -raising an exception itself, the ``rbac_rule_validation`` decorator handles -the rest). - -Neutron Examples -^^^^^^^^^^^^^^^^ - -A basic Neutron example that only expects 403's to be raised: - -.. code-block:: python - - @utils.requires_ext(extension='external-net', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["create_network", - "create_network:router:external"], - expected_error_codes=[403, 403]) - @decorators.idempotent_id('51adf2a7-739c-41e0-8857-3b4c460cbd24') - def test_create_network_router_external(self): - - """Create External Router Network Test - - RBAC test for the neutron create_network:router:external policy - """ - with self.override_role(): - self._create_network(router_external=True) - -Note that above the following expected error codes/rules relationship is -observed: - -* "create_network" => 403 -* "create_network:router:external" => 403 - -A more involved example that expects a 404 to be raised, should the first -policy under ``rules`` fail authorization, and a 403 to be raised for any -subsequent policy authorization failure: - -.. code-block:: python - - @rbac_rule_validation.action(service="neutron", - rules=["get_network", - "update_network", - "update_network:shared"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('37ea3e33-47d9-49fc-9bba-1af98fbd46d6') - def test_update_network_shared(self): - - """Update Shared Network Test - - RBAC test for the neutron update_network:shared policy - """ - with self.override_role(): - self._update_network(shared_network=True) - self.addCleanup(self._update_network, shared_network=False) - -Note that above the following expected error codes/rules relationship is -observed: - -* "get_network" => 404 -* "update_network" => 403 -* "update_network:shared" => 403 - -Limitations ------------ - -Multi-policy validation in RBAC tests comes with limitations, due to technical -and practical challenges. - -Technically, there are challenges associated with multiple policies across -cross-service API communication in OpenStack, such as between Nova and Cinder -or Nova and Neutron. The current framework does not account for these -cross-service policy enforcement workflows, and it is still up for debate -whether it should. - -Practically, it is not possible to enumerate every policy enforced by every API -in Patrole, as the maintenance overhead would be huge. - -.. _Neutron policy documentation: https://docs.openstack.org/neutron/pike/contributor/internals/policy.html diff --git a/doc/source/overview.rst b/doc/source/overview.rst deleted file mode 120000 index c768ff7d..00000000 --- a/doc/source/overview.rst +++ /dev/null @@ -1 +0,0 @@ -../../README.rst \ No newline at end of file diff --git a/doc/source/rbac-overview.rst b/doc/source/rbac-overview.rst deleted file mode 100644 index cf130b06..00000000 --- a/doc/source/rbac-overview.rst +++ /dev/null @@ -1,285 +0,0 @@ -.. _rbac-overview: - -================================== -Role-Based Access Control Overview -================================== - -Introduction ------------- - -Role-Based Access Control (RBAC) is used by most OpenStack services to control -user access to resources. Authorization is granted if a user has the necessary -role to perform an action. Patrole is concerned with validating that each of -these resources *can* be accessed by authorized users and *cannot* be accessed -by unauthorized users. - -OpenStack services use `oslo.policy`_ as the library for RBAC authorization. -Patrole relies on the same library for deriving expected test results. - -.. _policy-in-code: - -Policy in Code --------------- - -Services publish their policy-to-API mapping via policy in code documentation. -This mapping includes the list of APIs that authorize a policy, for each -policy declared within a service. - -For example, Nova's policy in code documentation is located in the -`Nova repository`_ under ``nova/policies``. Likewise, Keystone's policy in -code documentation is located in the `Keystone repository`_ under -``keystone/common/policies``. The other OpenStack services follow the same -directory layout pattern with respect to policy in code. - -The policy in code `governance goal`_ enumerates many advantages with following -this RBAC design approach. A so-called library of in-code policies offers the -following advantages, with respect to facilitating validation: - -* includes every policy enforced by an OpenStack service, enabling the - possibility of complete Patrole test coverage for that service (otherwise - one has to read the source code to discover all the policies) -* provides the policy-to-API mapping for each policy which can be used - to write correct Patrole tests (otherwise reading source code and - experimentation are required to derive this mapping) -* by extension, the policy-to-API mapping facilitates writing multi-policy - Patrole tests (otherwise even more experimentation and code reading is - required to arrive at all the policies enforced by an API) -* policy in code documentation includes additional information, like - descriptions and (in the case of some services, like Keystone) - `scope types`_, which help with understanding how to correctly write - Patrole tests -* by extension, such information helps to determine whether a Patrole test - should assume :term:`hard authorization` or :term:`soft authorization` - -Policy in Code (Default) Validation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -By default, Patrole validates default OpenStack policies. This is so that -the out-of-the-box defaults are sanity-checked, to ensure that OpenStack -services are secure, from an RBAC perspective, for each release. - -Patrole strives to validate RBAC by using the policy in code documentation, -wherever possible. See :ref:`validation-workflow-overview` for more details. - -.. _custom-policies: - -Custom Policies ---------------- - -Operators can override policy in code defaults using `policy.yaml`_. While -this allows operators to offer more fine-grained RBAC control to their tenants, -it opens the door to misconfiguration and bugs. Patrole can be used to validate -that custom policy overrides don't break anything and work as expected. - -Custom Policy Validation -^^^^^^^^^^^^^^^^^^^^^^^^ - -While testing default policy behavior is a valid use case, oftentimes default -policies are modified with custom overrides in production. OpenStack's -`policy.yaml`_ documentation claims that "modifying policy can have unexpected -side effects", which is why Patrole was created: to ensure that custom -overrides allow the principle of least privilege to be tailor-made to exact -specifications via policy overrides, without: - -* causing unintended side effects (breaking API endpoints, breaking - cross-service workflows, breaking the policy file itself); or -* resulting in poor RBAC configuration, promoting security vulnerabilities - -This has implications on Patrole's :ref:`design-principles`: validating custom -overrides requires the ability to handle arbitrary roles, which requires logic -capable of dynamically determining expected test behavior. - -Note that support for custom policies is limited. This is because custom -policies can be arbitrarily complex, requiring that tests be very robust -in order to handle all edge cases. - -.. _multiple-policies: - -Multiple Policies ------------------ - -Behind the scenes, many APIs enforce multiple policies, for many reasons, -including: - -* to control complex cross-service workflows; -* to control whether a server is booted from an image or booted from a volume - (for example); -* to control whether a response body should contain additional information - conditioned upon successful policy authorization. - -This makes `policy in code`_ especially important for policy validation: it -is difficult to keep track of all the policies being enforced across all the -individual APIs, without policy in code documentation. - -Multi-Policy Validation -^^^^^^^^^^^^^^^^^^^^^^^ - -Patrole offers support for validating APIs that enforce multiple policies. -Perhaps in an ideal world each API endpoint would enforce only one policy, -but in reality some API endpoints enforce multiple policies. Thus, to offer -accurate validation, Patrole handles multiple policies: - -* for services *with* policy in code documentation: this documentation - indicates that a single API endpoint enforces multiple policy actions. -* for services *without* policy in code documentation: the API code clearly - shows multiple policy actions being validated. Note that in this case some - degree of log tracing is required by developers to confirm that the expected - policies are getting enforced, prior to the tests getting merged. - -For more information, see :ref:`multi-policy-validation`. - -.. _policy-error-codes: - -Error Codes ------------ - -Most OpenStack services raise a ``403 Forbidden`` following failed -:term:`hard authorization`. Neutron, however, can raise a ``404 NotFound`` -as well. See Neutron's `authorization policy enforcement`_ documentation -for more details. - -Admin Context Policy --------------------- - -The so-called "admin context" policy refers to the following policy definition -(using the legacy policy file syntax): - -.. code-block:: javascript - - { - "context_is_admin": "role:admin" - ... - } - -Which is unfortunately used to bypass ``oslo.policy`` authorization checks, -for example: - -.. code-block:: python - - # This function is responsible for calling oslo.policy to check whether - # requests are authorized to perform an API action. - def enforce(context, action, target, [...]): - # Here this condition, if True, skips over the enforce call below which - # is what calls oslo.policy. - if context.is_admin: - return True - _ENFORCER.enforce([...]) # This is what can be skipped over. - [...] - -This type of behavior is currently present in many services. Unless such -logic is removed in the future for services that implement it, Patrole -won't really be able to validate that admin role works from an ``oslo.policy`` -perspective. - -Glossary --------- - -The following nomenclature is used throughout Patrole documentation so it is -important to understand what each term means in order to understand concepts -related to RBAC in Patrole. - -.. glossary:: - - authorize - - The act of ``oslo.policy`` determining whether a user can perform a - :term:`policy` given his or her :term:`role`. - - enforce - - See :term:`authorize`. - - hard authorization - - The `do_raise`_ flag controls whether policy authorization should result - in an exception getting raised or a boolean value getting returned. - Hard authorization results in an exception getting raised. Usually, this - results in a ``403 Forbidden`` getting returned for unauthorized requests. - (See :ref:`policy-error-codes` for further details.) - - Related term: :term:`soft authorization`. - - oslo.policy - - The OpenStack library providing support for RBAC policy enforcement across - all OpenStack services. See the `official documentation`_ for more - information. - - policy - - Defines an RBAC rule. Each policy is defined by a one-line statement in - the form "" : "". For more information, reference OpenStack's - `policy documentation`_. - - policy action - - See :term:`policy target`. - - policy file - - Prior to `governance goal`_ used by all OpenStack services to define - policy defaults. Still used by some services, which is why Patrole - needs to read the policy files to derive policy information for testing. - - policy in code - - Registers default OpenStack policies for a service in the service's code - base. - - Beginning with the Queens release, policy in code became a - `governance goal`_. - - policy rule - - The policy rule determines under which circumstances the API call is - permitted. - - policy target - - The name of a policy. - - requirements file - - Requirements-driven approach to declaring the expected RBAC test results - referenced by Patrole. Uses a high-level YAML syntax to crystallize policy - requirements concisely and unambiguously. See :ref:`requirements-authority` - for more information. - - role - - A designation for the set of actions that describe what a user can do in - the system. Roles are managed through the `Keystone Roles API`_. - - Role-Based Access Control (RBAC) - - May be formally defined as "an approach to restricting system access to - authorized users." - - rule - - See :term:`policy rule`. Note that currently the Patrole code base - conflates "rule" with :term:`policy target` in some places. - - soft authorization - - The `do_raise`_ flag controls whether policy authorization should result - in an exception getting raised or a boolean value getting returned. - Soft authorization results in a boolean value getting returned. When policy - authorization evaluates to true, additional operations are performed as a - part of the API request or additional information is included in the - response body (see `response filtering`_ for an example). - - Related term: :term:`hard authorization`. - -.. _Nova repository: https://git.openstack.org/cgit/openstack/nova/tree/nova/policies -.. _Keystone repository: https://git.openstack.org/cgit/openstack/keystone/tree/keystone/common/policies -.. _governance goal: https://governance.openstack.org/tc/goals/queens/policy-in-code.html -.. _scope types: https://docs.openstack.org/keystone/latest/admin/tokens-overview.html#authorization-scopes -.. _policy.yaml: https://docs.openstack.org/ocata/config-reference/policy-yaml-file.html -.. _oslo.policy: https://docs.openstack.org/oslo.policy/latest/ -.. _policy documentation: https://docs.openstack.org/kilo/config-reference/content/policy-json-file.html -.. _do_raise: https://docs.openstack.org/oslo.policy/latest/reference/api/oslo_policy.policy.html#oslo_policy.policy.Enforcer.enforce -.. _authorization policy enforcement: https://docs.openstack.org/neutron/latest/contributor/internals/policy.html -.. _official documentation: https://docs.openstack.org/oslo.policy/latest/ -.. _Keystone Roles API: https://docs.openstack.org/api-ref/identity/v3/#roles -.. _response filtering: https://docs.openstack.org/neutron/latest/contributor/internals/policy.html#response-filtering diff --git a/doc/source/test_writing_guide.rst b/doc/source/test_writing_guide.rst deleted file mode 100644 index ac502103..00000000 --- a/doc/source/test_writing_guide.rst +++ /dev/null @@ -1,166 +0,0 @@ -Patrole Test Writing Overview -============================= - -Introduction ------------- - -Patrole tests are broken up into 3 stages: - -#. :ref:`rbac-test-setup` -#. :ref:`rbac-test-execution` -#. :ref:`rbac-test-cleanup` - -See the :ref:`framework overview documentation ` -for a high-level explanation of the entire testing work flow and framework -implementation. The guide that follows is concerned with helping developers -know how to write Patrole tests. - -.. _role-overriding: - -Role Overriding ---------------- - -Role overriding is the way Patrole is able to create resources and delete -resources -- including those that require admin credentials -- while still -being able to exercise the same set of Tempest credentials to perform the API -action that authorizes the policy under test, by manipulating roles of the -Tempest credentials. - -Patrole implicitly splits up each test into 3 stages: set up, test execution, -and teardown. - -The role workflow is as follows: - -#. Setup: Admin role is used automatically. The primary credentials are - overridden with the admin role. -#. Test execution: ``[patrole] rbac_test_roles`` is used manually via the - call to ``with self.override_role()``. Everything that - is executed within this contextmanager uses the primary - credentials overridden with the ``[patrole] rbac_test_roles``. -#. Teardown: Admin role is used automatically. The primary credentials have - been overridden with the admin role. - -.. _rbac-test-setup: - -Test Setup ----------- - -Automatic role override in background. - -Resources can be set up inside the ``resource_setup`` class method that Tempest -provides. These resources are typically reserved for "expensive" resources -in terms of memory or storage requirements, like volumes and VMs. These -resources are **always** created via the admin role; Patrole automatically -handles this. - -Like Tempest, however, Patrole must also create resources inside tests -themselves. At the beginning of each test, the primary credentials have already -been overridden with the admin role. One can create whatever test-level -resources one needs, without having to worry about permissions. - -.. _rbac-test-execution: - -Test Execution --------------- - -Manual role override required. - -"Test execution" here means calling the API endpoint that enforces the policy -action expected by the ``rbac_rule_validation`` decorator. Test execution -should be performed *only after* calling -``with self.override_role()``. - -Immediately after that call, the API endpoint that enforces the policy should -be called. - -Examples -^^^^^^^^ - -Always use the contextmanager before calling the API that enforces the -expected policy action. - -Example:: - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-aggregates:show"]) - def test_show_aggregate_rbac(self): - # Do test setup before the ``override_role`` call. - aggregate_id = self._create_aggregate() - # Call the ``override_role`` method so that the primary credentials - # have the test role needed for test execution. - with self.override_role(): - self.aggregates_client.show_aggregate(aggregate_id) - -When using a waiter, do the wait outside the contextmanager. "Waiting" always -entails executing a ``GET`` request to the server, until the state of the -returned resource matches a desired state. These ``GET`` requests enforce -a different policy than the one expected. This is undesirable because -Patrole should only test policies in isolation from one another. - -Otherwise, the test result will be tainted, because instead of only the -expected policy getting enforced with the ``os_primary`` role, at least -two policies get enforced. - -Example using waiter:: - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-admin-password"]) - def test_change_server_password(self): - original_password = self.servers_client.show_password( - self.server['id']) - self.addCleanup(self.servers_client.change_password, self.server['id'], - adminPass=original_password) - - with self.override_role(): - self.servers_client.change_password( - self.server['id'], adminPass=data_utils.rand_password()) - # Call the waiter outside the ``override_role`` contextmanager, so that - # it is executed with admin role. - waiters.wait_for_server_status( - self.servers_client, self.server['id'], 'ACTIVE') - -Below is an example of a method that enforces multiple policies getting -called inside the contextmanager. The ``_complex_setup_method`` below -performs the correct API that enforces the expected policy -- in this -case ``self.resources_client.create_resource`` -- but then proceeds to -use a waiter. - -Incorrect:: - - def _complex_setup_method(self): - resource = self.resources_client.create_resource( - **kwargs)['resource'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self._delete_resource, resource) - waiters.wait_for_resource_status( - self.resources_client, resource['id'], 'available') - return resource - - @rbac_rule_validation.action( - service="example-service", - rules=["example-rule"]) - def test_change_server_password(self): - # Never call a helper function inside the contextmanager that calls a - # bunch of APIs. Only call the API that enforces the policy action - # contained in the decorator above. - with self.override_role(): - self._complex_setup_method() - -To fix this test, see the "Example using waiter" section above. It is -recommended to re-implement the logic in a helper method inside a test such -that only the relevant API is called inside the contextmanager, with -everything extraneous outside. - -.. _rbac-test-cleanup: - -Test Cleanup ------------- - -Automatic role override in background. - -After the test -- no matter whether it ended successfully or in failure -- -the credentials are overridden with the admin role by the Patrole framework, -*before* ``tearDown`` or ``tearDownClass`` are called. This means that -resources are always cleaned up using the admin role. diff --git a/etc/config-generator.patrole.conf b/etc/config-generator.patrole.conf deleted file mode 100644 index 8988ae00..00000000 --- a/etc/config-generator.patrole.conf +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -output_file = etc/patrole.conf.sample -namespace = patrole.config diff --git a/etc/patrole.conf.sample b/etc/patrole.conf.sample deleted file mode 100644 index 42f10421..00000000 --- a/etc/patrole.conf.sample +++ /dev/null @@ -1,172 +0,0 @@ -[DEFAULT] - - -[patrole] - -# -# From patrole.config -# - -# DEPRECATED: The current RBAC role against which to run -# Patrole tests. (string value) -# This option is deprecated for removal. -# Its value may be silently ignored in the future. -# Reason: This option is deprecated and being -# replaced with ``rbac_test_roles``. -#rbac_test_role = - -# The current RBAC roles to be assigned to Keystone -# Group against which to run Patrole tests. (list value) -#rbac_test_roles = admin - -# List of the paths to search for policy files. Each -# policy path assumes that the service name is included in the path -# once. Also -# assumes Patrole is on the same host as the policy files. The paths -# should be -# ordered by precedence, with high-priority paths before low-priority -# paths. All -# the paths that are found to contain the service's policy file will -# be used and -# all policy files will be merged. Allowed ``json`` or ``yaml`` -# formats. -# (list value) -#custom_policy_files = /etc/%s/policy.json - -# -# This option determines whether Patrole should run against a -# ``custom_requirements_file`` which defines RBAC requirements. The -# purpose of setting this flag to ``True`` is to verify that RBAC -# policy -# is in accordance to requirements. The idea is that the -# ``custom_requirements_file`` precisely defines what the RBAC -# requirements are. -# -# Here are the possible outcomes when running the Patrole tests -# against -# a ``custom_requirements_file``: -# -# YAML definition: allowed -# test run: allowed -# test result: pass -# -# YAML definition: allowed -# test run: not allowed -# test result: fail (under-permission) -# -# YAML definition: not allowed -# test run: allowed -# test result: fail (over-permission) -# (boolean value) -#test_custom_requirements = false - -# -# 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: -# -# .. code-block:: yaml -# -# : -# : -# - -# - -# - -# : -# - -# - -# : -# : -# - -# -# Where: -# -# service = the service that is being tested (cinder, nova, etc.). -# -# api_action = the policy action that is being tested. Examples: -# -# * volume:create -# * os_compute_api:servers:start -# * add_image -# -# allowed_role = the ``oslo.policy`` role that is allowed to perform -# the API. -# (string value) -#custom_requirements_file = - - -[patrole_log] - -# -# From patrole.config -# - -# Enables reporting on RBAC expected and actual test results for each -# Patrole test (boolean value) -#enable_reporting = false - -# Name of file where output from 'enable_reporting' is logged. Note -# that this file is recreated on each invocation of patrole (string -# value) -#report_log_name = patrole.log - -# Path (relative or absolute) where the output from 'enable_reporting' -# is logged. This is combined withreport_log_name to generate the full -# path. (string value) -#report_log_path = . - - -[policy-feature-enabled] - -# -# From patrole.config -# - -# Is the Neutron policy -# "create_port:fixed_ips:ip_address" available in the cloud? This -# policy was -# changed in a backwards-incompatible way. (boolean value) -#create_port_fixed_ips_ip_address_policy = true - -# Is the Neutron policy -# "update_port:fixed_ips:ip_address" available in the cloud? This -# policy was -# changed in a backwards-incompatible way. (boolean value) -#update_port_fixed_ips_ip_address_policy = true - -# Is the Cinder policy -# "limits_extension:used_limits" available in the cloud? This policy -# was -# changed in a backwards-incompatible way. (boolean value) -#limits_extension_used_limits_policy = true - -# Is the Cinder policy -# "volume_extension:volume_actions:attach" available in the cloud? -# This policy -# was changed in a backwards-incompatible way. (boolean value) -#volume_extension_volume_actions_attach_policy = true - -# Is the Cinder policy -# "volume_extension:volume_actions:reserve" available in the cloud? -# This policy -# was changed in a backwards-incompatible way. (boolean value) -#volume_extension_volume_actions_reserve_policy = true - -# Is the Cinder policy -# "volume_extension:volume_actions:unreserve" available in the cloud? -# This policy -# was changed in a backwards-incompatible way. (boolean value) -#volume_extension_volume_actions_unreserve_policy = true - -# Are the Nova API extension policies available in the -# cloud (e.g. os_compute_api:os-extended-availability-zone)? These -# policies were -# removed in Stein because Nova API extension concept was removed in -# Pike. (boolean value) -#removed_nova_policies_stein = true - -# Are the Cinder API extension policies available in the -# cloud (e.g. [create|update|get|delete]_encryption_policy)? These -# policies are -# added in Stein. (boolean value) -#added_cinder_policies_stein = true diff --git a/lower-constraints.txt b/lower-constraints.txt deleted file mode 100644 index a9fa87ac..00000000 --- a/lower-constraints.txt +++ /dev/null @@ -1,76 +0,0 @@ -alabaster==0.7.10 -appdirs==1.4.3 -asn1crypto==0.24.0 -Babel==2.5.3 -bcrypt==3.1.4 -certifi==2018.1.18 -cffi==1.14.0 -chardet==3.0.4 -cliff==2.11.0 -cmd2==0.8.1 -coverage==4.0 -cryptography==2.1.4 -debtcollector==1.19.0 -docutils==0.14 -dulwich==0.19.0 -extras==1.0.0 -fasteners==0.14.1 -fixtures==3.0.0 -future==0.16.0 -idna==2.6 -imagesize==1.0.0 -iso8601==0.1.12 -Jinja2==2.10 -jsonschema==2.6.0 -keystoneauth1==3.4.0 -linecache2==1.0.0 -MarkupSafe==1.0 -mccabe==0.2.1 -mock==2.0.0 -monotonic==1.4 -mox3==0.25.0 -msgpack==0.5.6 -netaddr==0.7.19 -netifaces==0.10.6 -nose==1.3.7 -nosexcover==1.0.10 -os-client-config==1.29.0 -oslo.concurrency==3.26.0 -oslo.config==5.2.0 -oslo.context==2.20.0 -oslo.i18n==3.20.0 -oslo.log==3.36.0 -oslo.policy==1.30.0 -oslo.serialization==2.25.0 -oslo.utils==3.36.0 -oslotest==3.2.0 -paramiko==2.4.1 -pbr==2.0.0 -prettytable==0.7.2 -pyasn1==0.4.2 -pycparser==2.18 -Pygments==2.2.0 -pyinotify==0.9.6 -PyNaCl==1.2.1 -pyparsing==2.2.0 -pyperclip==1.6.0 -python-dateutil==2.7.0 -python-mimeparse==1.6.0 -python-subunit==1.2.0 -pytz==2018.3 -PyYAML==3.13 -requests==2.18.4 -requestsexceptions==1.4.0 -rfc3986==1.1.0 -six==1.11.0 -snowballstemmer==1.2.1 -stestr==2.0.0 -stevedore==1.20.0 -tempest==30.0.0 -testrepository==0.0.20 -testtools==2.3.0 -traceback2==1.4.0 -unittest2==1.1.0 -urllib3==1.22 -voluptuous==0.11.1 -wrapt==1.10.11 diff --git a/patrole_tempest_plugin/__init__.py b/patrole_tempest_plugin/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/config.py b/patrole_tempest_plugin/config.py deleted file mode 100644 index e6d25159..00000000 --- a/patrole_tempest_plugin/config.py +++ /dev/null @@ -1,229 +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 oslo_config import cfg - - -patrole_group = cfg.OptGroup(name='patrole', title='Patrole Testing Options') - - -PatroleGroup = [ - cfg.StrOpt('rbac_test_role', - default='admin', - deprecated_for_removal=True, - deprecated_reason="""This option is deprecated and being -replaced with ``rbac_test_roles``. -""", - help="""The current RBAC role against which to run -Patrole tests."""), - cfg.ListOpt('rbac_test_roles', - help="""List of the RBAC roles against which to run -Patrole tests.""", - default=['admin']), - cfg.ListOpt('custom_policy_files', - default=['/etc/%s/policy.json'], - help="""List of the paths to search for policy files. Each -policy path assumes that the service name is included in the path once. Also -assumes Patrole is on the same host as the policy files. The paths should be -ordered by precedence, with high-priority paths before low-priority paths. All -the paths that are found to contain the service's policy file will be used and -all policy files will be merged. Allowed ``json`` or ``yaml`` formats. -"""), - cfg.BoolOpt('test_custom_requirements', - default=False, - help=""" -This option determines whether Patrole should run against a -``custom_requirements_file`` which defines RBAC requirements. The -purpose of setting this flag to ``True`` is to verify that RBAC policy -is in accordance to requirements. The idea is that the -``custom_requirements_file`` precisely defines what the RBAC requirements are. - -Here are the possible outcomes when running the Patrole tests against -a ``custom_requirements_file``: - -YAML definition: allowed -test run: allowed -test result: pass - -YAML definition: allowed -test run: not allowed -test result: fail (under-permission) - -YAML definition: not allowed -test run: allowed -test result: fail (over-permission) -"""), - cfg.StrOpt('custom_requirements_file', - help=""" -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: - -.. code-block:: yaml - - : - : - - - - - - - : - - - - - : - : - - - -Where: - -service = the service that is being tested (Cinder, Nova, etc.). - -api_action = the policy action that is being tested. Examples: - -* volume:create -* os_compute_api:servers:start -* add_image - -allowed_role = the ``oslo.policy`` role that is allowed to perform the API. -"""), - cfg.BoolOpt('validate_deprecated_rules', default=True, - help="""Some of the policy rules have deprecated version, -Patrole should be able to run check against default and deprecated rules, -otherwise the result of the tests may not be correct. -""") -] - - -patrole_log_group = cfg.OptGroup( - name='patrole_log', title='Patrole Logging Options') - - -PatroleLogGroup = [ - cfg.BoolOpt('enable_reporting', - default=False, - help="Enables reporting on RBAC expected and actual test " - "results for each Patrole test"), - cfg.StrOpt('report_log_name', - default='patrole.log', - help="Name of file where output from 'enable_reporting' is " - "logged. Note that this file is recreated on each " - "invocation of patrole"), - cfg.StrOpt('report_log_path', - default='.', - help="Path (relative or absolute) where the output from " - "'enable_reporting' is logged. This is combined with " - "report_log_name to generate the full path."), -] - - -policy_feature_enabled = cfg.OptGroup( - name='policy-feature-enabled', - title='Feature Flags for New or Changed Policies') - - -PolicyFeatureEnabledGroup = [ - # TODO(felipemonteiro): The 6 feature flags below should be removed after - # Pike is EOL. - cfg.BoolOpt('create_port_fixed_ips_ip_address_policy', - default=True, - help="""Is the Neutron policy -"create_port:fixed_ips:ip_address" available in the cloud? This policy was -changed in a backwards-incompatible way."""), - cfg.BoolOpt('update_port_fixed_ips_ip_address_policy', - default=True, - help="""Is the Neutron policy -"update_port:fixed_ips:ip_address" available in the cloud? This policy was -changed in a backwards-incompatible way."""), - cfg.BoolOpt('limits_extension_used_limits_policy', - default=True, - help="""Is the Cinder policy -"limits_extension:used_limits" available in the cloud? This policy was -changed in a backwards-incompatible way."""), - cfg.BoolOpt('volume_extension_volume_actions_attach_policy', - default=True, - help="""Is the Cinder policy -"volume_extension:volume_actions:attach" available in the cloud? This policy -was changed in a backwards-incompatible way."""), - cfg.BoolOpt('volume_extension_volume_actions_reserve_policy', - default=True, - help="""Is the Cinder policy -"volume_extension:volume_actions:reserve" available in the cloud? This policy -was changed in a backwards-incompatible way."""), - cfg.BoolOpt('volume_extension_volume_actions_unreserve_policy', - default=True, - help="""Is the Cinder policy -"volume_extension:volume_actions:unreserve" available in the cloud? This policy -was changed in a backwards-incompatible way."""), - # *** Include feature flags for groups of policies below. *** - # Best practice is to capture new policies, removed policies, renamed - # policies in a group, per release. - # - # TODO(felipemonteiro): Remove these feature flags once Stein is EOL. - cfg.BoolOpt('removed_nova_policies_stein', - default=True, - help="""Are the Nova API extension policies available in the -cloud (e.g. os_compute_api:os-extended-availability-zone)? These policies were -removed in Stein because Nova API extension concept was removed in Pike."""), - # TODO(gmann): Remove these feature flags once Victoria is EOL. - cfg.BoolOpt('removed_nova_policies_wallaby', - default=True, - help="""Are the Nova API policies being removed in wallaby -cycle (e.g. os_compute_api:os-agents)?"""), - cfg.BoolOpt('removed_keystone_policies_stein', - default=True, - help="""Are the obsolete Keystone policies available in the -cloud (e.g. identity:[create|update|get|delete]_credential)? These policies -were removed in Stein."""), - cfg.BoolOpt('added_cinder_policies_stein', - default=True, - help="""Are the Cinder Stein policies available in the cloud -(e.g. [create|update|get|delete]_encryption_policy)? These policies are added -in Stein."""), - cfg.BoolOpt('keystone_policy_enforcement_train', - default=True, - help="""Is the cloud running the Train release or newer? If -so, the Keystone Trust API is enforced differently depending on passed -arguments"""), - cfg.BoolOpt('changed_nova_policies_ussuri', - default=True, - help="""Are the Nova API policies available in the -cloud (e.g. os_compute_api:os-services)? These policies were -changed in Ussuri."""), - cfg.BoolOpt('changed_nova_policies_victoria', - default=True, - help="""Are the Nova deprecated API policies available in the -cloud (e.g. os_compute_api:os-networks)? These policies were -changed in Victoria."""), - cfg.BoolOpt('changed_cinder_policies_xena', - default=True, - help="""Are the Cinder API policies changed in the -cloud (e.g. 'group:group_types_specs')? These policies were -changed in Xena.""") -] - - -def list_opts(): - """Return a list of oslo.config options available. - - The purpose of this is to allow tools like the Oslo sample config file - generator to discover the options exposed to users. - """ - opt_list = [ - (patrole_group, PatroleGroup), - (patrole_log_group, PatroleLogGroup), - (policy_feature_enabled, PolicyFeatureEnabledGroup) - - ] - - return opt_list diff --git a/patrole_tempest_plugin/hacking/__init__.py b/patrole_tempest_plugin/hacking/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/hacking/checks.py b/patrole_tempest_plugin/hacking/checks.py deleted file mode 100644 index 48ef2695..00000000 --- a/patrole_tempest_plugin/hacking/checks.py +++ /dev/null @@ -1,249 +0,0 @@ -# Copyright 2013 IBM Corp. -# 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 os -import re - -from hacking import core -import pycodestyle - - -PYTHON_CLIENTS = ['cinder', 'glance', 'keystone', 'nova', 'swift', 'neutron', - 'ironic', 'heat', 'sahara'] - -PYTHON_CLIENT_RE = re.compile('import (%s)client' % '|'.join(PYTHON_CLIENTS)) -TEST_DEFINITION = re.compile(r'^\s*def test.*') -SETUP_TEARDOWN_CLASS_DEFINITION = re.compile(r'^\s+def (setUp|tearDown)Class') -SCENARIO_DECORATOR = re.compile(r'\s*@.*services\((.*)\)') -RAND_NAME_HYPHEN_RE = re.compile(r".*rand_name\(.+[\-\_][\"\']\)") -MUTABLE_DEFAULT_ARGS = re.compile(r"^\s*def .+\((.+=\{\}|.+=\[\])") -TESTTOOLS_SKIP_DECORATOR = re.compile(r'\s*@testtools\.skip\((.*)\)') -CLASS = re.compile(r"^class .+") -RBAC_CLASS_NAME_RE = re.compile(r'class .+RbacTest') -RULE_VALIDATION_DECORATOR = re.compile( - r'\s*@rbac_rule_validation.action\(.*') -IDEMPOTENT_ID_DECORATOR = re.compile(r'\s*@decorators\.idempotent_id\((.*)\)') -EXT_RBAC_TEST = re.compile( - r"class .+\(.+ExtRbacTest\)|class .+ExtRbacTest\(.+\)") - -have_rbac_decorator = False - - -@core.flake8ext -def import_no_clients_in_api_tests(physical_line, filename): - """Check for client imports from patrole_tempest_plugin/tests/api - - T102: Cannot import OpenStack python clients - """ - if "patrole_tempest_plugin/tests/api" in filename: - res = PYTHON_CLIENT_RE.match(physical_line) - if res: - return (physical_line.find(res.group(1)), - ("T102: python clients import not allowed " - "in patrole_tempest_plugin/tests/api/* or " - "patrole_tempest_plugin/tests/scenario/* tests")) - - -@core.flake8ext -def no_setup_teardown_class_for_tests(physical_line, filename): - """Check that tests do not use setUpClass/tearDownClass - - T105: Tests cannot use setUpClass/tearDownClass - """ - if pycodestyle.noqa(physical_line): - return - - if SETUP_TEARDOWN_CLASS_DEFINITION.match(physical_line): - return (physical_line.find('def'), - "T105: (setUp|tearDown)Class can not be used in tests") - - -@core.flake8ext -def service_tags_not_in_module_path(physical_line, filename): - """Check that a service tag isn't in the module path - - A service tag should only be added if the service name isn't already in - the module path. - - T107 - """ - matches = SCENARIO_DECORATOR.match(physical_line) - if matches: - services = matches.group(1).split(',') - for service in services: - service_name = service.strip().strip("'") - modulepath = os.path.split(filename)[0] - if service_name in modulepath: - return (physical_line.find(service_name), - "T107: service tag should not be in path") - - -@core.flake8ext -def no_hyphen_at_end_of_rand_name(logical_line, filename): - """Check no hyphen at the end of rand_name() argument - - T108 - """ - msg = "T108: hyphen should not be specified at the end of rand_name()" - if RAND_NAME_HYPHEN_RE.match(logical_line): - return 0, msg - - -@core.flake8ext -def no_mutable_default_args(logical_line): - """Check that mutable object isn't used as default argument - - N322: Method's default argument shouldn't be mutable - """ - msg = "N322: Method's default argument shouldn't be mutable!" - if MUTABLE_DEFAULT_ARGS.match(logical_line): - yield (0, msg) - - -@core.flake8ext -def no_testtools_skip_decorator(logical_line): - """Check that methods do not have the testtools.skip decorator - - T109 - """ - if TESTTOOLS_SKIP_DECORATOR.match(logical_line): - yield (0, "T109: Cannot use testtools.skip decorator; instead use " - "decorators.skip_because from tempest.lib") - - -@core.flake8ext -def use_rand_uuid_instead_of_uuid4(logical_line, filename): - """Check that tests use data_utils.rand_uuid() instead of uuid.uuid4() - - T113 - """ - if 'uuid.uuid4()' not in logical_line: - return - - msg = ("T113: Tests should use data_utils.rand_uuid()/rand_uuid_hex() " - "instead of uuid.uuid4()/uuid.uuid4().hex") - yield (0, msg) - - -@core.flake8ext -def no_rbac_rule_validation_decorator(physical_line, filename): - """Check that each test has the ``rbac_rule_validation.action`` decorator. - - Checks whether the test function has "@rbac_rule_validation.action" - above it; otherwise checks that it has "@decorators.idempotent_id" above - it and "@rbac_rule_validation.action" above that. - - Assumes that ``rbac_rule_validation.action`` decorator is either the first - or second decorator above the test function; otherwise this check fails. - - P100 - """ - global have_rbac_decorator - - if ("patrole_tempest_plugin/tests/api" in filename or - "patrole_tempest_plugin/tests/scenario" in filename): - - if RULE_VALIDATION_DECORATOR.match(physical_line): - have_rbac_decorator = True - return - - if TEST_DEFINITION.match(physical_line): - if not have_rbac_decorator: - return (0, "Must use rbac_rule_validation.action " - "decorator for API and scenario tests") - - have_rbac_decorator = False - - -@core.flake8ext -def no_rbac_suffix_in_test_filename(filename): - """Check that RBAC filenames end with "_rbac" suffix. - - P101 - """ - if "patrole_tempest_plugin/tests/api" in filename: - - if filename.endswith('rbac_base.py'): - return - - if not filename.endswith('_rbac.py'): - return 0, "RBAC test filenames must end in _rbac suffix" - - -@core.flake8ext -def no_rbac_test_suffix_in_test_class_name(physical_line, filename): - """Check that RBAC class names end with "RbacTest" - - P102 - """ - if "patrole_tempest_plugin/tests/api" in filename: - - if filename.endswith('rbac_base.py'): - return - - if CLASS.match(physical_line): - if not RBAC_CLASS_NAME_RE.match(physical_line): - return 0, "RBAC test class names must end in 'RbacTest'" - - -@core.flake8ext -def no_client_alias_in_test_cases(logical_line, filename): - """Check that test cases don't use "self.client" to define a client. - - P103 - """ - if "patrole_tempest_plugin/tests/api" in filename: - if "self.client" in logical_line or "cls.client" in logical_line: - return 0, "Do not use 'self.client' as a service client alias" - - -@core.flake8ext -def no_extension_rbac_test_suffix_in_plugin_test_class_name(physical_line, - filename): - """Check that Extension RBAC class names end with "ExtRbacTest" - - P104 - """ - suffix = "ExtRbacTest" - if "patrole_tempest_plugin/tests/api" in filename: - if EXT_RBAC_TEST.match(physical_line): - subclass, superclass = physical_line.split('(') - subclass = subclass.split('class')[1].strip() - superclass = superclass.split(')')[0].strip() - if "." in superclass: - superclass = superclass.split(".")[1] - - both_have = all( - clazz.endswith(suffix) for clazz in [subclass, superclass]) - none_have = not any( - clazz.endswith(suffix) for clazz in [subclass, superclass]) - - if not (both_have or none_have): - if (subclass.startswith("Base") and - superclass.startswith("Base")): - return - - # Case 1: Subclass of "BaseExtRbacTest" must end in `suffix` - # Case 2: Subclass that ends in `suffix` must inherit from base - # class ending in `suffix`. - if not subclass.endswith(suffix): - error = ("Plugin RBAC test subclasses must end in " - "'ExtRbacTest'") - return len(subclass) - 1, error - elif not superclass.endswith(suffix): - error = ("Plugin RBAC test subclasses must inherit from a " - "'ExtRbacTest' base class") - return len(superclass) - 1, error diff --git a/patrole_tempest_plugin/plugin.py b/patrole_tempest_plugin/plugin.py deleted file mode 100644 index 8af6a69d..00000000 --- a/patrole_tempest_plugin/plugin.py +++ /dev/null @@ -1,86 +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. - -import logging -import os - -from oslo_concurrency import lockutils - -from tempest import config -from tempest.test_discover import plugins - -from patrole_tempest_plugin import config as pconfig - -RBACLOG = logging.getLogger('rbac_reporting') - - -class PatroleTempestPlugin(plugins.TempestPlugin): - - def load_tests(self): - base_path = os.path.split(os.path.dirname( - os.path.abspath(__file__)))[0] - test_dir = "patrole_tempest_plugin/tests/api" - full_test_dir = os.path.join(base_path, test_dir) - return full_test_dir, base_path - - @lockutils.synchronized('_reset_log_file') - def _reset_log_file(self, logfile): - try: - os.remove(logfile) - except OSError: - pass - - def _configure_per_test_logging(self, conf): - # Separate log handler for rbac reporting - RBACLOG.setLevel(level=logging.INFO) - # Set up proper directory handling - report_abs_path = os.path.abspath(conf.patrole_log.report_log_path) - report_path = os.path.join( - report_abs_path, conf.patrole_log.report_log_name) - - # Remove the log file if it exists - self._reset_log_file(report_path) - - # Delay=True so that we don't end up creating an empty file if we - # never log to it. - rbac_report_handler = logging.FileHandler( - filename=report_path, delay=True, mode='a') - rbac_report_handler.setFormatter( - fmt=logging.Formatter(fmt='%(message)s')) - RBACLOG.addHandler(rbac_report_handler) - - def register_opts(self, conf): - config.register_opt_group( - conf, - pconfig.patrole_group, - pconfig.PatroleGroup) - config.register_opt_group( - conf, - pconfig.patrole_log_group, - pconfig.PatroleLogGroup) - config.register_opt_group( - conf, - pconfig.policy_feature_enabled, - pconfig.PolicyFeatureEnabledGroup) - - if conf.patrole_log.enable_reporting: - self._configure_per_test_logging(conf) - - def get_opt_lists(self): - return [ - (pconfig.patrole_group.name, pconfig.PatroleGroup), - (pconfig.policy_feature_enabled.name, - pconfig.PolicyFeatureEnabledGroup) - ] diff --git a/patrole_tempest_plugin/policy_authority.py b/patrole_tempest_plugin/policy_authority.py deleted file mode 100644 index 914f2f9a..00000000 --- a/patrole_tempest_plugin/policy_authority.py +++ /dev/null @@ -1,330 +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. - -import collections -import copy -import glob -import os - -from oslo_log import log as logging -from oslo_policy import policy -import pkg_resources -import stevedore -from tempest import config - -from patrole_tempest_plugin.rbac_authority import RbacAuthority -from patrole_tempest_plugin import rbac_exceptions - -CONF = config.CONF -LOG = logging.getLogger(__name__) - - -class PolicyAuthority(RbacAuthority): - """A class that uses ``oslo.policy`` for validating RBAC.""" - os_admin = None - - def __init__(self, project_id, user_id, service, extra_target_data=None): - """Initialization of Policy Authority class. - - Validates whether a test role can perform a policy action by querying - ``oslo.policy`` with necessary test data. - - If a policy file does not exist, checks whether the policy file is - registered as a namespace under "oslo.policy.policies". Nova, for - example, doesn't use a policy file by default; its policies are - implemented in code and registered as "nova" under - "oslo.policy.policies". - - If the policy file is not found in either code or in a policy file, - then an exception is raised. - - Additionally, if a custom policy file exists along with the default - policy in code implementation, the custom policy is prioritized. - - :param uuid project_id: project_id of object performing API call - :param uuid user_id: user_id of object performing API call - :param string service: service of the policy file - :param dict extra_target_data: dictionary containing additional object - data needed by oslo.policy to validate generic checks - - Example: - - .. code-block:: python - - # Below is the default policy implementation in code, defined in - # a service like Nova. - test_policies = [ - policy.DocumentedRuleDefault( - 'service:test_rule', - base.RULE_ADMIN_OR_OWNER, - "This is a description for a test policy", - [ - { - 'method': 'POST', - 'path': '/path/to/test/resource' - } - ]), - 'service:another_test_rule', - base.RULE_ADMIN_OR_OWNER, - "This is a description for another test policy", - [ - { - 'method': 'GET', - 'path': '/path/to/test/resource' - } - ]), - ] - - .. code-block:: yaml - - # Below is the custom override of the default policy in a YAML - # policy file. Note that the default rule is "rule:admin_or_owner" - # and the custom rule is "rule:admin_api". The `PolicyAuthority` - # class will use the "rule:admin_api" definition for this policy - # action. - "service:test_rule" : "rule:admin_api" - - # Note below that no override is provided for - # "service:another_test_rule", which means that the default policy - # rule is used: "rule:admin_or_owner". - """ - - if extra_target_data is None: - extra_target_data = {} - - self.service = self.validate_service(service) - - # Prioritize dynamically searching for policy files over relying on - # deprecated service-specific policy file locations. - if CONF.patrole.custom_policy_files: - self.discover_policy_files() - - self.rules = self.get_rules() - self.project_id = project_id - self.user_id = user_id - self.extra_target_data = extra_target_data - - @classmethod - def validate_service(cls, service): - """Validate whether the service passed to ``__init__`` exists.""" - service = service.lower().strip() if service else None - - # Cache the list of available services in memory to avoid needlessly - # doing an API call every time. - if not hasattr(cls, 'available_services') and cls.os_admin: - services_client = (cls.os_admin.identity_services_v3_client - if CONF.identity_feature_enabled.api_v3 - else cls.os_admin.identity_services_client) - services = services_client.list_services()['services'] - cls.available_services = [s['name'] for s in services] - - if not service or service not in cls.available_services: - LOG.debug("%s is NOT a valid service.", service) - raise rbac_exceptions.RbacInvalidServiceException( - "%s is NOT a valid service." % service) - - return service - - @classmethod - def discover_policy_files(cls): - """Dynamically discover the policy file for each service in - ``cls.available_services``. Pick all candidate paths found - out of the potential paths in ``[patrole] custom_policy_files``. - """ - if not hasattr(cls, 'policy_files'): - cls.policy_files = collections.defaultdict(list) - for service in cls.available_services: - for candidate_path in CONF.patrole.custom_policy_files: - path = candidate_path % service - for filename in glob.iglob(path): - if os.path.isfile(filename): - cls.policy_files[service].append(filename) - - def allowed(self, rule_name, roles): - """Checks if a given rule in a policy is allowed with given role. - - :param string rule_name: Policy name to pass to``oslo.policy``. - :param List[string] roles: List of roles to validate for authorization. - :raises RbacParsingException: If ``rule_name`` does not exist in the - cloud (in policy file or among registered in-code policy defaults). - """ - is_admin_context = self._is_admin_context(roles) - is_allowed = self._allowed( - access=self._get_access_token(roles), - apply_rule=rule_name, - is_admin=is_admin_context) - return is_allowed - - def _handle_deprecated_rule(self, default): - deprecated_rule = default.deprecated_rule - deprecated_msg = ( - 'Policy "%(old_name)s":"%(old_check_str)s" was deprecated in ' - '%(release)s in favor of "%(name)s":"%(check_str)s". Reason: ' - '%(reason)s. Either ensure your deployment is ready for the new ' - 'default or copy/paste the deprecated policy into your policy ' - 'file and maintain it manually.' % { - 'old_name': deprecated_rule.name, - 'old_check_str': deprecated_rule.check_str, - 'release': default.deprecated_since, - 'name': default.name, - 'check_str': default.check_str, - 'reason': default.deprecated_reason - } - ) - LOG.warn(deprecated_msg) - oslo_policy_version = pkg_resources.parse_version( - pkg_resources.get_distribution("oslo.policy").version) - # NOTE(gmann): oslo policy 3.7.0 onwards does not allow to modify - # the Rule object check attribute. - required_version = pkg_resources.parse_version('3.7.0') - if oslo_policy_version >= required_version: - return policy.OrCheck([default.check, deprecated_rule.check]) - else: - default.check = policy.OrCheck( - [policy._parser.parse_rule(cs) for cs in - [default.check_str, - deprecated_rule.check_str]]) - return default.check - - def get_rules(self): - rules = policy.Rules() - # Check whether policy file exists and attempt to read it. - for path in self.policy_files[self.service]: - try: - with open(path, 'r') as fp: - for k, v in policy.Rules.load(fp.read()).items(): - if k not in rules: - rules[k] = v - # If the policy name and rule are the same, no - # ambiguity, so no reason to warn. - elif str(v) != str(rules[k]): - msg = ("The same policy name: %s was found in " - "multiple policies files for service %s. " - "This can lead to policy rule ambiguity. " - "Using rule: %s; Rule from file: %s") - LOG.warning(msg, k, self.service, rules[k], v) - except (ValueError, IOError): - LOG.warning("Failed to read policy file '%s' for service %s.", - path, self.service) - - # Check whether policy actions are defined in code. Nova and Keystone, - # for example, define their default policy actions in code. - mgr = stevedore.named.NamedExtensionManager( - 'oslo.policy.policies', - names=[self.service], - invoke_on_load=True, - warn_on_missing_entrypoint=False) - - if mgr: - policy_generator = {plc.name: plc.obj for plc in mgr} - if self.service in policy_generator: - for rule in policy_generator[self.service]: - if rule.name not in rules: - if CONF.patrole.validate_deprecated_rules: - # NOTE (sergey.vilgelm): - # The `DocumentedRuleDefault` object has no - # `deprecated_rule` attribute in Pike - check = rule.check - if getattr(rule, 'deprecated_rule', False): - check = self._handle_deprecated_rule(rule) - rules[rule.name] = check - elif str(rule.check) != str(rules[rule.name]): - msg = ("The same policy name: %s was found in the " - "policies files and in the code for service " - "%s. This can lead to policy rule ambiguity. " - "Using rule: %s; Rule from code: %s") - LOG.warning(msg, rule.name, self.service, - rules[rule.name], rule.check) - - if not rules: - msg = ( - 'Policy files for {0} service were not found among the ' - 'registered in-code policies or in any of the possible policy ' - 'files: {1}.'.format( - self.service, - [loc % self.service - for loc in CONF.patrole.custom_policy_files])) - raise rbac_exceptions.RbacParsingException(msg) - - return rules - - def _is_admin_context(self, roles): - """Checks whether a role has admin context. - - If context_is_admin is contained in the policy file, then checks - whether the given role is contained in context_is_admin. If it is not - in the policy file, then default to context_is_admin: admin. - """ - if 'context_is_admin' in self.rules: - return self._allowed( - access=self._get_access_token(roles), - apply_rule='context_is_admin') - return CONF.identity.admin_role in roles - - def _get_access_token(self, roles): - access_token = { - "token": { - "roles": [{'name': r} for r in roles], - "project_id": self.project_id, - "tenant_id": self.project_id, - "user_id": self.user_id - } - } - return access_token - - def _allowed(self, access, apply_rule, is_admin=False): - """Checks if a given rule in a policy is allowed with given ``access``. - - :param dict access: Dictionary from ``_get_access_token``. - :param string apply_rule: Rule to be checked using ``oslo.policy``. - :param bool is_admin: Whether admin context is used. - """ - access_data = copy.copy(access['token']) - access_data['roles'] = [role['name'] for role in access_data['roles']] - access_data['is_admin'] = is_admin - # TODO(felipemonteiro): Dynamically calculate is_admin_project rather - # than hard-coding it to True. is_admin_project cannot be determined - # from the role, but rather from project and domain names. For more - # information, see: - # https://git.openstack.org/cgit/openstack/keystone/tree/keystone/token/providers/common.py?id=37ce5417418f8acbd27f3dacb70c605b0fe48301#n150 - access_data['is_admin_project'] = True - - class Object(object): - pass - o = Object() - o.rules = self.rules - - target = {"project_id": access_data['project_id'], - "tenant_id": access_data['project_id'], - "network:tenant_id": access_data['project_id'], - "user_id": access_data['user_id']} - if self.extra_target_data: - target.update(self.extra_target_data) - - result = self._try_rule(apply_rule, target, access_data, o) - return result - - def _try_rule(self, apply_rule, target, access_data, o): - if apply_rule not in self.rules: - message = ('Policy action "{0}" not found in policy files: ' - '{1} or among registered policy in code defaults for ' - '{2} service.').format(apply_rule, - self.policy_files[self.service], - self.service) - LOG.debug(message) - raise rbac_exceptions.RbacParsingException(message) - else: - rule = self.rules[apply_rule] - return rule(target, access_data, o) diff --git a/patrole_tempest_plugin/rbac_authority.py b/patrole_tempest_plugin/rbac_authority.py deleted file mode 100644 index 294ecc51..00000000 --- a/patrole_tempest_plugin/rbac_authority.py +++ /dev/null @@ -1,38 +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. - -import abc - -import six - - -@six.add_metaclass(abc.ABCMeta) -class RbacAuthority(object): - """Class for validating whether a given role can perform a policy action. - - Any class that extends ``RbacAuthority`` provides the logic for determining - whether a role has permissions to execute a policy action. - """ - - @abc.abstractmethod - def allowed(self, rule, role): - """Determine whether the role should be able to perform the API. - - :param rule: The name of the policy enforced by the API. - :param role: The role used to determine whether ``rule`` can be - executed. - :returns: True if the ``role`` has permissions to execute - ``rule``, else False. - """ diff --git a/patrole_tempest_plugin/rbac_exceptions.py b/patrole_tempest_plugin/rbac_exceptions.py deleted file mode 100644 index c30961ba..00000000 --- a/patrole_tempest_plugin/rbac_exceptions.py +++ /dev/null @@ -1,119 +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 exceptions - - -class BasePatroleException(exceptions.TempestException): - message = "An unknown RBAC exception occurred" - - -class BasePatroleResponseBodyException(BasePatroleException): - message = "Response body incomplete due to RBAC authorization failure" - - -class RbacMissingAttributeResponseBody(BasePatroleResponseBodyException): - """Raised when a list or show action is missing an attribute following - RBAC authorization failure. - """ - message = ("The response body is missing the expected %(attribute)s due " - "to policy enforcement failure") - - -class RbacPartialResponseBody(BasePatroleResponseBodyException): - """Raised when a list action only returns a subset of the available - resources. - - For example, admin can return more resources than member for a list action. - """ - message = ("The response body only lists a subset of the available " - "resources due to partial policy enforcement failure. Response " - "body: %(body)s") - - -class RbacEmptyResponseBody(BasePatroleResponseBodyException): - """Raised when a list or show action is empty following RBAC authorization - failure. - """ - message = "The response body is empty due to policy enforcement failure." - - -class RbacResourceSetupFailed(BasePatroleException): - message = "RBAC resource setup failed" - - -class RbacOverPermissionException(BasePatroleException): - """Raised when the expected result is failure but the actual result is - pass. - """ - message = "Unauthorized action was allowed to be performed" - - -class RbacUnderPermissionException(BasePatroleException): - """Raised when the expected result is pass but the actual result is - failure. - """ - message = "Authorized action was not allowed to be performed" - - -class RbacExpectedWrongException(BasePatroleException): - """Raised when the expected exception does not match the actual exception - raised, when both are instances of Forbidden or NotFound, indicating - the test provides a wrong argument to `expected_error_codes`. - """ - message = ("Expected %(expected)s to be raised but %(actual)s was raised " - "instead. Actual exception: %(exception)s") - - -class RbacInvalidServiceException(BasePatroleException): - """Raised when an invalid service is passed to ``rbac_rule_validation`` - decorator. - """ - message = "Attempted to test an invalid service" - - -class RbacParsingException(BasePatroleException): - message = "Attempted to test an invalid policy file or action" - - -class RbacInvalidErrorCode(BasePatroleException): - message = "Unsupported error code passed in test" - - -class RbacOverrideRoleException(BasePatroleException): - """Raised when override_role is used incorrectly or fails somehow. - - Used for safeguarding against false positives that might occur when the - expected exception isn't raised inside the ``override_role`` context. - Specifically, when: - - * ``override_role`` isn't called - * an exception is raised before ``override_role`` context - * an exception is raised after ``override_role`` context - """ - message = "Override role failure or incorrect usage" - - -class RbacValidateListException(BasePatroleException): - """Raised when override_role_and_validate_list is used incorrectly. - - Specifically, when: - - * Neither ``resource_id`` nor ``resources`` is initialized - * Both ``resource_id`` and ``resources`` are initialized - * The ``ctx.resources`` variable wasn't set in - override_role_and_validate_list context. - """ - message = "Incorrect usage of override_role_and_validate_list: %(reason)s" diff --git a/patrole_tempest_plugin/rbac_rule_validation.py b/patrole_tempest_plugin/rbac_rule_validation.py deleted file mode 100644 index 9334702d..00000000 --- a/patrole_tempest_plugin/rbac_rule_validation.py +++ /dev/null @@ -1,516 +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. - -import functools -import logging -import sys - -from oslo_log import versionutils -from oslo_utils import excutils -import six - -from tempest import config -from tempest.lib import exceptions as lib_exc -from tempest import test - -from patrole_tempest_plugin import policy_authority -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import requirements_authority -import testtools - - -CONF = config.CONF -LOG = logging.getLogger(__name__) - -_SUPPORTED_ERROR_CODES = [403, 404] -_DEFAULT_ERROR_CODE = 403 - -RBACLOG = logging.getLogger('rbac_reporting') - - -def action(service, - rules=None, - expected_error_codes=None, - extra_target_data=None): - """A decorator for verifying OpenStack policy enforcement. - - A decorator which allows for positive and negative RBAC testing. Given: - - * an OpenStack service, - * a policy action (``rule``) enforced by that service, and - * the test roles defined by ``[patrole] rbac_test_roles`` - - determines whether the test role has sufficient permissions to perform an - API call that enforces the ``rule``. - - This decorator should only be applied to an instance or subclass of - ``tempest.test.BaseTestCase``. - - The result from ``_is_authorized`` is used to determine the *expected* - test result. The *actual* test result is determined by running the - Tempest test this decorator applies to. - - Below are the following possibilities from comparing the *expected* and - *actual* results: - - 1) If *expected* is True and the test passes (*actual*), this is a success. - 2) If *expected* is True and the test fails (*actual*), this results in a - ``RbacUnderPermissionException`` exception failure. - 3) If *expected* is False and the test passes (*actual*), this results in - an ``RbacOverPermissionException`` exception failure. - 4) If *expected* is False and the test fails (*actual*), this is a success. - - As such, negative and positive testing can be applied using this decorator. - - :param str service: An OpenStack service. Examples: "nova" or "neutron". - :param list rules: A list of policy actions defined in a policy file or in - code. The rules are logical-ANDed together to derive the expected - result. Also accepts list of callables that return a policy action. - - .. note:: - - Patrole currently only supports custom JSON policy files. - - :type rules: list[str] or list[callable] - :param list expected_error_codes: When the ``rules`` list parameter is - used, then this list indicates the expected error code to use if one - of the rules does not allow the role being tested. This list must - coincide with and its elements remain in the same order as the rules - in the rules list. - - Example:: - - rules=["api_action1", "api_action2"] - expected_error_codes=[404, 403] - - a) If api_action1 fails and api_action2 passes, then the expected - error code is 404. - b) if api_action2 fails and api_action1 passes, then the expected - error code is 403. - c) if both api_action1 and api_action2 fail, then the expected error - code is the first error seen (404). - - If it is not passed, then it is defaulted to 403. - - .. warning:: - - A 404 should not be provided *unless* the endpoint masks a - ``Forbidden`` exception as a ``NotFound`` exception. - - :type expected_error_codes: list[int] - :param dict extra_target_data: Dictionary, keyed with ``oslo.policy`` - generic check names, whose values are string literals that reference - nested ``tempest.test.BaseTestCase`` attributes. Used by - ``oslo.policy`` for performing matching against attributes that are - sent along with the API calls. Example:: - - extra_target_data={ - "target.token.user_id": - "os_alt.auth_provider.credentials.user_id" - }) - - :raises RbacInvalidServiceException: If ``service`` is invalid. - :raises RbacUnderPermissionException: For item (2) above. - :raises RbacOverPermissionException: For item (3) above. - :raises RbacExpectedWrongException: When a 403 is expected but a 404 - is raised instead or vice versa. - - Examples:: - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-agents"]) - def test_list_agents_rbac(self): - # The call to `override_role` is mandatory. - with self.override_role(): - self.agents_client.list_agents() - """ - - if extra_target_data is None: - extra_target_data = {} - - rules, expected_error_codes = _prepare_multi_policy(rules, - expected_error_codes) - - def decorator(test_func): - roles = CONF.patrole.rbac_test_roles - # TODO(vegasq) drop once CONF.patrole.rbac_test_role is removed - if CONF.patrole.rbac_test_role: - msg = ('CONF.patrole.rbac_test_role is deprecated in favor of ' - 'CONF.patrole.rbac_test_roles and will be removed in ' - 'future.') - versionutils.report_deprecated_feature(LOG, msg) - if not roles: - roles.append(CONF.patrole.rbac_test_role) - - @functools.wraps(test_func) - def wrapper(*args, **kwargs): - if args and isinstance(args[0], test.BaseTestCase): - test_obj = args[0] - else: - raise rbac_exceptions.RbacResourceSetupFailed( - '`rbac_rule_validation` decorator can only be applied to ' - 'an instance of `tempest.test.BaseTestCase`.') - - allowed = True - disallowed_rules = [] - for rule in rules: - _allowed = _is_authorized( - test_obj, service, rule, extra_target_data) - if not _allowed: - disallowed_rules.append(rule) - allowed = allowed and _allowed - - if disallowed_rules: - # Choose the first disallowed rule and expect the error - # code corresponding to it. - first_error_index = rules.index(disallowed_rules[0]) - exp_error_code = expected_error_codes[first_error_index] - LOG.debug("%s: Expecting %d to be raised for policy name: %s", - test_func.__name__, exp_error_code, - disallowed_rules[0]) - else: - exp_error_code = expected_error_codes[0] - - expected_exception, irregular_msg = _get_exception_type( - exp_error_code) - - caught_exception = None - test_status = 'Allowed' - - try: - test_func(*args, **kwargs) - except rbac_exceptions.RbacInvalidServiceException: - with excutils.save_and_reraise_exception(): - msg = ("%s is not a valid service." % service) - # FIXME(felipemonteiro): This test_status is logged too - # late. Need a function to log it before re-raising. - test_status = ('Error, %s' % (msg)) - LOG.error(msg) - except (expected_exception, - rbac_exceptions.BasePatroleResponseBodyException) \ - as actual_exception: - caught_exception = actual_exception - test_status = 'Denied' - - if irregular_msg: - LOG.warning(irregular_msg, - test_func.__name__, - ', '.join(rules), - service) - - if allowed: - msg = ("User with roles %s was not allowed to perform the " - "following actions: %s. Expected allowed actions: " - "%s. Expected disallowed actions: %s." % ( - roles, sorted(rules), - sorted(set(rules) - set(disallowed_rules)), - sorted(disallowed_rules))) - LOG.error(msg) - raise rbac_exceptions.RbacUnderPermissionException( - "%s Exception was: %s" % (msg, actual_exception)) - except Exception as actual_exception: - caught_exception = actual_exception - - if _check_for_expected_mismatch_exception(expected_exception, - actual_exception): - LOG.error('Expected and actual exceptions do not match. ' - 'Expected: %s. Actual: %s.', - expected_exception, - actual_exception.__class__) - raise rbac_exceptions.RbacExpectedWrongException( - expected=expected_exception, - actual=actual_exception.__class__, - exception=actual_exception) - else: - with excutils.save_and_reraise_exception(): - exc_info = sys.exc_info() - error_details = six.text_type(exc_info[1]) - msg = ("An unexpected exception has occurred during " - "test: %s. Exception was: %s" % ( - test_func.__name__, error_details)) - test_status = 'Error, %s' % (error_details) - LOG.error(msg) - else: - if not allowed: - msg = ( - "OverPermission: Role %s was allowed to perform the " - "following disallowed actions: %s" % ( - roles, sorted(disallowed_rules) - ) - ) - LOG.error(msg) - raise rbac_exceptions.RbacOverPermissionException(msg) - finally: - if CONF.patrole_log.enable_reporting: - RBACLOG.info( - "[Service]: %s, [Test]: %s, [Rules]: %s, " - "[Expected]: %s, [Actual]: %s", - service, test_func.__name__, ', '.join(rules), - "Allowed" if allowed else "Denied", - test_status) - - # Sanity-check that ``override_role`` was called to eliminate - # false-positives and bad test flows resulting from exceptions - # getting raised too early, too late or not at all, within - # the scope of an RBAC test. - _validate_override_role_called( - test_obj, - actual_exception=caught_exception) - - return wrapper - return decorator - - -def _prepare_multi_policy(rules, exp_error_codes): - if exp_error_codes: - if not rules: - msg = ("The `rules` list must be provided if using the " - "`expected_error_codes` list.") - raise ValueError(msg) - if len(rules) != len(exp_error_codes): - msg = ("The `expected_error_codes` list is not the same length " - "as the `rules` list.") - raise ValueError(msg) - if not isinstance(exp_error_codes, (tuple, list)): - exp_error_codes = [exp_error_codes] - else: - exp_error_codes = [] - - if rules is None: - rules = [] - elif not isinstance(rules, (tuple, list)): - rules = [rules] - - # Fill in the exp_error_codes if needed. This is needed for the scenarios - # where no exp_error_codes array is provided, so the error codes must be - # set to the default error code value and there must be the same number - # of error codes as rules. - num_ecs = len(exp_error_codes) - num_rules = len(rules) - if (num_ecs < num_rules): - for i in range(num_rules - num_ecs): - exp_error_codes.append(_DEFAULT_ERROR_CODE) - - evaluated_rules = [ - r() if callable(r) else r for r in rules - ] - - return evaluated_rules, exp_error_codes - - -def _is_authorized(test_obj, service, rule, extra_target_data): - """Validates whether current RBAC role has permission to do policy action. - - :param test_obj: An instance or subclass of ``tempest.test.BaseTestCase``. - :param service: The OpenStack service that enforces ``rule``. - :param rule: The name of the policy action. Examples include - "identity:create_user" or "os_compute_api:os-agents". - :param extra_target_data: Dictionary, keyed with ``oslo.policy`` generic - check names, whose values are string literals that reference nested - ``tempest.test.BaseTestCase`` attributes. Used by ``oslo.policy`` for - performing matching against attributes that are sent along with the API - calls. - - :returns: True if the current RBAC role can perform the policy action, - else False. - - :raises RbacResourceSetupFailed: If `project_id` or `user_id` are missing - from the `auth_provider` attribute in `test_obj`. - """ - - try: - project_id = test_obj.os_primary.credentials.project_id - user_id = test_obj.os_primary.credentials.user_id - except AttributeError as e: - msg = ("{0}: project_id or user_id not found in os_primary.credentials" - .format(e)) - LOG.error(msg) - raise rbac_exceptions.RbacResourceSetupFailed(msg) - - roles = CONF.patrole.rbac_test_roles - # TODO(vegasq) drop once CONF.patrole.rbac_test_role is removed - if CONF.patrole.rbac_test_role: - if not roles: - roles.append(CONF.patrole.rbac_test_role) - - # Adding implied roles - roles = test_obj.get_all_needed_roles(roles) - - # Test RBAC against custom requirements. Otherwise use oslo.policy. - if CONF.patrole.test_custom_requirements: - authority = requirements_authority.RequirementsAuthority( - CONF.patrole.custom_requirements_file, service) - else: - formatted_target_data = _format_extra_target_data( - test_obj, extra_target_data) - policy_authority.PolicyAuthority.os_admin = test_obj.os_admin - authority = policy_authority.PolicyAuthority( - project_id, user_id, service, - extra_target_data=formatted_target_data) - - is_allowed = authority.allowed(rule, roles) - - if is_allowed: - LOG.debug("[Policy action]: %s, [Role]: %s is allowed!", rule, - roles) - else: - LOG.debug("[Policy action]: %s, [Role]: %s is NOT allowed!", - rule, roles) - - return is_allowed - - -def _get_exception_type(expected_error_code=_DEFAULT_ERROR_CODE): - """Dynamically calculate the expected exception to be caught. - - Dynamically calculate the expected exception to be caught by the test case. - Only ``Forbidden`` and ``NotFound`` exceptions are permitted. ``NotFound`` - is supported because Neutron, for security reasons, masks ``Forbidden`` - exceptions as ``NotFound`` exceptions. - - :param expected_error_code: the integer representation of the expected - exception to be caught. Must be contained in - ``_SUPPORTED_ERROR_CODES``. - :returns: tuple of the exception type corresponding to - ``expected_error_code`` and a message explaining that a non-Forbidden - exception was expected, if applicable. - """ - expected_exception = None - irregular_msg = None - - if not isinstance(expected_error_code, six.integer_types) \ - or expected_error_code not in _SUPPORTED_ERROR_CODES: - msg = ("Please pass an expected error code. Currently " - "supported codes: {0}".format(_SUPPORTED_ERROR_CODES)) - LOG.error(msg) - raise rbac_exceptions.RbacInvalidErrorCode(msg) - - if expected_error_code == 403: - expected_exception = lib_exc.Forbidden - elif expected_error_code == 404: - expected_exception = lib_exc.NotFound - irregular_msg = ("NotFound exception was caught for test %s. Expected " - "policies which may have caused the error: %s. The " - "service %s throws a 404 instead of a 403, which is " - "irregular") - return expected_exception, irregular_msg - - -def _format_extra_target_data(test_obj, extra_target_data): - """Formats the "extra_target_data" dictionary with correct test data. - - Before being formatted, "extra_target_data" is a dictionary that maps a - policy string like "trust.trustor_user_id" to a nested list of - ``tempest.test.BaseTestCase`` attributes. For example, the attribute list - in:: - - "trust.trustor_user_id": "os.auth_provider.credentials.user_id" - - is parsed by iteratively calling ``getattr`` until the value of "user_id" - is resolved. The resulting dictionary returns:: - - "trust.trustor_user_id": "the user_id of the `os_primary` credential" - - :param test_obj: An instance or subclass of ``tempest.test.BaseTestCase``. - :param extra_target_data: Dictionary, keyed with ``oslo.policy`` generic - check names, whose values are string literals that reference nested - ``tempest.test.BaseTestCase`` attributes. Used by ``oslo.policy`` for - performing matching against attributes that are sent along with the API - calls. - :returns: Dictionary containing additional object data needed by - ``oslo.policy`` to validate generic checks. - """ - attr_value = test_obj - formatted_target_data = {} - - for user_attribute, attr_string in extra_target_data.items(): - attrs = attr_string.split('.') - for attr in attrs: - attr_value = getattr(attr_value, attr) - formatted_target_data[user_attribute] = attr_value - - return formatted_target_data - - -def _check_for_expected_mismatch_exception(expected_exception, - actual_exception): - """Checks that ``expected_exception`` matches ``actual_exception``. - - Since Patrole must handle 403/404 it is important that the expected and - actual error codes match. - - :param excepted_exception: Expected exception for test. - :param actual_exception: Actual exception raised by test. - :returns: True if match, else False. - :rtype: boolean - """ - permission_exceptions = (lib_exc.Forbidden, lib_exc.NotFound) - if isinstance(actual_exception, permission_exceptions): - if not isinstance(actual_exception, expected_exception.__class__): - return True - return False - - -def _validate_override_role_called(test_obj, actual_exception): - """Validates that :func:`rbac_utils.RbacUtilsMixin.override_role` is called - during each Patrole test. - - Useful for validating that the expected exception isn't raised too early - (before ``override_role`` call) or too late (after ``override_call``) or - at all (which is a bad test). - - :param test_obj: An instance or subclass of ``tempest.test.BaseTestCase``. - :param actual_exception: Actual exception raised by test. - :raises RbacOverrideRoleException: If ``override_role`` isn't called, is - called too early, or is called too late. - """ - called = test_obj._validate_override_role_called() - base_msg = ('This error is unrelated to RBAC and is due to either ' - 'an API or override role failure. Exception: %s' % - actual_exception) - - if not called: - if actual_exception is not None: - # Use testtools skipException in base TestCase - # to support different skip exceptions used. - # Just return so the skip exception will go up - # the stack and be handled by the unit testing framework - if isinstance(actual_exception, - testtools.testcase.TestCase.skipException): - return - msg = ('Caught exception (%s) but it was raised before the ' - '`override_role` context. ' % actual_exception.__class__) - else: - msg = 'Test missing required `override_role` call. ' - msg += base_msg - LOG.error(msg) - raise rbac_exceptions.RbacOverrideRoleException(msg) - else: - exc_caught_in_ctx = test_obj._validate_override_role_caught_exc() - # This block is only executed if ``override_role`` is called. If - # an exception is raised and the exception wasn't raised in the - # ``override_role`` context and if the exception isn't a valid - # exception type (instance of ``BasePatroleException``), then this is - # a legitimate error. - if (not exc_caught_in_ctx and - actual_exception is not None and - not isinstance(actual_exception, - rbac_exceptions.BasePatroleException)): - msg = ('Caught exception (%s) but it was raised after the ' - '`override_role` context. ' % actual_exception.__class__) - msg += base_msg - LOG.error(msg) - raise rbac_exceptions.RbacOverrideRoleException(msg) diff --git a/patrole_tempest_plugin/rbac_utils.py b/patrole_tempest_plugin/rbac_utils.py deleted file mode 100644 index ed65a740..00000000 --- a/patrole_tempest_plugin/rbac_utils.py +++ /dev/null @@ -1,501 +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. - -import contextlib -import sys -import time - -from oslo_log import log as logging -from oslo_utils import excutils - -from tempest import config -from tempest.lib import exceptions as lib_exc - -from patrole_tempest_plugin import rbac_exceptions - -CONF = config.CONF -LOG = logging.getLogger(__name__) - - -class _ValidateListContext(object): - """Context class responsible for validation of the list functions. - - This class is used in ``override_role_and_validate_list`` function and - the result of a list function must be assigned to the ``ctx.resources`` - variable. - - Example:: - - with self.override_role_and_validate_list(...) as ctx: - ctx.resources = list_function() - - """ - def __init__(self, admin_resources=None, admin_resource_id=None): - """Constructor for ``ValidateListContext``. - - Either ``admin_resources`` or ``admin_resource_id`` should be used, - not both. - - :param list admin_resources: The list of resources received before - calling the ``override_role_and_validate_list`` function. To - validate will be used the ``_validate_len`` function. - :param UUID admin_resource_id: An ID of a resource created before - calling the ``override_role_and_validate_list`` function. To - validate will be used the ``_validate_resource`` function. - :raises RbacValidateListException: if both ``admin_resources`` and - ``admin_resource_id`` are set or unset. - """ - self.resources = None - if admin_resources is not None and not admin_resource_id: - self._admin_len = len(admin_resources) - if not self._admin_len: - raise rbac_exceptions.RbacValidateListException( - reason="the list of admin resources cannot be empty") - self._validate_func = self._validate_len - elif admin_resource_id and admin_resources is None: - self._admin_resource_id = admin_resource_id - self._validate_func = self._validate_resource - else: - raise rbac_exceptions.RbacValidateListException( - reason="admin_resources and admin_resource_id are mutually " - "exclusive") - - def _validate_len(self): - """Validates that the number of resources is less than admin resources. - """ - if not len(self.resources): - raise rbac_exceptions.RbacEmptyResponseBody() - elif self._admin_len > len(self.resources): - raise rbac_exceptions.RbacPartialResponseBody(body=self.resources) - - def _validate_resource(self): - """Validates that the admin resource is present in the resources. - """ - for resource in self.resources: - if resource['id'] == self._admin_resource_id: - return - raise rbac_exceptions.RbacPartialResponseBody(body=self.resources) - - def _validate(self): - """Calls the proper validation function. - - :raises RbacValidateListException: if the ``ctx.resources`` variable is - not assigned. - """ - if self.resources is None: - raise rbac_exceptions.RbacValidateListException( - reason="ctx.resources is not assigned") - self._validate_func() - - -class RbacUtilsMixin(object): - """Utility mixin responsible for switching ``os_primary`` role. - - Should be used as a mixin class alongside an instance of - :py:class:`tempest.test.BaseTestCase` to perform Patrole class setup for a - base RBAC class. Child classes should not use this mixin. - - Example:: - - class BaseRbacTest(rbac_utils.RbacUtilsMixin, base.BaseV2ComputeTest): - - @classmethod - def setup_clients(cls): - super(BaseRbacTest, cls).setup_clients() - - cls.hosts_client = cls.os_primary.hosts_client - ... - - This class is responsible for overriding the value of the primary Tempest - credential's role (i.e. ``os_primary`` role). By doing so, it is possible - to seamlessly swap between admin credentials, needed for setup and clean - up, and primary credentials, needed to perform the API call which does - policy enforcement. The primary credentials always cycle between roles - defined by ``CONF.identity.admin_role`` and - ``CONF.patrole.rbac_test_roles``. - """ - credentials = ['primary', 'admin'] - - def __init__(self, *args, **kwargs): - super(RbacUtilsMixin, self).__init__(*args, **kwargs) - - # Shows if override_role was called. - self.__override_role_called = False - # Shows if exception raised during override_role. - self.__override_role_caught_exc = False - - _admin_role_id = None - _rbac_role_ids = None - _project_id = None - _user_id = None - _role_map = None - _role_inferences_mapping = None - _orig_roles = [] - - admin_roles_client = None - - @classmethod - def restore_roles(cls): - if cls._orig_roles: - LOG.info("Restoring original roles %s", cls._orig_roles) - roles_already_present = cls._list_and_clear_user_roles_on_project( - cls._orig_roles) - - if not roles_already_present: - cls._create_user_role_on_project(cls._orig_roles) - - @classmethod - def setup_clients(cls): - if CONF.identity_feature_enabled.api_v3: - admin_roles_client = cls.os_admin.roles_v3_client - else: - raise lib_exc.InvalidConfiguration( - "Patrole role overriding only supports v3 identity API.") - - cls.admin_roles_client = admin_roles_client - - cls._project_id = cls.os_primary.credentials.tenant_id - cls._user_id = cls.os_primary.credentials.user_id - cls._role_inferences_mapping = cls._prepare_role_inferences_mapping() - - cls._init_roles() - - # Store the user's original roles and rollback after testing. - roles = cls.admin_roles_client.list_user_roles_on_project( - cls._project_id, cls._user_id)['roles'] - cls._orig_roles = [role['id'] for role in roles] - cls.addClassResourceCleanup(cls.restore_roles) - - # Change default role to admin - cls._override_role(False) - - super(RbacUtilsMixin, cls).setup_clients() - - @classmethod - def _prepare_role_inferences_mapping(cls): - """Preparing roles mapping to support role inferences - - Making query to `list-all-role-inference-rules`_ keystone API - returns all inference rules, which makes it possible to prepare - roles mapping. - - It walks recursively through the raw data:: - - {"role_inferences": [ - { - "implies": [{"id": "3", "name": "reader"}], - "prior_role": {"id": "2", "name": "member"} - }, - { - "implies": [{"id": "2", "name": "member"}], - "prior_role": {"id": "1", "name": "admin"} - } - ] - } - - and converts it to the mapping:: - - { - "2": ["3"], # "member": ["reader"], - "1": ["2", "3"] # "admin": ["member", "reader"] - } - - .. _list-all-role-inference-rules: https://docs.openstack.org/api-ref/identity/v3/#list-all-role-inference-rules - """ # noqa: E501 - def process_roles(role_id, data): - roles = data.get(role_id, set()) - for rid in roles.copy(): - roles.update(process_roles(rid, data)) - - return roles - - def convert_data(data): - res = {} - for rule in data: - prior_role = rule['prior_role']['id'] - implies = {r['id'] for r in rule['implies']} - res[prior_role] = implies - return res - - raw_data = cls.admin_roles_client.list_all_role_inference_rules() - data = convert_data(raw_data['role_inferences']) - res = {} - for role_id in data: - res[role_id] = process_roles(role_id, data) - return res - - def get_all_needed_roles(self, roles): - """Extending given roles with roles from mapping - - Examples:: - ["admin"] >> ["admin", "member", "reader"] - ["member"] >> ["member", "reader"] - ["reader"] >> ["reader"] - ["custom_role"] >> ["custom_role"] - - :param roles: list of roles - :return: extended list of roles - """ - res = set(r for r in roles) - for role in res.copy(): - role_id = self.__class__._role_map.get(role) - implied_roles = self.__class__._role_inferences_mapping.get( - role_id, set()) - role_names = {self.__class__._role_map[rid] - for rid in implied_roles} - res.update(role_names) - LOG.debug('All needed roles: %s; Base roles: %s', res, roles) - return list(res) - - @contextlib.contextmanager - def override_role(self): - """Override the role used by ``os_primary`` Tempest credentials. - - Temporarily change the role used by ``os_primary`` credentials to: - - * ``[patrole] rbac_test_roles`` before test execution - * ``[identity] admin_role`` after test execution - - Automatically switches to admin role after test execution. - - :returns: None - - .. warning:: - - This function can alter user roles for pre-provisioned credentials. - Work is underway to safely clean up after this function. - - Example:: - - @rbac_rule_validation.action(service='test', - rules=['a:test:rule']) - def test_foo(self): - # Allocate test-level resources here. - with self.override_role(): - # The role for `os_primary` has now been overridden. Within - # this block, call the API endpoint that enforces the - # expected policy specified by "rule" in the decorator. - self.foo_service.bar_api_call() - # The role is switched back to admin automatically. Note that - # if the API call above threw an exception, any code below this - # point in the test is not executed. - """ - self._set_override_role_called() - self._override_role(True) - try: - # Execute the test. - yield - finally: - # Check whether an exception was raised. If so, remember that - # for future validation. - exc = sys.exc_info()[0] - if exc is not None: - self._set_override_role_caught_exc() - # This code block is always executed, no matter the result of the - # test. Automatically switch back to the admin role for test clean - # up. - self._override_role(False) - - @classmethod - def _override_role(cls, toggle_rbac_role=False): - """Private helper for overriding ``os_primary`` Tempest credentials. - - :param toggle_rbac_role: Boolean value that controls the role that - overrides default role of ``os_primary`` credentials. - * If True: role is set to ``[patrole] rbac_test_role`` - * If False: role is set to ``[identity] admin_role`` - """ - LOG.debug('Overriding role to: %s.', toggle_rbac_role) - roles_already_present = False - - try: - target_roles = (cls._rbac_role_ids - if toggle_rbac_role else [cls._admin_role_id]) - roles_already_present = cls._list_and_clear_user_roles_on_project( - target_roles) - - # Do not override roles if `target_role` already exists. - if not roles_already_present: - cls._create_user_role_on_project(target_roles) - except Exception as exp: - with excutils.save_and_reraise_exception(): - LOG.exception(exp) - finally: - auth_providers = cls.get_auth_providers() - for provider in auth_providers: - provider.clear_auth() - # Fernet tokens are not subsecond aware so sleep to ensure we are - # passing the second boundary before attempting to authenticate. - # Only sleep if a token revocation occurred as a result of role - # overriding. This will optimize test runtime in the case where - # ``[identity] admin_role`` == ``[patrole] rbac_test_roles``. - if not roles_already_present: - time.sleep(1) - - for provider in auth_providers: - provider.set_auth() - - @classmethod - def _init_roles(cls): - available_roles = cls.admin_roles_client.list_roles()['roles'] - cls._role_map = {r['name']: r['id'] for r in available_roles} - LOG.debug('Available roles: %s', cls._role_map.keys()) - - rbac_role_ids = [] - roles = CONF.patrole.rbac_test_roles - # TODO(vegasq) drop once CONF.patrole.rbac_test_role is removed - if CONF.patrole.rbac_test_role: - if not roles: - roles.append(CONF.patrole.rbac_test_role) - - for role_name in roles: - rbac_role_ids.append(cls._role_map.get(role_name)) - - admin_role_id = cls._role_map.get(CONF.identity.admin_role) - - if not all([admin_role_id, all(rbac_role_ids)]): - missing_roles = [] - msg = ("Could not find `[patrole] rbac_test_roles` or " - "`[identity] admin_role`, both of which are required for " - "RBAC testing.") - if not admin_role_id: - missing_roles.append(CONF.identity.admin_role) - if not all(rbac_role_ids): - missing_roles += [role_name for role_name in roles - if role_name not in cls._role_map] - - msg += " Following roles were not found: %s." % ( - ", ".join(missing_roles)) - msg += " Available roles: %s." % ", ".join(cls._role_map) - raise rbac_exceptions.RbacResourceSetupFailed(msg) - - cls._admin_role_id = admin_role_id - cls._rbac_role_ids = rbac_role_ids - # Adding backward mapping - cls._role_map.update({v: k for k, v in cls._role_map.items()}) - - @classmethod - def _create_user_role_on_project(cls, role_ids): - for role_id in role_ids: - cls.admin_roles_client.create_user_role_on_project( - cls._project_id, cls._user_id, role_id) - - @classmethod - def _list_and_clear_user_roles_on_project(cls, role_ids): - roles = cls.admin_roles_client.list_user_roles_on_project( - cls._project_id, cls._user_id)['roles'] - all_role_ids = [role['id'] for role in roles] - - # NOTE(felipemonteiro): We do not use ``role_id in all_role_ids`` here - # to avoid over-permission errors: if the current list of roles on the - # project includes "admin" and "Member", and we are switching to the - # "Member" role, then we must delete the "admin" role. Thus, we only - # return early if the user's roles on the project are an exact match. - if set(role_ids) == set(all_role_ids): - return True - - for role in roles: - cls.admin_roles_client.delete_role_from_user_on_project( - cls._project_id, cls._user_id, role['id']) - - return False - - @contextlib.contextmanager - def override_role_and_validate_list(self, - admin_resources=None, - admin_resource_id=None): - """Call ``override_role`` and validate RBAC for a list API action. - - List actions usually do soft authorization: partial or empty response - bodies are returned instead of exceptions. This helper validates - that unauthorized roles only return a subset of the available - resources. - Should only be used for validating list API actions. - - :param test_obj: Instance of ``tempest.test.BaseTestCase``. - :param list admin_resources: The list of resources received before - calling the ``override_role_and_validate_list`` function. - :param UUID admin_resource_id: An ID of a resource created before - calling the ``override_role_and_validate_list`` function. - :return: py:class:`_ValidateListContext` object. - - Example:: - - # the resource created by admin - admin_resource_id = ( - self.ntp_client.create_dscp_marking_rule() - ["dscp_marking_rule"]["id']) - with self.override_role_and_validate_list( - admin_resource_id=admin_resource_id) as ctx: - # the list of resources available for member role - ctx.resources = self.ntp_client.list_dscp_marking_rules( - policy_id=self.policy_id)["dscp_marking_rules"] - """ - ctx = _ValidateListContext(admin_resources, admin_resource_id) - with self.override_role(): - yield ctx - ctx._validate() - - @classmethod - def get_auth_providers(cls): - """Returns list of auth_providers used within test. - - Tests may redefine this method to include their own or third party - client auth_providers. - """ - return [cls.os_primary.auth_provider] - - def _set_override_role_called(self): - """Helper for tracking whether ``override_role`` was called.""" - self.__override_role_called = True - - def _set_override_role_caught_exc(self): - """Helper for tracking whether exception was thrown inside - ``override_role``. - """ - self.__override_role_caught_exc = True - - def _validate_override_role_called(self): - """Idempotently validate that ``override_role`` is called and reset - its value to False for sequential tests. - """ - was_called = self.__override_role_called - self.__override_role_called = False - return was_called - - def _validate_override_role_caught_exc(self): - """Idempotently validate that exception was caught inside - ``override_role``, so that, by process of elimination, it can be - determined whether one was thrown outside (which is invalid). - """ - caught_exception = self.__override_role_caught_exc - self.__override_role_caught_exc = False - return caught_exception - - -def is_admin(): - """Verifies whether the current test role equals the admin role. - - :returns: True if ``rbac_test_roles`` contain the admin role. - """ - roles = CONF.patrole.rbac_test_roles - # TODO(vegasq) drop once CONF.patrole.rbac_test_role is removed - if CONF.patrole.rbac_test_role: - roles.append(CONF.patrole.rbac_test_role) - roles = list(set(roles)) - - # TODO(felipemonteiro): Make this more robust via a context is admin - # lookup. - return CONF.identity.admin_role in roles diff --git a/patrole_tempest_plugin/requirements_authority.py b/patrole_tempest_plugin/requirements_authority.py deleted file mode 100644 index 4d6f25be..00000000 --- a/patrole_tempest_plugin/requirements_authority.py +++ /dev/null @@ -1,150 +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. -import copy -import yaml - -from oslo_log import log as logging - -from tempest import config -from tempest.lib import exceptions as lib_exc - -from patrole_tempest_plugin.rbac_authority import RbacAuthority -from patrole_tempest_plugin import rbac_exceptions - -CONF = config.CONF -LOG = logging.getLogger(__name__) - - -class RequirementsParser(object): - """A class that parses a custom requirements file.""" - _inner = None - - class Inner(object): - _rbac_map = None - - def __init__(self, filepath): - with open(filepath) as f: - RequirementsParser.Inner._rbac_map = \ - list(yaml.safe_load_all(f)) - - def __init__(self, filepath): - if RequirementsParser._inner is None: - RequirementsParser._inner = RequirementsParser.Inner(filepath) - - @staticmethod - def parse(component): - """Parses a requirements file with the following format: - - .. code-block:: yaml - - : - : - - - - , - - - : - - - - - : - : - - - - :param str component: Name of the OpenStack service to be validated. - :returns: The dictionary that maps each policy action to the list - of allowed roles, for the given ``component``. - :rtype: dict - """ - try: - for section in RequirementsParser.Inner._rbac_map: - if component in section: - rules = copy.copy(section[component]) - - for rule in rules: - rules[rule] = [ - roles.split(',') for roles in rules[rule]] - - for i, role_pack in enumerate(rules[rule]): - rules[rule][i] = [r.strip() for r in role_pack] - - return rules - except yaml.parser.ParserError: - LOG.error("Error while parsing the requirements YAML file. Did " - "you pass a valid component name from the test case?") - return {} - - -class RequirementsAuthority(RbacAuthority): - """A class that uses a custom requirements file to validate RBAC.""" - - def __init__(self, filepath=None, component=None): - """This class can be used to achieve a requirements-driven approach to - validating an OpenStack cloud's RBAC implementation. Using this - approach, Patrole computes expected test results by performing lookups - against a custom requirements file which precisely defines the cloud's - RBAC requirements. - - :param str filepath: Path where the custom requirements file lives. - Defaults to ``[patrole].custom_requirements_file``. - :param str component: Name of the OpenStack service to be validated. - """ - self.filepath = filepath or CONF.patrole.custom_requirements_file - if component is not None: - self.roles_dict = RequirementsParser(self.filepath).parse( - component) - else: - self.roles_dict = None - - def allowed(self, rule_name, roles): - """Checks if a given rule in a policy is allowed with given role. - - :param string rule_name: Rule to be checked using provided requirements - file specified by ``[patrole].custom_requirements_file``. Must be - a key present in this file, under the appropriate component. - :param List[string] roles: Roles to validate against custom - requirements file. - :returns: True if ``role`` is allowed to perform ``rule_name``, else - False. - :rtype: bool - :raises RbacParsingException: If ``rule_name`` does not exist among the - keyed policy names in the custom requirements file. - """ - if not self.roles_dict: - raise lib_exc.InvalidConfiguration( - "Roles dictionary parsed from requirements YAML file is " - "empty. Ensure the requirements YAML file is correctly " - "formatted.") - try: - requirement_roles = self.roles_dict[rule_name] - except KeyError: - raise rbac_exceptions.RbacParsingException( - "'%s' rule name is not defined in the requirements YAML file: " - "%s" % (rule_name, self.filepath)) - - for role_reqs in requirement_roles: - required_roles = [ - role for role in role_reqs if not role.startswith("!")] - forbidden_roles = [ - role[1:] for role in role_reqs if role.startswith("!")] - - # User must have all required roles - required_passed = all([r in roles for r in required_roles]) - # User must not have any forbidden roles - forbidden_passed = all([r not in forbidden_roles - for r in roles]) - - if required_passed and forbidden_passed: - return True - - return False diff --git a/patrole_tempest_plugin/tests/__init__.py b/patrole_tempest_plugin/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/api/README.rst b/patrole_tempest_plugin/tests/api/README.rst deleted file mode 120000 index e2853ecd..00000000 --- a/patrole_tempest_plugin/tests/api/README.rst +++ /dev/null @@ -1 +0,0 @@ -../../../doc/source/field_guide/rbac.rst \ No newline at end of file diff --git a/patrole_tempest_plugin/tests/api/__init__.py b/patrole_tempest_plugin/tests/api/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/api/compute/__init__.py b/patrole_tempest_plugin/tests/api/compute/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/api/compute/rbac_base.py b/patrole_tempest_plugin/tests/api/compute/rbac_base.py deleted file mode 100644 index b798b166..00000000 --- a/patrole_tempest_plugin/tests/api/compute/rbac_base.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2017 AT&T Corporation -# 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.compute import base as compute_base -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils - -from patrole_tempest_plugin import rbac_utils - - -class BaseV2ComputeRbacTest(rbac_utils.RbacUtilsMixin, - compute_base.BaseV2ComputeTest): - - @classmethod - def setup_clients(cls): - super(BaseV2ComputeRbacTest, cls).setup_clients() - cls.hosts_client = cls.os_primary.hosts_client - cls.tenant_usages_client = cls.os_primary.tenant_usages_client - cls.networks_client = cls.os_primary.networks_client - cls.subnets_client = cls.os_primary.subnets_client - cls.ports_client = cls.os_primary.ports_client - - @classmethod - def create_flavor(cls, **kwargs): - flavor_kwargs = { - "name": data_utils.rand_name(cls.__name__ + '-flavor'), - "ram": data_utils.rand_int_id(1, 10), - "vcpus": data_utils.rand_int_id(1, 10), - "disk": data_utils.rand_int_id(1, 10), - "id": data_utils.rand_uuid(), - } - if kwargs: - flavor_kwargs.update(kwargs) - flavor = cls.flavors_client.create_flavor(**flavor_kwargs)['flavor'] - cls.addClassResourceCleanup( - cls.flavors_client.wait_for_resource_deletion, flavor['id']) - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.flavors_client.delete_flavor, flavor['id']) - return flavor diff --git a/patrole_tempest_plugin/tests/api/compute/test_agents_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_agents_rbac.py deleted file mode 100644 index de9a1730..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_agents_rbac.py +++ /dev/null @@ -1,118 +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.common import utils -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_nova_policies_ussuri: - _AGENTS_LIST = "os_compute_api:os-agents:list" - _AGENTS_CREATE = "os_compute_api:os-agents:create" - _AGENTS_UPDATE = "os_compute_api:os-agents:update" - _AGENTS_DELETE = "os_compute_api:os-agents:delete" -else: - _AGENTS_LIST = "os_compute_api:os-agents" - _AGENTS_CREATE = "os_compute_api:os-agents" - _AGENTS_UPDATE = "os_compute_api:os-agents" - _AGENTS_DELETE = "os_compute_api:os-agents" - - -class AgentsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(AgentsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-agents', 'compute'): - raise cls.skipException( - '%s skipped as os-agents not enabled' % cls.__name__) - if CONF.policy_feature_enabled.removed_nova_policies_wallaby: - raise cls.skipException( - '%s skipped as os-agents APIs/policies are not avaialble ' - 'any more.' % cls.__name__) - - def _param_helper(self, **kwargs): - rand_key = 'architecture' - if rand_key in kwargs: - # NOTE: The rand_name is for avoiding agent conflicts. - # If you try to create an agent with the same hypervisor, - # os and architecture as an existing agent, Nova will return - # an HTTPConflict or HTTPServerError. - kwargs[rand_key] = data_utils.rand_name(kwargs[rand_key]) - return kwargs - - @rbac_rule_validation.action( - service="nova", rules=[_AGENTS_LIST]) - @decorators.idempotent_id('d1bc6d97-07f5-4f45-ac29-1c619a6a7e27') - def test_list_agents_rbac(self): - with self.override_role(): - self.agents_client.list_agents() - - @rbac_rule_validation.action( - service="nova", - rules=[_AGENTS_CREATE]) - @decorators.idempotent_id('77d6cae4-1ced-47f7-af2e-3d6a45958fd6') - def test_create_agent(self): - params = {'hypervisor': 'kvm', 'os': 'win', 'architecture': 'x86', - 'version': '7.0', 'url': 'xxx://xxxx/xxx/xxx', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'} - with self.override_role(): - body = self.agents_client.create_agent(**params)['agent'] - self.addCleanup(self.agents_client.delete_agent, - body['agent_id']) - - @rbac_rule_validation.action( - service="nova", - rules=[_AGENTS_UPDATE]) - @decorators.idempotent_id('b22f2681-9ffb-439b-b240-dae503e41020') - def test_update_agent(self): - params = self._param_helper( - hypervisor='common', os='linux', - architecture='x86_64', version='7.0', - url='xxx://xxxx/xxx/xxx', - md5hash='add6bb58e139be103324d04d82d8f545') - body = self.agents_client.create_agent(**params)['agent'] - self.addCleanup(self.agents_client.delete_agent, - body['agent_id']) - update_params = self._param_helper( - version='8.0', - url='xxx://xxxx/xxx/xxx2', - md5hash='add6bb58e139be103324d04d82d8f547') - - with self.override_role(): - self.agents_client.update_agent(body['agent_id'], **update_params) - - @rbac_rule_validation.action( - service="nova", - rules=[_AGENTS_DELETE]) - @decorators.idempotent_id('c5042af8-0682-43b0-abc4-bf33349e23dd') - def test_delete_agent(self): - params = self._param_helper( - hypervisor='common', os='linux', - architecture='x86_64', version='7.0', - url='xxx://xxxx/xxx/xxx', - md5hash='add6bb58e139be103324d04d82d8f545') - body = self.agents_client.create_agent(**params)['agent'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.agents_client.delete_agent, - body['agent_id']) - with self.override_role(): - self.agents_client.delete_agent(body['agent_id']) diff --git a/patrole_tempest_plugin/tests/api/compute/test_aggregates_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_aggregates_rbac.py deleted file mode 100644 index 687512b2..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_aggregates_rbac.py +++ /dev/null @@ -1,150 +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. - -import testtools - -from tempest.common import utils -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - - -class AggregatesRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(AggregatesRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-aggregates', 'compute'): - msg = "%s skipped as os-aggregates not enabled." % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(AggregatesRbacTest, cls).setup_clients() - cls.hosts_client = cls.os_primary.hosts_client - - @classmethod - def resource_setup(cls): - super(AggregatesRbacTest, cls).resource_setup() - cls.host = None - hypers = cls.hypervisor_client.list_hypervisors( - detail=True)['hypervisors'] - - if CONF.compute.hypervisor_type: - hypers = [hyper for hyper in hypers - if (hyper['hypervisor_type'] == - CONF.compute.hypervisor_type)] - - hosts_available = [hyper['service']['host'] for hyper in hypers - if (hyper['state'] == 'up' and - hyper['status'] == 'enabled')] - if hosts_available: - cls.host = hosts_available[0] - else: - msg = "no available compute node found" - if CONF.compute.hypervisor_type: - msg += " for hypervisor_type %s" % CONF.compute.hypervisor_type - raise testtools.TestCase.failureException(msg) - - def _create_aggregate(self): - agg_name = data_utils.rand_name(self.__class__.__name__ + '-aggregate') - aggregate = self.aggregates_client.create_aggregate(name=agg_name) - aggregate_id = aggregate['aggregate']['id'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.aggregates_client.delete_aggregate, - aggregate_id) - return aggregate_id - - def _add_host_to_aggregate(self, aggregate_id): - self.aggregates_client.add_host(aggregate_id, host=self.host) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.aggregates_client.remove_host, - aggregate_id, - host=self.host) - - @rbac_rule_validation.action( - service="nova", rules=["os_compute_api:os-aggregates:create"]) - @decorators.idempotent_id('ba754393-896e-434a-9704-452ff4a84f3f') - def test_create_aggregate_rbac(self): - with self.override_role(): - self._create_aggregate() - - @rbac_rule_validation.action( - service="nova", rules=["os_compute_api:os-aggregates:show"]) - @decorators.idempotent_id('8fb0b749-b120-4727-b3fb-bcfa3fa6f55b') - def test_show_aggregate_rbac(self): - aggregate_id = self._create_aggregate() - with self.override_role(): - self.aggregates_client.show_aggregate(aggregate_id) - - @rbac_rule_validation.action( - service="nova", rules=["os_compute_api:os-aggregates:index"]) - @decorators.idempotent_id('146284da-5dd6-4c97-b598-42b480f014c6') - def test_list_aggregate_rbac(self): - with self.override_role(): - self.aggregates_client.list_aggregates() - - @rbac_rule_validation.action( - service="nova", rules=["os_compute_api:os-aggregates:update"]) - @decorators.idempotent_id('c94e0d69-99b6-477e-b301-2cd0e9d0ad81') - def test_update_aggregate_rbac(self): - aggregate_id = self._create_aggregate() - new_name = data_utils.rand_name(self.__class__.__name__ + '-aggregate') - with self.override_role(): - self.aggregates_client.update_aggregate(aggregate_id, - name=new_name) - - @rbac_rule_validation.action( - service="nova", rules=["os_compute_api:os-aggregates:delete"]) - @decorators.idempotent_id('5a50c5a6-0f12-4405-a1ce-2288ae895ea6') - def test_delete_aggregate_rbac(self): - aggregate_id = self._create_aggregate() - with self.override_role(): - self.aggregates_client.delete_aggregate(aggregate_id) - - @rbac_rule_validation.action( - service="nova", rules=["os_compute_api:os-aggregates:add_host"]) - @decorators.idempotent_id('97e6e9df-5291-4faa-8147-755b2d1f1ce2') - def test_add_host_to_aggregate_rbac(self): - aggregate_id = self._create_aggregate() - with self.override_role(): - self._add_host_to_aggregate(aggregate_id) - - @rbac_rule_validation.action( - service="nova", rules=["os_compute_api:os-aggregates:remove_host"]) - @decorators.idempotent_id('5b035a25-75d2-4d72-b4d6-0f0337335628') - def test_remove_host_from_aggregate_rbac(self): - aggregate_id = self._create_aggregate() - self._add_host_to_aggregate(aggregate_id) - with self.override_role(): - self.aggregates_client.remove_host(aggregate_id, host=self.host) - - @rbac_rule_validation.action( - service="nova", rules=["os_compute_api:os-aggregates:set_metadata"]) - @decorators.idempotent_id('ed6f3849-065c-4ae9-a81e-6ad7ed0d3d9d') - def test_set_metadata_on_aggregate_rbac(self): - aggregate_id = self._create_aggregate() - rand_key = data_utils.rand_name(self.__class__.__name__ + '-key') - rand_val = data_utils.rand_name(self.__class__.__name__ + '-val') - with self.override_role(): - self.aggregates_client.set_metadata( - aggregate_id, - metadata={rand_key: rand_val}) diff --git a/patrole_tempest_plugin/tests/api/compute/test_availability_zone_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_availability_zone_rbac.py deleted file mode 100644 index c7fe6426..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_availability_zone_rbac.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2017 AT&T Corporation. -# 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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class NovaAvailabilityZoneRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(NovaAvailabilityZoneRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-availability-zone', 'compute'): - msg = ("%s skipped as os-availability-zone not " - "enabled." % cls.__name__) - raise cls.skipException(msg) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-availability-zone:list"]) - @decorators.idempotent_id('cd34e7ea-d26e-4fa3-a8d0-f8883726ce3d') - def test_get_availability_zone_list_rbac(self): - with self.override_role(): - self.availability_zone_client.list_availability_zones() - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-availability-zone:detail"]) - @decorators.idempotent_id('2f61c191-6ece-4f21-b487-39d749e3d38e') - def test_get_availability_zone_list_detail_rbac(self): - with self.override_role(): - self.availability_zone_client.list_availability_zones(detail=True) diff --git a/patrole_tempest_plugin/tests/api/compute/test_flavor_access_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_flavor_access_rbac.py deleted file mode 100644 index 9f976bdc..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_flavor_access_rbac.py +++ /dev/null @@ -1,116 +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. - -import testtools - -from tempest import config -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -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 - -CONF = config.CONF - - -class FlavorAccessRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def resource_setup(cls): - super(FlavorAccessRbacTest, cls).resource_setup() - cls.flavor_id = cls.create_flavor(is_public=False)['id'] - cls.public_flavor_id = CONF.compute.flavor_ref - cls.tenant_id = cls.os_primary.credentials.tenant_id - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('a2bd3740-765d-4c95-ac98-9e027378c75e') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-access"]) - def test_show_flavor_contains_is_public_key(self): - public_flavor_id = CONF.compute.flavor_ref - - with self.override_role(): - body = self.flavors_client.show_flavor(public_flavor_id)[ - 'flavor'] - - expected_attr = 'os-flavor-access:is_public' - if expected_attr not in body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('dd388146-9750-4124-82ba-62deff1052bb') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-access"]) - def test_list_flavors_details_contains_is_public_key(self): - expected_attr = 'os-flavor-access:is_public' - - with self.override_role(): - flavors = self.flavors_client.list_flavors(detail=True)['flavors'] - # There should already be a public flavor available, namely - # `CONF.compute.flavor_ref`. - public_flavors = [f for f in flavors if expected_attr in f] - - # If the `expected_attr` was not found in any flavor, then policy - # enforcement failed. - if not public_flavors: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @decorators.idempotent_id('39cb5c8f-9990-436f-9282-fc76a41d9bac') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-access:add_tenant_access"]) - def test_add_flavor_access(self): - with self.override_role(): - self.flavors_client.add_flavor_access( - flavor_id=self.flavor_id, tenant_id=self.tenant_id) - self.addCleanup(self.flavors_client.remove_flavor_access, - flavor_id=self.flavor_id, tenant_id=self.tenant_id) - - @decorators.idempotent_id('61b8621f-52e4-473a-8d07-e228af8853d1') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-access:remove_tenant_access"]) - def test_remove_flavor_access(self): - self.flavors_client.add_flavor_access( - flavor_id=self.flavor_id, tenant_id=self.tenant_id) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.flavors_client.remove_flavor_access, - flavor_id=self.flavor_id, tenant_id=self.tenant_id) - - with self.override_role(): - self.flavors_client.remove_flavor_access( - flavor_id=self.flavor_id, tenant_id=self.tenant_id) - - @decorators.idempotent_id('e1cf59fb-7f32-40a1-96b9-248ab23dd581') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-access"]) - def test_list_flavor_access(self): - # Add flavor access for os_primary so that it can access the flavor or - # else a NotFound is raised. - self.flavors_client.add_flavor_access( - flavor_id=self.flavor_id, tenant_id=self.tenant_id) - self.addCleanup(self.flavors_client.remove_flavor_access, - flavor_id=self.flavor_id, tenant_id=self.tenant_id) - - with self.override_role(): - self.flavors_client.list_flavor_access(self.flavor_id) diff --git a/patrole_tempest_plugin/tests/api/compute/test_flavor_extra_specs_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_flavor_extra_specs_rbac.py deleted file mode 100644 index c2f9f402..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_flavor_extra_specs_rbac.py +++ /dev/null @@ -1,94 +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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class FlavorExtraSpecsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(FlavorExtraSpecsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-flavor-extra-specs', 'compute'): - msg = "os-flavor-extra-specs extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(FlavorExtraSpecsRbacTest, cls).resource_setup() - cls.flavor = cls.create_flavor() - - def _set_flavor_extra_spec(self): - rand_key = data_utils.rand_name(self.__class__.__name__ + '-key') - rand_val = data_utils.rand_name(self.__class__.__name__ + '-val') - specs = {rand_key: rand_val} - self.flavors_client.set_flavor_extra_spec(self.flavor['id'], - **specs)['extra_specs'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.flavors_client.unset_flavor_extra_spec, - self.flavor['id'], rand_key) - return rand_key - - @decorators.idempotent_id('daee891d-dfe9-4501-a39c-29f2371bec3c') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-extra-specs:show"]) - def test_show_flavor_extra_spec(self): - key = self._set_flavor_extra_spec() - with self.override_role(): - self.flavors_client.show_flavor_extra_spec(self.flavor['id'], key) - - @decorators.idempotent_id('fcffeca2-ed04-4e85-bf93-02fb5643f22b') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-extra-specs:create"]) - def test_set_flavor_extra_spec(self): - with self.override_role(): - self._set_flavor_extra_spec() - - @decorators.idempotent_id('42b85279-6bfa-4f58-b7a2-258c284f03c5') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-extra-specs:update"]) - def test_update_flavor_extra_spec(self): - key = self._set_flavor_extra_spec() - update_val = data_utils.rand_name(self.__class__.__name__ + '-val') - with self.override_role(): - self.flavors_client.update_flavor_extra_spec( - self.flavor['id'], key, **{key: update_val}) - - @decorators.idempotent_id('4b0e5471-e010-4c09-8965-80898e6760a3') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-extra-specs:delete"]) - def test_unset_flavor_extra_spec(self): - key = self._set_flavor_extra_spec() - with self.override_role(): - self.flavors_client.unset_flavor_extra_spec(self.flavor['id'], key) - - @decorators.idempotent_id('02c3831a-3ce9-476e-a722-d805ac2da621') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-extra-specs:index"]) - def test_list_flavor_extra_specs(self): - self._set_flavor_extra_spec() - with self.override_role(): - self.flavors_client.list_flavor_extra_specs(self.flavor['id']) diff --git a/patrole_tempest_plugin/tests/api/compute/test_flavor_manage_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_flavor_manage_rbac.py deleted file mode 100644 index 2aa69321..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_flavor_manage_rbac.py +++ /dev/null @@ -1,49 +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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class FlavorManageRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(FlavorManageRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'): - msg = "OS-FLV-EXT-DATA extension not enabled." - raise cls.skipException(msg) - - @decorators.idempotent_id('a4e7faec-7a4b-4809-9856-90d5b747ca35') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-manage:create"]) - def test_create_flavor_manage(self): - with self.override_role(): - self.create_flavor() - - @decorators.idempotent_id('782e988e-061b-4c40-896f-a77c70c2b057') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-manage:delete"]) - def test_delete_flavor_manage(self): - flavor_id = self.create_flavor()['id'] - - with self.override_role(): - self.flavors_client.delete_flavor(flavor_id) - self.flavors_client.wait_for_resource_deletion(flavor_id) diff --git a/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py deleted file mode 100644 index 50ab048d..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py +++ /dev/null @@ -1,63 +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. - -import testtools - -from tempest.common import utils -from tempest import config -from tempest.lib import decorators - -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 - -CONF = config.CONF - - -class FlavorRxtxRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(FlavorRxtxRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-flavor-rxtx', 'compute'): - msg = "os-flavor-rxtx extension not enabled." - raise cls.skipException(msg) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('5e1fd9f0-9a08-485a-ad9c-0fc66e4d64b7') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-rxtx"]) - def test_list_flavors_details_rxtx(self): - with self.override_role(): - result = self.flavors_client.list_flavors(detail=True)['flavors'] - if 'rxtx_factor' not in result[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='rxtx_factor') - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('70c55a07-c843-4627-a29d-ba78673c1e63') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-flavor-rxtx"]) - def test_get_flavor_rxtx(self): - with self.override_role(): - result = self.flavors_client.show_flavor( - CONF.compute.flavor_ref)['flavor'] - if 'rxtx_factor' not in result: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='rxtx_factor') diff --git a/patrole_tempest_plugin/tests/api/compute/test_floating_ip_pools_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_floating_ip_pools_rbac.py deleted file mode 100644 index 3736f8db..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_floating_ip_pools_rbac.py +++ /dev/null @@ -1,54 +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.common import utils -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - - -class FloatingIpPoolsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - # Tests will fail with a 404 starting from microversion 2.36: - # See the following link for details: - # https://docs.openstack.org/api-ref/compute/#floating-ip-pools-os-floating-ip-pools-deprecated - max_microversion = '2.35' - - @classmethod - def setup_clients(cls): - super(FloatingIpPoolsRbacTest, cls).setup_clients() - cls.fip_pools_client = cls.os_primary.floating_ip_pools_client - - @classmethod - def skip_checks(cls): - super(FloatingIpPoolsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-floating-ip-pools', 'compute'): - msg = "%s skipped as os-floating-ip-pools extension not enabled." \ - % cls.__name__ - raise cls.skipException(msg) - if not CONF.network_feature_enabled.floating_ips: - raise cls.skipException("Floating ips are not available") - - @decorators.idempotent_id('c1a17153-b25d-4444-a721-5897d7737482') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-floating-ip-pools"]) - def test_list_floating_ip_pools(self): - with self.override_role(): - self.fip_pools_client.list_floating_ip_pools() diff --git a/patrole_tempest_plugin/tests/api/compute/test_floating_ips_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_floating_ips_rbac.py deleted file mode 100644 index ed3691ef..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_floating_ips_rbac.py +++ /dev/null @@ -1,101 +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.common import utils -from tempest import config -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - -# RBAC category or action was changed in Victoria release per -# https://docs.openstack.org/api-ref/compute/#floating-ips-os-floating-ips-deprecated -# and -# https://github.com/openstack/nova/blob/master/nova/policies/floating_ips.py#L21 -if CONF.policy_feature_enabled.changed_nova_policies_victoria: - _FIP_GET = "os_compute_api:os-floating-ips:list" - _FIP_SHOW = "os_compute_api:os-floating-ips:show" - _FIP_CREATE = "os_compute_api:os-floating-ips:create" - _FIP_DELETE = "os_compute_api:os-floating-ips:delete" -else: - _FIP_GET = "os_compute_api:os-floating-ips" - _FIP_SHOW = "os_compute_api:os-floating-ips" - _FIP_CREATE = "os_compute_api:os-floating-ips" - _FIP_DELETE = "os_compute_api:os-floating-ips" - - -class FloatingIpsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - # Tests will fail with a 404 starting from microversion 2.36: - # See the following link for details: - # https://docs.openstack.org/api-ref/compute/#floating-ips-os-floating-ips-deprecated - max_microversion = '2.35' - - @classmethod - def skip_checks(cls): - super(FloatingIpsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-floating-ips', 'compute'): - msg = "%s skipped as os-floating-ips extension not enabled." \ - % cls.__name__ - raise cls.skipException(msg) - if not CONF.network_feature_enabled.floating_ips: - raise cls.skipException("Floating ips are not available") - - @decorators.idempotent_id('ac1b3053-f755-4cda-85a0-30e88b88d7ba') - @rbac_rule_validation.action( - service="nova", - rules=[_FIP_GET]) - def test_list_floating_ips(self): - with self.override_role(): - self.floating_ips_client.list_floating_ips() - - @decorators.idempotent_id('bebe52b3-5269-4e72-80c8-5a4a39c3bfa6') - @rbac_rule_validation.action( - service="nova", - rules=[_FIP_SHOW]) - def test_show_floating_ip(self): - body = self.floating_ips_client.create_floating_ip( - pool=CONF.network.floating_network_name)['floating_ip'] - self.addCleanup( - self.floating_ips_client.delete_floating_ip, body['id']) - with self.override_role(): - self.floating_ips_client.show_floating_ip(body['id']) - - @decorators.idempotent_id('2bfb8745-c329-4ee9-95f6-c165a1989dbf') - @rbac_rule_validation.action( - service="nova", - rules=[_FIP_CREATE]) - def test_create_floating_ips(self): - with self.override_role(): - body = self.floating_ips_client.create_floating_ip( - pool=CONF.network.floating_network_name)['floating_ip'] - self.addCleanup( - self.floating_ips_client.delete_floating_ip, body['id']) - - @decorators.idempotent_id('d3028373-5027-4e7a-b761-01c515403ecb') - @rbac_rule_validation.action( - service="nova", - rules=[_FIP_DELETE]) - def test_delete_floating_ip(self): - body = self.floating_ips_client.create_floating_ip( - pool=CONF.network.floating_network_name)['floating_ip'] - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.floating_ips_client.delete_floating_ip, body['id']) - with self.override_role(): - self.floating_ips_client.delete_floating_ip(body['id']) diff --git a/patrole_tempest_plugin/tests/api/compute/test_hosts_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_hosts_rbac.py deleted file mode 100644 index 5a598e0c..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_hosts_rbac.py +++ /dev/null @@ -1,64 +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.common import utils -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_nova_policies_victoria: - _HOSTS_LIST = "os_compute_api:os-hosts:list" - _HOSTS_SHOW = "os_compute_api:os-hosts:show" -else: - _HOSTS_LIST = "os_compute_api:os-hosts" - _HOSTS_SHOW = "os_compute_api:os-hosts" - - -class HostsRbacTest(rbac_base.BaseV2ComputeRbacTest): - # These tests will fail with a 404 starting from microversion 2.43: - # See the following links for details: - # https://docs.openstack.org/api-ref/compute/#hosts-os-hosts-deprecated - max_microversion = '2.42' - - @classmethod - def skip_checks(cls): - super(HostsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-hosts', 'compute'): - msg = "%s skipped as os-hosts not enabled." % cls.__name__ - raise cls.skipException(msg) - - @decorators.idempotent_id('035b7935-2fae-4218-8d37-27fa83097494') - @rbac_rule_validation.action( - service="nova", - rules=[_HOSTS_LIST]) - def test_list_hosts(self): - with self.override_role(): - self.hosts_client.list_hosts() - - @decorators.idempotent_id('bc10d8b4-d2c3-4d4e-9d2b-31d1bd3e1b51') - @rbac_rule_validation.action( - service="nova", - rules=[_HOSTS_SHOW]) - def test_show_host_details(self): - hosts = self.hosts_client.list_hosts()['hosts'] - hosts = [host for host in hosts if host['service'] == 'compute'] - self.assertNotEmpty(hosts) - - with self.override_role(): - self.hosts_client.show_host(hosts[0]['host_name']) diff --git a/patrole_tempest_plugin/tests/api/compute/test_hypervisor_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_hypervisor_rbac.py deleted file mode 100644 index 8ad253a9..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_hypervisor_rbac.py +++ /dev/null @@ -1,138 +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.common import utils -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_nova_policies_ussuri: - _HYPERVISOR_LIST = "os_compute_api:os-hypervisors:list" - _HYPERVISOR_SHOW = "os_compute_api:os-hypervisors:show" - _HYPERVISOR_LIST_DETAIL = "os_compute_api:os-hypervisors:list-detail" - _HYPERVISOR_STATISTICS = "os_compute_api:os-hypervisors:statistics" - _HYPERVISOR_UPTIME = "os_compute_api:os-hypervisors:uptime" - _HYPERVISOR_SEARCH = "os_compute_api:os-hypervisors:search" - _HYPERVISOR_SERVER = "os_compute_api:os-hypervisors:servers" -else: - _HYPERVISOR_LIST = "os_compute_api:os-hypervisors" - _HYPERVISOR_SHOW = "os_compute_api:os-hypervisors" - _HYPERVISOR_LIST_DETAIL = "os_compute_api:os-hypervisors" - _HYPERVISOR_STATISTICS = "os_compute_api:os-hypervisors" - _HYPERVISOR_UPTIME = "os_compute_api:os-hypervisors" - _HYPERVISOR_SEARCH = "os_compute_api:os-hypervisors" - _HYPERVISOR_SERVER = "os_compute_api:os-hypervisors" - - -class HypervisorRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(HypervisorRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-hypervisors', 'compute'): - msg = "%s skipped as os-hypervisors extension not enabled." \ - % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(HypervisorRbacTest, cls).resource_setup() - cls.hypervisor =\ - cls.hypervisor_client.list_hypervisors()['hypervisors'][0] - - @decorators.idempotent_id('17bbeb9a-e73e-445f-a771-c794448ef562') - @rbac_rule_validation.action( - service="nova", - rules=[_HYPERVISOR_LIST]) - def test_list_hypervisors(self): - with self.override_role(): - self.hypervisor_client.list_hypervisors() - - @decorators.idempotent_id('36b95c7d-1085-487a-a674-b7c1ca35f520') - @rbac_rule_validation.action( - service="nova", - rules=[_HYPERVISOR_LIST_DETAIL]) - def test_list_hypervisors_with_details(self): - with self.override_role(): - self.hypervisor_client.list_hypervisors(detail=True) - - @decorators.idempotent_id('8a7f6f9e-34a6-4480-8875-bba566c3a581') - @rbac_rule_validation.action( - service="nova", - rules=[_HYPERVISOR_SHOW]) - def test_show_hypervisor(self): - with self.override_role(): - self.hypervisor_client.show_hypervisor(self.hypervisor['id']) - - @decorators.idempotent_id('ca0e465c-6365-4a7f-ae58-6f8ddbca06c2') - @rbac_rule_validation.action( - service="nova", - rules=[_HYPERVISOR_STATISTICS]) - def test_show_hypervisor_statistics(self): - with self.override_role(): - self.hypervisor_client.show_hypervisor_statistics() - - @decorators.idempotent_id('109b37c5-91ba-4da5-b2a2-d7618d84406d') - @rbac_rule_validation.action( - service="nova", - rules=[_HYPERVISOR_UPTIME]) - def test_show_hypervisor_uptime(self): - with self.override_role(): - self.hypervisor_client.show_hypervisor_uptime( - self.hypervisor['id']) - - -class HypervisorMaxv252RbacTest(rbac_base.BaseV2ComputeRbacTest): - # These tests will fail with a 404 starting from microversion 2.53: - # See the following links for details: - # https://docs.openstack.org/api-ref/compute/#list-hypervisor-servers - # https://docs.openstack.org/api-ref/compute/#search-hypervisor - max_microversion = '2.52' - - @classmethod - def skip_checks(cls): - super(HypervisorMaxv252RbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-hypervisors', 'compute'): - msg = "%s skipped as os-hypervisors extension not enabled." \ - % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(HypervisorMaxv252RbacTest, cls).resource_setup() - cls.hypervisor =\ - cls.hypervisor_client.list_hypervisors()['hypervisors'][0] - - @decorators.idempotent_id('b86f03cf-2e79-4d88-9eea-62f761591413') - @rbac_rule_validation.action( - service="nova", - rules=[_HYPERVISOR_SERVER]) - def test_list_servers_on_hypervisor(self): - with self.override_role(): - self.hypervisor_client.list_servers_on_hypervisor( - self.hypervisor['hypervisor_hostname']) - - @decorators.idempotent_id('3dbc71c1-8f04-4674-a67c-dcb2fd99b1b4') - @rbac_rule_validation.action( - service="nova", - rules=[_HYPERVISOR_SEARCH]) - def test_search_hypervisor(self): - with self.override_role(): - self.hypervisor_client.search_hypervisor( - self.hypervisor['hypervisor_hostname']) diff --git a/patrole_tempest_plugin/tests/api/compute/test_images_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_images_rbac.py deleted file mode 100644 index 66590e9d..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_images_rbac.py +++ /dev/null @@ -1,314 +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. - -import testtools - -from tempest.common import image as common_image -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators -from tempest.lib import exceptions as lib_exc - -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 - -CONF = config.CONF - - -class ImagesRbacTest(rbac_base.BaseV2ComputeRbacTest): - """RBAC tests for the Nova images API. - - These APIs are proxy calls to the Image service. Consequently, no Nova - policy actions are enforced; instead, only Glance policy actions are - enforced. As such, these tests check that only Glance policy actions are - executed. - """ - - # These tests will fail with a 404 starting from microversion 2.36. - # See the following link for details: - # https://docs.openstack.org/api-ref/compute/#images-deprecated - max_microversion = '2.35' - - @classmethod - def skip_checks(cls): - super(ImagesRbacTest, cls).skip_checks() - if not CONF.service_available.glance: - skip_msg = ("%s skipped as glance is not available" % cls.__name__) - raise cls.skipException(skip_msg) - - @classmethod - def setup_clients(cls): - super(ImagesRbacTest, cls).setup_clients() - if CONF.image_feature_enabled.api_v2: - cls.glance_image_client = cls.os_primary.image_client_v2 - elif CONF.image_feature_enabled.api_v1: - cls.glance_image_client = cls.os_primary.image_client - else: - raise lib_exc.InvalidConfiguration( - 'Either api_v1 or api_v2 must be True in ' - '[image-feature-enabled].') - - @classmethod - def resource_setup(cls): - super(ImagesRbacTest, cls).resource_setup() - params = {'name': data_utils.rand_name(cls.__name__ + '-image')} - if CONF.image_feature_enabled.api_v1: - params = {'headers': common_image.image_meta_to_headers(**params)} - - cls.image = cls.glance_image_client.create_image(**params) - cls.addClassResourceCleanup( - cls.glance_image_client.wait_for_resource_deletion, - cls.image['id']) - cls.addClassResourceCleanup( - cls.glance_image_client.delete_image, cls.image['id']) - - @decorators.idempotent_id('b861f302-b72b-4055-81db-c62ff30b136d') - @rbac_rule_validation.action( - service="glance", - rules=["get_images"]) - def test_list_images(self): - with self.override_role(): - self.compute_images_client.list_images() - - @decorators.idempotent_id('4365ae0f-15ee-4b54-a527-1679faaed140') - @rbac_rule_validation.action( - service="glance", - rules=["get_images"]) - def test_list_images_with_details(self): - with self.override_role(): - self.compute_images_client.list_images(detail=True) - - @decorators.idempotent_id('886dfcae-51bf-4610-9e52-82d7189524c2') - @rbac_rule_validation.action( - service="glance", - rules=["get_image"]) - def test_show_image_details(self): - with self.override_role(): - self.compute_images_client.show_image(self.image['id']) - - @decorators.idempotent_id('5888c7aa-0803-46d4-a3fb-5d4729465cd5') - @rbac_rule_validation.action( - service="glance", - rules=["delete_image"]) - def test_delete_image(self): - image = self.glance_image_client.create_image( - name=data_utils.rand_name(self.__class__.__name__ + '-image')) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.glance_image_client.delete_image, image['id']) - - with self.override_role(): - self.compute_images_client.delete_image(image['id']) - - -class ImagesMetadataRbacTest(rbac_base.BaseV2ComputeRbacTest): - """RBAC tests for the Nova metadata images API. - - These APIs are proxy calls to the Image service. Consequently, no Nova - policy actions are enforced; instead, only Glance policy actions are - enforced. As such, these tests check that only Glance policy actions are - executed. - """ - - # These tests will fail with a 404 starting from microversion 2.39. - # See the following link for details: - # https://docs.openstack.org/api-ref/compute/#images-deprecated - max_microversion = '2.38' - - @classmethod - def skip_checks(cls): - super(ImagesMetadataRbacTest, cls).skip_checks() - if not CONF.service_available.glance: - skip_msg = ("%s skipped as glance is not available" % cls.__name__) - raise cls.skipException(skip_msg) - - @classmethod - def setup_clients(cls): - super(ImagesMetadataRbacTest, cls).setup_clients() - if CONF.image_feature_enabled.api_v2: - cls.glance_image_client = cls.os_primary.image_client_v2 - elif CONF.image_feature_enabled.api_v1: - cls.glance_image_client = cls.os_primary.image_client - else: - raise lib_exc.InvalidConfiguration( - 'Either api_v1 or api_v2 must be True in ' - '[image-feature-enabled].') - - @classmethod - def resource_setup(cls): - super(ImagesMetadataRbacTest, cls).resource_setup() - params = {'name': data_utils.rand_name(cls.__name__ + '-image')} - if CONF.image_feature_enabled.api_v1: - params = {'headers': common_image.image_meta_to_headers(**params)} - - cls.image = cls.glance_image_client.create_image(**params) - cls.addClassResourceCleanup( - cls.glance_image_client.wait_for_resource_deletion, - cls.image['id']) - cls.addClassResourceCleanup( - cls.glance_image_client.delete_image, cls.image['id']) - - @decorators.idempotent_id('dbe09d4c-e615-48cb-b908-a06a0f410a8e') - @rbac_rule_validation.action( - service="glance", - rules=["get_image"]) - def test_show_image_metadata_item(self): - self.compute_images_client.set_image_metadata(self.image['id'], - meta={'foo': 'bar'}) - self.addCleanup(self.compute_images_client.delete_image_metadata_item, - self.image['id'], key='foo') - - with self.override_role(): - self.compute_images_client.show_image_metadata_item( - self.image['id'], key='foo') - - @decorators.idempotent_id('59f66079-d564-47e8-81b0-03c2e84d339e') - @rbac_rule_validation.action( - service="glance", - rules=["get_image"]) - def test_list_image_metadata(self): - with self.override_role(): - self.compute_images_client.list_image_metadata(self.image['id']) - - @decorators.idempotent_id('575604aa-909f-4b1b-a5a5-cfae1f63044b') - @rbac_rule_validation.action( - service="glance", - rules=["modify_image"]) - def test_create_image_metadata(self): - with self.override_role(): - # NOTE(felipemonteiro): Although the name of the client function - # appears wrong, it's actually correct: update_image_metadata does - # an http post. - self.compute_images_client.update_image_metadata( - self.image['id'], meta={'foo': 'bar'}) - self.addCleanup(self.compute_images_client.delete_image_metadata_item, - self.image['id'], key='foo') - - @decorators.idempotent_id('fb8c4eb6-00e5-454c-b8bc-0e801ec369f1') - @rbac_rule_validation.action( - service="glance", - rules=["modify_image"]) - def test_update_image_metadata(self): - with self.override_role(): - self.compute_images_client.set_image_metadata(self.image['id'], - meta={'foo': 'bar'}) - self.addCleanup(self.compute_images_client.delete_image_metadata_item, - self.image['id'], key='foo') - - @decorators.idempotent_id('9c7c2036-af9b-49a8-8ba1-09b027ee5def') - @rbac_rule_validation.action( - service="glance", - rules=["modify_image"]) - def test_update_image_metadata_item(self): - with self.override_role(): - self.compute_images_client.set_image_metadata_item( - self.image['id'], meta={'foo': 'bar'}, key='foo') - self.addCleanup(self.compute_images_client.delete_image_metadata_item, - self.image['id'], key='foo') - - @decorators.idempotent_id('5f0dc4e6-0761-4613-9bde-0a6acdc78f46') - @rbac_rule_validation.action( - service="glance", - rules=["modify_image"]) - def test_delete_image_metadata_item(self): - self.compute_images_client.set_image_metadata(self.image['id'], - meta={'foo': 'bar'}) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.compute_images_client.delete_image_metadata_item, - self.image['id'], key='foo') - - with self.override_role(): - self.compute_images_client.delete_image_metadata_item( - self.image['id'], key='foo') - - -class ImageSizeRbacTest(rbac_base.BaseV2ComputeRbacTest): - """Tests the ``image_size`` compute policies. - - NOTE(felipemonteiro): If Patrole is enhanced to test multiple policies - simultaneously, these policy actions can be combined with the related - tests from ``ImagesRbacTest`` above. - """ - - # These tests will fail with a 404 starting from microversion 2.36. - # See the following link for details: - # https://docs.openstack.org/api-ref/compute/#images-deprecated - max_microversion = '2.35' - - @classmethod - def skip_checks(cls): - super(ImageSizeRbacTest, cls).skip_checks() - if not CONF.service_available.glance: - skip_msg = ("%s skipped as glance is not available" % cls.__name__) - raise cls.skipException(skip_msg) - - @classmethod - def setup_clients(cls): - super(ImageSizeRbacTest, cls).setup_clients() - if CONF.image_feature_enabled.api_v2: - cls.glance_image_client = cls.os_primary.image_client_v2 - elif CONF.image_feature_enabled.api_v1: - cls.glance_image_client = cls.os_primary.image_client - else: - raise lib_exc.InvalidConfiguration( - 'Either api_v1 or api_v2 must be True in ' - '[image-feature-enabled].') - - @classmethod - def resource_setup(cls): - super(ImageSizeRbacTest, cls).resource_setup() - params = {'name': data_utils.rand_name(cls.__name__ + '-image')} - if CONF.image_feature_enabled.api_v1: - params = {'headers': common_image.image_meta_to_headers(**params)} - - cls.image = cls.glance_image_client.create_image(**params) - cls.addClassResourceCleanup( - cls.glance_image_client.wait_for_resource_deletion, - cls.image['id']) - cls.addClassResourceCleanup( - cls.glance_image_client.delete_image, cls.image['id']) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('fe34d2a6-5743-45bf-8f92-a1d703d7c7ab') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:image-size"]) - def test_show_image_includes_image_size(self): - with self.override_role(): - body = self.compute_images_client.show_image(self.image['id'])[ - 'image'] - - expected_attr = 'OS-EXT-IMG-SIZE:size' - if expected_attr not in body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('08342c7d-297d-42ee-b398-90fce2443792') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:image-size"]) - def test_list_images_with_details_includes_image_size(self): - with self.override_role(): - body = self.compute_images_client.list_images(detail=True)[ - 'images'] - - expected_attr = 'OS-EXT-IMG-SIZE:size' - if expected_attr not in body[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) diff --git a/patrole_tempest_plugin/tests/api/compute/test_instance_usages_audit_log_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_instance_usages_audit_log_rbac.py deleted file mode 100644 index 72c4b022..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_instance_usages_audit_log_rbac.py +++ /dev/null @@ -1,64 +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. - -import datetime - -from six.moves.urllib import parse as urllib - -from tempest.common import utils -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_nova_policies_ussuri: - _INSTANCE_USAGE_LIST = "os_compute_api:os-instance-usage-audit-log:list" - _INSTANCE_USAGE_SHOW = "os_compute_api:os-instance-usage-audit-log:show" -else: - _INSTANCE_USAGE_LIST = "os_compute_api:os-instance-usage-audit-log" - _INSTANCE_USAGE_SHOW = "os_compute_api:os-instance-usage-audit-log" - - -class InstanceUsagesAuditLogRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(InstanceUsagesAuditLogRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-instance-usage-audit-log', - 'compute'): - msg = "os-instance-usage-audit-log extension not enabled." - raise cls.skipException(msg) - - @decorators.idempotent_id('c80246c0-5c13-4ab0-97ba-91551cd53dc1') - @rbac_rule_validation.action( - service="nova", rules=[_INSTANCE_USAGE_LIST]) - def test_list_instance_usage_audit_logs(self): - with self.override_role(): - (self.instance_usages_audit_log_client - .list_instance_usage_audit_logs()) - - @decorators.idempotent_id('ded8bfbd-5d90-4a58-aee0-d31231bf3c9b') - @rbac_rule_validation.action( - service="nova", rules=[_INSTANCE_USAGE_SHOW]) - def test_show_instance_usage_audit_log(self): - now = datetime.datetime.now() - - with self.override_role(): - (self.instance_usages_audit_log_client. - show_instance_usage_audit_log( - urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))) diff --git a/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py deleted file mode 100644 index 15d71436..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py +++ /dev/null @@ -1,66 +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.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class KeypairsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - def _create_keypair(self): - key_name = data_utils.rand_name(self.__class__.__name__ + '-key') - keypair = self.keypairs_client.create_keypair(name=key_name) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.keypairs_client.delete_keypair, - key_name) - return keypair - - @decorators.idempotent_id('16e0ae81-e05f-48cd-b253-cf31ab0732f0') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-keypairs:create"]) - def test_create_keypair(self): - with self.override_role(): - self._create_keypair() - - @decorators.idempotent_id('85a5eb99-40ec-4e77-9358-bee2cdf9d7df') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-keypairs:show"]) - def test_show_keypair(self): - kp_name = self._create_keypair()['keypair']['name'] - with self.override_role(): - self.keypairs_client.show_keypair(kp_name) - - @decorators.idempotent_id('6bff9f1c-b809-43c1-8d63-61fbd19d49d3') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-keypairs:delete"]) - def test_delete_keypair(self): - kp_name = self._create_keypair()['keypair']['name'] - with self.override_role(): - self.keypairs_client.delete_keypair(kp_name) - - @decorators.idempotent_id('6bb31346-ff7f-4b10-978e-170ac5fcfa3e') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-keypairs:index"]) - def test_index_keypair(self): - with self.override_role(): - self.keypairs_client.list_keypairs() diff --git a/patrole_tempest_plugin/tests/api/compute/test_limits_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_limits_rbac.py deleted file mode 100644 index 564a36d5..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_limits_rbac.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2017 AT&T Corporation -# 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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class LimitsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(LimitsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-limits', 'compute'): - msg = "%s skipped as os-limits not enabled." % cls.__name__ - raise cls.skipException(msg) - - @rbac_rule_validation.action(service="nova", - rules=["os_compute_api:limits"]) - @decorators.idempotent_id('3fb60f83-9a5f-4fdd-89d9-26c3710844a1') - def test_show_limits(self): - with self.override_role(): - self.limits_client.show_limits() diff --git a/patrole_tempest_plugin/tests/api/compute/test_migrations_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_migrations_rbac.py deleted file mode 100644 index cd3047da..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_migrations_rbac.py +++ /dev/null @@ -1,38 +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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class MigrationsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(MigrationsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-migrations', 'compute'): - msg = "%s skipped as os-migrations not enabled." % cls.__name__ - raise cls.skipException(msg) - - @decorators.idempotent_id('5795231c-3729-448c-a072-9a225db1a328') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-migrations:index"]) - def test_list_services(self): - with self.override_role(): - self.migrations_client.list_migrations() diff --git a/patrole_tempest_plugin/tests/api/compute/test_quota_class_sets_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_quota_class_sets_rbac.py deleted file mode 100644 index b26ddc3b..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_quota_class_sets_rbac.py +++ /dev/null @@ -1,85 +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.common import identity -from tempest.common import tempest_fixtures as fixtures -from tempest.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class QuotaClassesRbacTest(rbac_base.BaseV2ComputeRbacTest): - - credentials = ['primary', 'admin'] - - def setUp(self): - # All test cases in this class need to externally lock on doing - # anything with default quota values. - self.useFixture(fixtures.LockFixture('compute_quotas')) - super(QuotaClassesRbacTest, self).setUp() - - @classmethod - def skip_checks(cls): - super(QuotaClassesRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-quota-class-sets', 'compute'): - msg = "%s skipped as os-quota-class-sets extension not enabled."\ - % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(QuotaClassesRbacTest, cls).setup_clients() - cls.quota_classes_client = cls.os_primary.quota_classes_client - cls.identity_projects_client = cls.os_primary.projects_client - - @classmethod - def resource_setup(cls): - super(QuotaClassesRbacTest, cls).resource_setup() - # Create a project with its own quota. - project_name = data_utils.rand_name(cls.__name__) - project_desc = project_name + '-desc' - project = identity.identity_utils(cls.os_admin).create_project( - name=project_name, description=project_desc) - cls.project_id = project['id'] - cls.addClassResourceCleanup( - identity.identity_utils(cls.os_admin).delete_project, - cls.project_id) - - @decorators.idempotent_id('c10198ed-9df2-440e-a49b-367dadc6de94') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-quota-class-sets:show"]) - def test_show_quota_class_set(self): - with self.override_role(): - self.quota_classes_client.show_quota_class_set('default') - - @decorators.idempotent_id('81889e69-efd2-4e96-bb4c-ee3b646b9755') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-quota-class-sets:update"]) - def test_update_quota_class_set(self): - # Update the pre-existing quotas for the project_id. - quota_class_set = self.quota_classes_client.show_quota_class_set( - self.project_id)['quota_class_set'] - quota_class_set.pop('id') - for quota, default in quota_class_set.items(): - quota_class_set[quota] = default + 100 - - with self.override_role(): - self.quota_classes_client.update_quota_class_set( - self.project_id, **quota_class_set) diff --git a/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py deleted file mode 100644 index a41d0e0c..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py +++ /dev/null @@ -1,112 +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.common import identity -from tempest.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class QuotaSetsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - credentials = ['primary', 'admin'] - - @classmethod - def setup_clients(cls): - super(QuotaSetsRbacTest, cls).setup_clients() - cls.projects_client = cls.os_primary.projects_client - - @classmethod - def skip_checks(cls): - super(QuotaSetsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-quota-sets', 'compute'): - msg = "%s skipped as os-quota-sets extension not enabled."\ - % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(QuotaSetsRbacTest, cls).resource_setup() - cls.tenant_id = cls.quotas_client.tenant_id - cls.user_id = cls.quotas_client.user_id - cls.quota_set = set(('injected_file_content_bytes', - 'metadata_items', 'injected_files', - 'ram', 'floating_ips', 'fixed_ips', 'key_pair', - 'injected_file_path_bytes', 'instances', - 'security_group_rules', 'cores', - 'security_groups')) - - @decorators.idempotent_id('8229ceb0-db6a-4a2c-99c2-de226905d8b6') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-quota-sets:update"]) - def test_update_quota_set(self): - default_quota_set = self.quotas_client.show_default_quota_set( - self.tenant_id)['quota_set'] - default_quota_set.pop('id') - new_quota_set = {'injected_file_content_bytes': 20480} - - with self.override_role(): - self.quotas_client.update_quota_set(self.tenant_id, - force=True, - **new_quota_set) - self.addCleanup(self.quotas_client.update_quota_set, self.tenant_id, - **default_quota_set) - - @decorators.idempotent_id('58df5613-8f3c-400a-8b4b-2bae624d05e9') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-quota-sets:defaults"]) - def test_show_default_quota_set(self): - with self.override_role(): - self.quotas_client.show_default_quota_set(self.tenant_id) - - @decorators.idempotent_id('e8169ac4-c402-4864-894e-aba74e3a459c') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-quota-sets:show"]) - def test_show_quota_set(self): - with self.override_role(): - self.quotas_client.show_quota_set(self.tenant_id) - - @decorators.idempotent_id('4e240644-bf61-4872-9c32-8289ee2fdbbd') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-quota-sets:delete"]) - def test_delete_quota_set(self): - project_name = data_utils.rand_name( - self.__class__.__name__) - project_desc = project_name + '-desc' - project = identity.identity_utils(self.os_admin).create_project( - name=project_name, description=project_desc) - project_id = project['id'] - self.addCleanup( - identity.identity_utils(self.os_admin).delete_project, - project_id) - - with self.override_role(): - self.quotas_client.delete_quota_set(project_id) - - @decorators.idempotent_id('ac9184b6-f3b3-4e17-a632-4b92c6500f86') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-quota-sets:detail"]) - def test_show_quota_set_details(self): - with self.override_role(): - self.quotas_client.show_quota_set(self.tenant_id, - detail=True) diff --git a/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py deleted file mode 100644 index cf19befb..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py +++ /dev/null @@ -1,187 +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 import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_nova_policies_ussuri: - _SG_LIST = "os_compute_api:os-security-groups:list" - _SG_ADD = "os_compute_api:os-security-groups:add" - _SG_REMOVE = "os_compute_api:os-security-groups:remove" -else: - _SG_LIST = "os_compute_api:os-security-groups" - _SG_ADD = "os_compute_api:os-security-groups" - _SG_REMOVE = "os_compute_api:os-security-groups" - -if CONF.policy_feature_enabled.changed_nova_policies_victoria: - _SG_GET = "os_compute_api:os-security-groups:get" - _SG_SHOW = "os_compute_api:os-security-groups:show" - _SG_CREATE = "os_compute_api:os-security-groups:create" - _SG_UPDATE = "os_compute_api:os-security-groups:update" - _SG_DELETE = "os_compute_api:os-security-groups:delete" -else: - _SG_GET = "os_compute_api:os-security-groups" - _SG_SHOW = "os_compute_api:os-security-groups" - _SG_CREATE = "os_compute_api:os-security-groups" - _SG_UPDATE = "os_compute_api:os-security-groups" - _SG_DELETE = "os_compute_api:os-security-groups" - - -class SecurtiyGroupsRbacTest(rbac_base.BaseV2ComputeRbacTest): - """Tests non-deprecated security group policies. Requires network service. - - This class tests non-deprecated policies for adding and removing a security - group to and from a server. - """ - - @classmethod - def skip_checks(cls): - super(SecurtiyGroupsRbacTest, cls).skip_checks() - # All the tests below require the network service. - # NOTE(gmann) Currently 'network' service is always True in - # utils.get_service_list() So below check is not much of use. - # Commenting the below check as Tempest is moving the get_service_list - # from test.py to utils. - # If we want to check 'network' service availability, then - # get_service_list can be used from new location. - # if not utils.get_service_list()['network']: - # raise cls.skipException( - # 'Skipped because the network service is not available') - - @classmethod - def setup_credentials(cls): - # A network and a subnet will be created for these tests. - cls.set_network_resources(network=True, subnet=True) - super(SecurtiyGroupsRbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(SecurtiyGroupsRbacTest, cls).resource_setup() - cls.server = cls.create_test_server(wait_until='ACTIVE') - - @rbac_rule_validation.action( - service="nova", - rules=[_SG_LIST]) - @decorators.idempotent_id('3db159c6-a467-469f-9a25-574197885520') - def test_list_security_groups_by_server(self): - with self.override_role(): - self.servers_client.list_security_groups_by_server( - self.server['id']) - - @rbac_rule_validation.action( - service="nova", - rules=[_SG_ADD]) - @decorators.idempotent_id('ea1ca73f-2d1d-43cb-9a46-900d7927b357') - def test_create_security_group_for_server(self): - sg_name = self.create_security_group()['name'] - - with self.override_role(): - self.servers_client.add_security_group(self.server['id'], - name=sg_name) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.servers_client.remove_security_group, - self.server['id'], name=sg_name) - - @rbac_rule_validation.action( - service="nova", - rules=[_SG_REMOVE]) - @decorators.idempotent_id('0ad2e856-e2d3-4ac5-a620-f93d0d3d2626') - def test_remove_security_group_from_server(self): - sg_name = self.create_security_group()['name'] - - self.servers_client.add_security_group(self.server['id'], name=sg_name) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.servers_client.remove_security_group, - self.server['id'], name=sg_name) - - with self.override_role(): - self.servers_client.remove_security_group( - self.server['id'], name=sg_name) - - -class SecurityGroupsRbacMaxV235Test(rbac_base.BaseV2ComputeRbacTest): - - # Tests in this class will fail with a 404 from microversion 2.36, - # according to: - # https://docs.openstack.org/api-ref/compute/#security-groups-os-security-groups-deprecated - max_microversion = '2.35' - - @classmethod - def skip_checks(cls): - super(SecurityGroupsRbacMaxV235Test, cls).skip_checks() - # All the tests below require the network service. - # NOTE(gmann) Currently 'network' service is always True in - # utils.get_service_list() So below check is not much of use. - # Commenting the below check as Tempest is moving the get_service_list - # from test.py to utils. - # If we want to check 'network' service availability, then - # get_service_list can be used from new location. - # if not utils.get_service_list()['network']: - # raise cls.skipException( - # 'Skipped because the network service is not available') - - @rbac_rule_validation.action( - service="nova", - rules=[_SG_GET]) - @decorators.idempotent_id('4ac58e49-48c1-4fca-a6c3-3f95fb99eb77') - def test_list_security_groups(self): - with self.override_role(): - self.security_groups_client.list_security_groups() - - @rbac_rule_validation.action( - service="nova", - rules=[_SG_CREATE]) - @decorators.idempotent_id('e8fe7f5a-69ee-412d-81d3-a8c7a488b54d') - def test_create_security_groups(self): - with self.override_role(): - self.create_security_group()['id'] - - @rbac_rule_validation.action( - service="nova", - rules=[_SG_DELETE]) - @decorators.idempotent_id('59127e8e-302d-11e7-93ae-92361f002671') - def test_delete_security_groups(self): - sec_group_id = self.create_security_group()['id'] - with self.override_role(): - self.security_groups_client.delete_security_group(sec_group_id) - - @rbac_rule_validation.action( - service="nova", - rules=[_SG_UPDATE]) - @decorators.idempotent_id('3de5c6bc-b822-469e-a627-82427d38b067') - def test_update_security_groups(self): - sec_group_id = self.create_security_group()['id'] - new_name = data_utils.rand_name() - new_desc = data_utils.rand_name() - - with self.override_role(): - self.security_groups_client.update_security_group( - sec_group_id, name=new_name, description=new_desc) - - @rbac_rule_validation.action( - service="nova", - rules=[_SG_SHOW]) - @decorators.idempotent_id('6edc0320-302d-11e7-93ae-92361f002671') - def test_show_security_groups(self): - sec_group_id = self.create_security_group()['id'] - with self.override_role(): - self.security_groups_client.show_security_group(sec_group_id) diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py deleted file mode 100644 index 1410caa1..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py +++ /dev/null @@ -1,422 +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. - -import testtools - -from tempest.common import utils -from tempest.common import waiters -from tempest import config -from tempest.lib.common import api_version_utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators -from tempest.lib import exceptions as lib_exc - -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 - -CONF = config.CONF - - -class ServerActionsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - # admin credentials used for waiters which invokes a show API call - credentials = ['primary', 'admin'] - - @classmethod - def setup_clients(cls): - super(ServerActionsRbacTest, cls).setup_clients() - cls.admin_servers_client = cls.os_admin.servers_client - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ServerActionsRbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(ServerActionsRbacTest, cls).resource_setup() - cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id'] - cls.flavor_ref = CONF.compute.flavor_ref - cls.flavor_ref_alt = CONF.compute.flavor_ref_alt - cls.image_ref = CONF.compute.image_ref - - def setUp(self): - super(ServerActionsRbacTest, self).setUp() - try: - waiters.wait_for_server_status(self.servers_client, - 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'] - except Exception: - # Recreating the server in case something happened during a test - self.__class__.server_id = self.recreate_server(self.server_id) - - def _stop_server(self): - self.servers_client.stop_server(self.server_id) - waiters.wait_for_server_status( - self.admin_servers_client, self.server_id, 'SHUTOFF') - - def _resize_server(self, flavor): - status = self.admin_servers_client. \ - show_server(self.server_id)['server']['status'] - if status == 'RESIZED': - return - self.servers_client.resize_server(self.server_id, flavor) - waiters.wait_for_server_status( - self.admin_servers_client, self.server_id, 'VERIFY_RESIZE') - - def _confirm_resize_server(self): - status = self.admin_servers_client. \ - show_server(self.server_id)['server']['status'] - if status == 'VERIFY_RESIZE': - self.servers_client.confirm_resize_server(self.server_id) - waiters.wait_for_server_status( - self.admin_servers_client, self.server_id, 'ACTIVE') - - def _shelve_server(self): - self.servers_client.shelve_server(self.server_id) - self.addCleanup(self._cleanup_server_actions, - self.servers_client.unshelve_server, - self.server_id) - offload_time = CONF.compute.shelved_offload_time - if offload_time >= 0: - waiters.wait_for_server_status(self.admin_servers_client, - self.server_id, - 'SHELVED_OFFLOADED', - extra_timeout=offload_time) - else: - waiters.wait_for_server_status(self.admin_servers_client, - self.server_id, - 'SHELVED') - - def _pause_server(self): - self.servers_client.pause_server(self.server_id) - self.addCleanup(self._cleanup_server_actions, - self.servers_client.unpause_server, - self.server_id) - waiters.wait_for_server_status( - self.admin_servers_client, self.server_id, 'PAUSED') - - def _cleanup_server_actions(self, function, server_id, **kwargs): - server = self.servers_client.show_server(server_id)['server'] - if server['status'] != 'ACTIVE': - function(server_id, **kwargs) - - @decorators.idempotent_id('117f4ff2-8544-437b-824f-5e41cb6640ee') - @testtools.skipUnless(CONF.compute_feature_enabled.pause, - 'Pause is not available.') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-pause-server:pause"]) - def test_pause_server(self): - with self.override_role(): - self._pause_server() - - @decorators.idempotent_id('087008cf-82fa-4eeb-ae8b-32c4126456ad') - @testtools.skipUnless(CONF.compute_feature_enabled.pause, - 'Pause is not available.') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-pause-server:unpause"]) - def test_unpause_server(self): - self._pause_server() - with self.override_role(): - self.servers_client.unpause_server(self.server_id) - waiters.wait_for_server_status( - self.servers_client, self.server_id, 'ACTIVE') - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:stop"]) - @decorators.idempotent_id('ab4a17d2-166f-4a6d-9944-f17baa576cf2') - def test_stop_server(self): - with self.override_role(): - self._stop_server() - - @decorators.attr(type='slow') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:start"]) - @decorators.idempotent_id('8876bfa9-4d10-406e-a335-a57e451abb12') - def test_start_server(self): - self._stop_server() - - with self.override_role(): - self.servers_client.start_server(self.server_id) - waiters.wait_for_server_status( - self.servers_client, self.server_id, 'ACTIVE') - - @decorators.attr(type='slow') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:resize"]) - @decorators.idempotent_id('0546fbdd-2d8f-4ce8-ac00-f1e2129d0765') - @testtools.skipUnless(CONF.compute_feature_enabled.resize, - 'Resize is not available.') - def test_resize_server(self): - with self.override_role(): - self._resize_server(self.flavor_ref_alt) - - @decorators.attr(type='slow') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:revert_resize"]) - @decorators.idempotent_id('d41b64b8-a72d-414a-a4c5-94e1eb5e5a96') - @testtools.skipUnless(CONF.compute_feature_enabled.resize, - 'Resize is not available.') - def test_revert_resize_server(self): - self._resize_server(self.flavor_ref_alt) - - with self.override_role(): - self.servers_client.revert_resize_server(self.server_id) - waiters.wait_for_server_status( - self.servers_client, self.server_id, 'ACTIVE') - - @decorators.attr(type='slow') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:confirm_resize"]) - @decorators.idempotent_id('f51620cb-dfcb-4e5d-b421-2e0edaa1316e') - @testtools.skipUnless(CONF.compute_feature_enabled.resize, - 'Resize is not available.') - def test_confirm_resize_server(self): - self._resize_server(self.flavor_ref_alt) - self.addCleanup(self._confirm_resize_server) - self.addCleanup(self._resize_server, self.flavor_ref) - self.addCleanup(self._confirm_resize_server) - - with self.override_role(): - self._confirm_resize_server() - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:rebuild"]) - @decorators.idempotent_id('54b1a30b-c96c-472c-9c83-ccaf6ec7e20b') - def test_rebuild_server(self): - with self.override_role(): - self.servers_client.rebuild_server(self.server_id, self.image_ref) - waiters.wait_for_server_status( - self.servers_client, self.server_id, 'ACTIVE') - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:reboot"]) - @decorators.idempotent_id('19f27856-56e1-44f8-8615-7257f6b85cbb') - def test_reboot_server(self): - with self.override_role(): - self.servers_client.reboot_server(self.server_id, type='HARD') - waiters.wait_for_server_status( - self.servers_client, self.server_id, 'ACTIVE') - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:index"]) - @decorators.idempotent_id('631f0d86-7607-4198-8312-9da2f05464a4') - def test_server_index(self): - with self.override_role(): - self.servers_client.list_servers(minimal=True) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:detail"]) - @decorators.idempotent_id('96093480-3ce5-4a8b-b569-aed870379c24') - def test_server_detail(self): - with self.override_role(): - self.servers_client.list_servers(detail=True) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:detail:get_all_tenants"]) - @decorators.idempotent_id('a9e5a1c0-acfe-49a2-b2b1-fd8b19d61f71') - def test_server_detail_all_tenants(self): - with self.override_role(): - self.servers_client.list_servers(detail=True, all_tenants=1) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:index:get_all_tenants"]) - @decorators.idempotent_id('4b93ba56-69e6-41f5-82c4-84a5c4c42091') - def test_server_index_all_tenants(self): - with self.override_role(): - self.servers_client.list_servers(minimal=True, all_tenants=1) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:show"]) - @decorators.idempotent_id('eaaf4f51-31b5-497f-8f0f-f527e5f70b83') - def test_show_server(self): - with self.override_role(): - self.servers_client.show_server(self.server_id) - - @utils.services('image') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:create_image"]) - @decorators.idempotent_id('ba0ac859-99f4-4055-b5e0-e0905a44d331') - def test_create_image(self): - with self.override_role(): - # This function will also call show image - self.create_image_from_server(self.server_id, wait_until='ACTIVE') - - @utils.services('image', 'volume') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:create_image:allow_volume_backed"]) - @decorators.idempotent_id('8b869f73-49b3-4cc4-a0ce-ef64f8e1d6f9') - def test_create_image_from_volume_backed_server(self): - # volume_backed=True creates a volume and create server will be - # requested with 'block_device_mapping_v2' with necessary values for - # this test. - server = self.create_test_server(volume_backed=True, - wait_until='ACTIVE') - with self.override_role(): - # This function will also call show image. - image = self.create_image_from_server(server['id'], - wait_until='ACTIVE', - wait_for_server=False) - self.addCleanup(self.compute_images_client.wait_for_resource_deletion, - image['id']) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.compute_images_client.delete_image, image['id']) - - @decorators.idempotent_id('9fdd4630-731c-4f7c-bce5-69fa3792c52a') - @decorators.attr(type='slow') - @testtools.skipUnless(CONF.compute_feature_enabled.snapshot, - 'Snapshotting not available, backup not possible.') - @utils.services('image') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-create-backup"]) - def test_create_backup(self): - # Prioritize glance v2 over v1 for deleting/waiting for image status. - if CONF.image_feature_enabled.api_v2: - glance_client = self.os_primary.image_client_v2 - elif CONF.image_feature_enabled.api_v1: - glance_client = self.os_primary.image_client - else: - raise lib_exc.InvalidConfiguration( - 'Either api_v1 or api_v2 must be True in ' - '[image-feature-enabled].') - - backup_name = data_utils.rand_name(self.__class__.__name__ + '-Backup') - - with self.override_role(): - resp = self.servers_client.create_backup( - self.server_id, backup_type='daily', rotation=1, - name=backup_name).response - - # Prior to microversion 2.45, image ID must be parsed from location - # header. With microversion 2.45+, image_id is returned. - if api_version_utils.compare_version_header_to_response( - "OpenStack-API-Version", "2.45", resp, "lt"): - image_id = resp['image_id'] - else: - image_id = data_utils.parse_image_id(resp['location']) - - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - glance_client.delete_image, image_id) - waiters.wait_for_image_status(glance_client, image_id, 'active') - - @decorators.attr(type='slow') - @decorators.idempotent_id('0b70c527-af75-4bed-9ccf-4f1310a8b60f') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-shelve:shelve"]) - def test_shelve_server(self): - with self.override_role(): - self._shelve_server() - - @decorators.attr(type='slow') - @decorators.idempotent_id('4b6e849a-9182-49ff-9257-e97e751b475e') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-shelve:unshelve"]) - def test_unshelve_server(self): - self._shelve_server() - with self.override_role(): - self.servers_client.unshelve_server(self.server_id) - waiters.wait_for_server_status( - self.servers_client, self.server_id, 'ACTIVE') - - -class ServerActionsV214RbacTest(rbac_base.BaseV2ComputeRbacTest): - - min_microversion = '2.14' - max_microversion = 'latest' - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ServerActionsV214RbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(ServerActionsV214RbacTest, cls).resource_setup() - cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id'] - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-evacuate"]) - @decorators.idempotent_id('78ecef3c-faff-412a-83be-47651963eb21') - def test_evacuate_server(self): - fake_host_name = data_utils.rand_name( - self.__class__.__name__ + '-fake-host') - - # NOTE(felipemonteiro): Because evacuating a server is a risky action - # to test in the gates, a 404 is coerced using a fake host. However, - # the policy check is done before the 404 is thrown. - with self.override_role(): - self.assertRaisesRegex( - lib_exc.NotFound, - "Compute host %s not found." % fake_host_name, - self.servers_client.evacuate_server, self.server_id, - host=fake_host_name) - - -class ServerActionsV216RbacTest(rbac_base.BaseV2ComputeRbacTest): - - # This class has test case(s) that requires at least microversion 2.16. - # See the following link for details: - # https://docs.openstack.org/api-ref/compute/#show-server-details - min_microversion = '2.16' - max_microversion = 'latest' - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ServerActionsV216RbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(ServerActionsV216RbacTest, cls).resource_setup() - cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id'] - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:show:host_status"]) - @decorators.idempotent_id('736da575-86f8-4b2a-9902-dd37dc9a409b') - def test_show_server_host_status(self): - with self.override_role(): - server = self.servers_client.show_server(self.server_id)['server'] - - if 'host_status' not in server: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='host_status') diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_consoles_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_consoles_rbac.py deleted file mode 100644 index 076ad058..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_server_consoles_rbac.py +++ /dev/null @@ -1,109 +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 import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - - -class ServerConsolesRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(ServerConsolesRbacTest, cls).skip_checks() - if not CONF.compute_feature_enabled.console_output: - raise cls.skipException('Console output not available.') - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ServerConsolesRbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(ServerConsolesRbacTest, cls).resource_setup() - cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id'] - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-console-output"]) - @decorators.idempotent_id('90fd80f6-456c-11e7-a919-92ebcb67fe33') - def test_get_console_output(self): - with self.override_role(): - self.servers_client.get_console_output(self.server_id) - - -class ServerConsolesMaxV25RbacTest(rbac_base.BaseV2ComputeRbacTest): - - max_microversion = '2.5' - - @classmethod - def skip_checks(cls): - super(ServerConsolesMaxV25RbacTest, cls).skip_checks() - if not CONF.compute_feature_enabled.console_output: - raise cls.skipException('Console output not available.') - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ServerConsolesMaxV25RbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(ServerConsolesMaxV25RbacTest, cls).resource_setup() - cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id'] - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-remote-consoles"]) - @decorators.idempotent_id('b0a72c02-9b15-4dcb-b186-efe8753370ab') - def test_get_vnc_console_output(self): - with self.override_role(): - self.servers_client.get_vnc_console(self.server_id, type="novnc") - - -class ServerConsolesV26RbacTest(rbac_base.BaseV2ComputeRbacTest): - - min_microversion = '2.6' - max_microversion = 'latest' - - @classmethod - def skip_checks(cls): - super(ServerConsolesV26RbacTest, cls).skip_checks() - if not CONF.compute_feature_enabled.console_output: - raise cls.skipException('Console output not available.') - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ServerConsolesV26RbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(ServerConsolesV26RbacTest, cls).resource_setup() - cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id'] - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-remote-consoles"]) - @decorators.idempotent_id('879597de-87e0-4da9-a60a-28c8088dc508') - def test_get_remote_console_output(self): - with self.override_role(): - self.servers_client.get_remote_console(self.server_id, - "novnc", "vnc") diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_groups_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_groups_rbac.py deleted file mode 100644 index 7c5002be..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_server_groups_rbac.py +++ /dev/null @@ -1,64 +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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class ServerGroupsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(ServerGroupsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-server-groups', 'compute'): - msg = "%s skipped as os-server-groups not enabled." % cls.__name__ - raise cls.skipException(msg) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-groups:create"]) - @decorators.idempotent_id('7f3eae94-6130-47e9-81ac-34009f55be2f') - def test_create_server_group(self): - with self.override_role(): - self.create_test_server_group() - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-groups:delete"]) - @decorators.idempotent_id('832d9be3-632e-47b2-93d2-5897db43e3e2') - def test_delete_server_group(self): - server_group = self.create_test_server_group() - with self.override_role(): - self.server_groups_client.delete_server_group(server_group['id']) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-groups:index"]) - @decorators.idempotent_id('5eccd67f-5945-483b-b1c8-de851ebfc1c1') - def test_list_server_groups(self): - with self.override_role(): - self.server_groups_client.list_server_groups() - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-groups:show"]) - @decorators.idempotent_id('62534e3f-7e99-4a3d-a08e-33e056460cf2') - def test_show_server_group(self): - server_group = self.create_test_server_group() - with self.override_role(): - self.server_groups_client.show_server_group(server_group['id']) diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_metadata_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_metadata_rbac.py deleted file mode 100644 index 55536ad6..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_server_metadata_rbac.py +++ /dev/null @@ -1,89 +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 patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class ServerMetadataRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ServerMetadataRbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(ServerMetadataRbacTest, cls).resource_setup() - cls.server = cls.create_test_server(metadata={}, wait_until='ACTIVE') - cls.meta = {'default_key': 'value1', 'delete_key': 'value2'} - - def setUp(self): - super(ServerMetadataRbacTest, self).setUp() - self.servers_client.set_server_metadata(self.server['id'], self.meta)[ - 'metadata'] - - @decorators.idempotent_id('b07bbc27-58e2-4581-869d-ad228cec5d9a') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:server-metadata:index"]) - def test_list_server_metadata(self): - with self.override_role(): - self.servers_client.list_server_metadata(self.server['id']) - - @decorators.idempotent_id('6e76748b-2417-4fa2-b41a-c0cc4bff356b') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:server-metadata:update_all"]) - def test_set_server_metadata(self): - with self.override_role(): - self.servers_client.set_server_metadata(self.server['id'], {}) - - @decorators.idempotent_id('1060bac4-fe16-4a77-be64-d8e482a06eab') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:server-metadata:create"]) - def test_update_server_metadata(self): - with self.override_role(): - self.servers_client.update_server_metadata(self.server['id'], {}) - - @decorators.idempotent_id('93dd8323-d3fa-48d1-8bd6-91c1b62fc341') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:server-metadata:show"]) - def test_show_server_metadata_item(self): - with self.override_role(): - self.servers_client.show_server_metadata_item( - self.server['id'], 'default_key') - - @decorators.idempotent_id('79511293-4bd7-447d-ba7e-634d0f4da70c') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:server-metadata:update"]) - def test_set_server_metadata_item(self): - with self.override_role(): - self.servers_client.set_server_metadata_item( - self.server['id'], 'default_key', {'default_key': 'value2'}) - - @decorators.idempotent_id('feec5064-678d-40bc-a88f-c856e18d1e31') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:server-metadata:delete"]) - def test_delete_server_metadata_item(self): - with self.override_role(): - self.servers_client.delete_server_metadata_item( - self.server['id'], 'delete_key') diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_migrations_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_migrations_rbac.py deleted file mode 100644 index 6ad8f400..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_server_migrations_rbac.py +++ /dev/null @@ -1,92 +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. - -import testtools - -from tempest.common import waiters -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base as base - -CONF = config.CONF - - -class MigrateServerV225RbacTest(base.BaseV2ComputeRbacTest): - min_microversion = '2.25' - max_microversion = 'latest' - block_migration = 'auto' - - @classmethod - def skip_checks(cls): - super(MigrateServerV225RbacTest, cls).skip_checks() - if CONF.compute.min_compute_nodes < 2: - raise cls.skipException( - "Less than 2 compute nodes, skipping migration tests.") - - def _get_server_details(self, server_id): - body = self.servers_client.show_server(server_id)['server'] - return body - - def _get_host_for_server(self, server_id): - return self._get_server_details(server_id)['OS-EXT-SRV-ATTR:host'] - - def _get_host_other_than(self, host): - for target_host in self._get_compute_hostnames(): - if host != target_host: - return target_host - - def _get_compute_hostnames(self): - body = self.hosts_client.list_hosts()['hosts'] - return [ - host_record['host_name'] - for host_record in body - if host_record['service'] == 'compute' - ] - - @decorators.attr(type='slow') - @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration, - 'Cold migration not available.') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-migrate-server:migrate"]) - @decorators.idempotent_id('c6f1607c-9fed-4c00-807e-9ba675b98b1b') - def test_cold_migration(self): - server = self.create_test_server(wait_until="ACTIVE") - with self.override_role(): - self.servers_client.migrate_server(server['id']) - waiters.wait_for_server_status(self.servers_client, - server['id'], 'VERIFY_RESIZE') - - @decorators.attr(type='slow') - @testtools.skipUnless(CONF.compute_feature_enabled.live_migration, - 'Live migration feature is not enabled.') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-migrate-server:migrate_live"]) - @decorators.idempotent_id('33520834-72c8-4edb-a189-a2e0fc9eb0d3') - def test_migration_live(self): - server_id = self.create_test_server(wait_until="ACTIVE", - volume_backed=False)['id'] - actual_host = self._get_host_for_server(server_id) - target_host = self._get_host_other_than(actual_host) - - with self.override_role(): - self.servers_client.live_migrate_server( - server_id, host=target_host, - block_migration=self.block_migration) - waiters.wait_for_server_status(self.servers_client, - server_id, "ACTIVE") 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 deleted file mode 100644 index 9abd00e5..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py +++ /dev/null @@ -1,828 +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. - -import netaddr - -import testtools - -from tempest.common import utils -from tempest.common import waiters -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators -from tempest.lib import exceptions as lib_exc - -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 - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_nova_policies_ussuri: - _DEFERRED_FORCE = "os_compute_api:os-deferred-delete:force" - _ATTACH_INTERFACES_LIST = "os_compute_api:os-attach-interfaces:list" - _ATTACH_INTERFACES_SHOW = "os_compute_api:os-attach-interfaces:show" - _INSTANCE_ACTIONS_LIST = "os_compute_api:os-instance-actions:list" - _SERVER_PASSWORD_SHOW = "os_compute_api:os-server-password:show" - _SERVER_PASSWORD_CLEAR = "os_compute_api:os-server-password:clear" -else: - _DEFERRED_FORCE = "os_compute_api:os-deferred-delete" - _ATTACH_INTERFACES_LIST = "os_compute_api:os-attach-interfaces" - _ATTACH_INTERFACES_SHOW = "os_compute_api:os-attach-interfaces" - _INSTANCE_ACTIONS_LIST = "os_compute_api:os-instance-actions" - _SERVER_PASSWORD_SHOW = "os_compute_api:os-server-password" - _SERVER_PASSWORD_CLEAR = "os_compute_api:os-server-password" - -if CONF.policy_feature_enabled.changed_nova_policies_victoria: - _MULTINIC_ADD = "os_compute_api:os-multinic:add" -else: - _MULTINIC_ADD = "os_compute_api:os-multinic" - - -class MiscPolicyActionsRbacTest(rbac_base.BaseV2ComputeRbacTest): - """Test multiple policy actions that require a server to be created. - - Minimize the number of servers that need to be created across classes - by consolidating test cases related to different policy "families" into - one class. This reduces the risk of running into `BuildErrorException` - errors being raised due to too many servers being created simultaneously - especially when higher concurrency is used. - - Only applies to: - * policy "families" that require server creation - * small policy "families" -- i.e. containing one to three policies - - Tests are ordered by policy name. - """ - - credentials = ['primary', 'admin'] - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(MiscPolicyActionsRbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(MiscPolicyActionsRbacTest, cls).resource_setup() - 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') - except lib_exc.NotFound: - # If the server was found to be deleted by a previous test, - # a new one is built - 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 = 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) - - @utils.requires_ext(extension='os-admin-actions', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-admin-actions:reset_state"]) - @decorators.idempotent_id('ae84dd0b-f364-462e-b565-3457f9c019ef') - def test_reset_server_state(self): - """Test reset server state, part of os-admin-actions.""" - with self.override_role(): - self.servers_client.reset_state(self.server['id'], state='error') - self.addCleanup(self.servers_client.reset_state, self.server['id'], - state='active') - - @utils.requires_ext(extension='os-admin-actions', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-admin-actions:inject_network_info"]) - @decorators.idempotent_id('ce48c340-51c1-4cff-9b6e-0cc5ef008630') - def test_inject_network_info(self): - """Test inject network info, part of os-admin-actions.""" - with self.override_role(): - self.servers_client.inject_network_info(self.server['id']) - - @testtools.skipIf( - CONF.policy_feature_enabled.removed_nova_policies_wallaby, - "This API extension policy was removed in Wallaby") - @utils.requires_ext(extension='os-admin-actions', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-admin-actions:reset_network"]) - @decorators.idempotent_id('2911a242-15c4-4fcb-80d5-80a8930661b0') - def test_reset_network(self): - """Test reset network, part of os-admin-actions.""" - with self.override_role(): - self.servers_client.reset_network(self.server['id']) - - @testtools.skipUnless(CONF.compute_feature_enabled.change_password, - 'Change password not available.') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-admin-password"]) - @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']) - - with self.override_role(): - self.servers_client.change_password( - 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.servers_client, self.server['id'], 'ACTIVE') - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @utils.requires_ext(extension='os-config-drive', service='compute') - @decorators.idempotent_id('2c82e819-382d-4d6f-87f0-a45954cbbc64') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-config-drive"]) - def test_list_servers_with_details_config_drive(self): - """Test list servers with config_drive property in response body.""" - with self.override_role(): - body = self.servers_client.list_servers(detail=True)['servers'] - expected_attr = 'config_drive' - # If the first server contains "config_drive", then all the others do. - if expected_attr not in body[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @utils.requires_ext(extension='os-config-drive', service='compute') - @decorators.idempotent_id('55c62ef7-b72b-4970-acc6-05b0a4316e5d') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-config-drive"]) - def test_show_server_config_drive(self): - """Test show server with config_drive property in response body.""" - with self.override_role(): - body = self.servers_client.show_server(self.server['id'])['server'] - expected_attr = 'config_drive' - if expected_attr not in body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @utils.requires_ext(extension='os-deferred-delete', service='compute') - @decorators.idempotent_id('189bfed4-1e6d-475c-bb8c-d57e60895391') - @rbac_rule_validation.action( - service="nova", - rules=[_DEFERRED_FORCE]) - def test_force_delete_server(self): - """Test force delete server, part of os-deferred-delete.""" - with self.override_role(): - # Force-deleting a server enforces os-deferred-delete. - self.servers_client.force_delete_server(self.server['id']) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('d873740a-7b10-40a9-943d-7cc18115370e') - @utils.requires_ext(extension='OS-EXT-AZ', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-extended-availability-zone"]) - def test_list_servers_with_details_extended_availability_zone(self): - """Test list servers OS-EXT-AZ:availability_zone attr in resp body.""" - expected_attr = 'OS-EXT-AZ:availability_zone' - - with self.override_role(): - body = self.servers_client.list_servers(detail=True)['servers'] - # If the first server contains `expected_attr`, then all the others do. - if expected_attr not in body[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('727e5360-770a-4b9c-8015-513a40216635') - @utils.requires_ext(extension='OS-EXT-AZ', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-extended-availability-zone"]) - def test_show_server_extended_availability_zone(self): - """Test show server OS-EXT-AZ:availability_zone attr in resp body.""" - expected_attr = 'OS-EXT-AZ:availability_zone' - - with self.override_role(): - body = self.servers_client.show_server(self.server['id'])['server'] - if expected_attr not in body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('4aa5d93e-4887-468a-8eb4-b6eca0ca6437') - @utils.requires_ext(extension='OS-EXT-SRV-ATTR', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-extended-server-attributes"]) - def test_list_servers_extended_server_attributes(self): - """Test list servers with details, with extended server attributes in - response body. - """ - with self.override_role(): - body = self.servers_client.list_servers(detail=True)['servers'] - - # NOTE(felipemonteiro): The attributes included below should be - # returned by all microversions. We don't include tests for other - # microversions since Tempest schema validation takes care of that in - # `show_server` call above. (Attributes there are *optional*.) - for attr in ('host', 'instance_name'): - whole_attr = 'OS-EXT-SRV-ATTR:%s' % attr - if whole_attr not in body[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=whole_attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('2ed7aee2-94b2-4a9f-ae63-a51b7f94fe30') - @utils.requires_ext(extension='OS-EXT-SRV-ATTR', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-extended-server-attributes"]) - def test_show_server_extended_server_attributes(self): - """Test show server with extended server attributes in response - body. - """ - with self.override_role(): - body = self.servers_client.show_server(self.server['id'])['server'] - - # NOTE(felipemonteiro): The attributes included below should be - # returned by all microversions. We don't include tests for other - # microversions since Tempest schema validation takes care of that in - # `show_server` call above. (Attributes there are *optional*.) - for attr in ('host', 'instance_name'): - whole_attr = 'OS-EXT-SRV-ATTR:%s' % attr - if whole_attr not in body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=whole_attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('82053c27-3134-4003-9b55-bc9fafdb0e3b') - @utils.requires_ext(extension='OS-EXT-STS', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-extended-status"]) - def test_list_servers_extended_status(self): - """Test list servers with extended properties in response body.""" - with self.override_role(): - body = self.servers_client.list_servers(detail=True)['servers'] - - expected_attrs = ('OS-EXT-STS:task_state', 'OS-EXT-STS:vm_state', - 'OS-EXT-STS:power_state') - for attr in expected_attrs: - if attr not in body[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('7d2620a5-eea1-4a8b-96ea-86ad77a73fc8') - @utils.requires_ext(extension='OS-EXT-STS', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-extended-status"]) - def test_show_server_extended_status(self): - """Test show server with extended properties in response body.""" - with self.override_role(): - body = self.servers_client.show_server(self.server['id'])['server'] - - expected_attrs = ('OS-EXT-STS:task_state', 'OS-EXT-STS:vm_state', - 'OS-EXT-STS:power_state') - for attr in expected_attrs: - if attr not in body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('21e39cbe-6c32-48fc-80dd-3e1fece6053f') - @utils.requires_ext(extension='os-extended-volumes', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-extended-volumes"]) - def test_list_servers_with_details_extended_volumes(self): - """Test list servers os-extended-volumes:volumes_attached attr in resp - body. - """ - expected_attr = 'os-extended-volumes:volumes_attached' - - with self.override_role(): - body = self.servers_client.list_servers(detail=True)['servers'] - if expected_attr not in body[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @decorators.idempotent_id('7f163708-0d25-4138-8512-dfdd72a92989') - @utils.requires_ext(extension='os-extended-volumes', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-extended-volumes"]) - def test_show_server_extended_volumes(self): - """Test show server os-extended-volumes:volumes_attached attr in resp - body. - """ - expected_attr = 'os-extended-volumes:volumes_attached' - - with self.override_role(): - body = self.servers_client.show_server(self.server['id'])['server'] - if expected_attr not in body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @utils.requires_ext(extension='os-instance-actions', service='compute') - @decorators.idempotent_id('9d1b131d-407e-4fa3-8eef-eb2c4526f1da') - @rbac_rule_validation.action( - service="nova", - rules=[_INSTANCE_ACTIONS_LIST]) - def test_list_instance_actions(self): - """Test list instance actions, part of os-instance-actions.""" - with self.override_role(): - self.servers_client.list_instance_actions(self.server['id']) - - @utils.requires_ext(extension='os-instance-actions', service='compute') - @decorators.idempotent_id('eb04c439-4215-4029-9ccb-5b3c041bfc25') - @rbac_rule_validation.action( - service="nova", - rules=["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'] - - with self.override_role(): - instance_action = self.servers_client.show_instance_action( - self.server['id'], request_id)['instanceAction'] - - if 'events' not in instance_action: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='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.RbacMissingAttributeResponseBody( - attribute='events.traceback') - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-keypairs"]) - @decorators.idempotent_id('81e6fa34-c06b-42ca-b195-82bf8699b940') - def test_show_server_keypair(self): - with self.override_role(): - result = self.servers_client.show_server(self.server['id'])[ - 'server'] - if 'key_name' not in result: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='key_name') - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-keypairs"]) - @decorators.idempotent_id('41ca4280-ec59-4b80-a9b1-6bc6366faf39') - def test_list_servers_keypairs(self): - with self.override_role(): - result = self.servers_client.list_servers(detail=True)['servers'] - if 'key_name' not in result[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='key_name') - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-lock-server:lock"]) - @decorators.idempotent_id('b81e10fb-1864-498f-8c1d-5175c6fec5fb') - def test_lock_server(self): - """Test lock server, part of os-lock-server.""" - with self.override_role(): - self.servers_client.lock_server(self.server['id']) - self.addCleanup(self.servers_client.unlock_server, self.server['id']) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-lock-server:unlock"]) - @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']) - - with self.override_role(): - self.servers_client.unlock_server(self.server['id']) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-lock-server:unlock", - "os_compute_api:os-lock-server:unlock:unlock_override"]) - @decorators.idempotent_id('40dfeef9-73ee-48a9-be19-a219875de457') - def test_unlock_server_override(self): - """Test force unlock server, part of os-lock-server. - - In order to trigger the unlock:unlock_override policy instead - 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']) - - with self.override_role(): - self.servers_client.unlock_server(self.server['id']) - - @utils.requires_ext(extension='os-rescue', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-rescue"]) - @decorators.idempotent_id('fbbb2afc-ed0e-4552-887d-ac00fb5d436e') - def test_rescue_server(self): - """Test rescue server, part of os-rescue.""" - with self.override_role(): - self.servers_client.rescue_server(self.server['id']) - waiters.wait_for_server_status( - self.servers_client, self.server['id'], 'RESCUE') - - @decorators.idempotent_id('ac2d956f-d6a3-4184-b814-b44d05c9574c') - @utils.requires_ext(extension='os-rescue', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-rescue"]) - def test_unrescue_server(self): - """Test unrescue server, part of os-rescue.""" - self.servers_client.rescue_server(self.server['id']) - waiters.wait_for_server_status( - self.servers_client, self.server['id'], 'RESCUE') - - with self.override_role(): - self.servers_client.unrescue_server(self.server['id']) - waiters.wait_for_server_status( - self.servers_client, self.server['id'], 'ACTIVE') - - @utils.requires_ext(extension='os-server-diagnostics', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-diagnostics"]) - @decorators.idempotent_id('5dabfcc4-bedb-417b-8247-b3ee7c5c0f3e') - def test_show_server_diagnostics(self): - """Test show server diagnostics, part of os-server-diagnostics.""" - with self.override_role(): - self.servers_client.show_server_diagnostics(self.server['id']) - - @utils.requires_ext(extension='os-server-password', service='compute') - @decorators.idempotent_id('aaf43f78-c178-4581-ac18-14afd3f1f6ba') - @rbac_rule_validation.action( - service="nova", - rules=[_SERVER_PASSWORD_CLEAR]) - def test_delete_server_password(self): - """Test delete server password, part of os-server-password.""" - with self.override_role(): - self.servers_client.delete_password(self.server['id']) - - @utils.requires_ext(extension='os-server-password', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=[_SERVER_PASSWORD_SHOW]) - @decorators.idempotent_id('f677971a-7d20-493c-977f-6ff0a74b5b2c') - def test_get_server_password(self): - """Test show server password, part of os-server-password.""" - with self.override_role(): - self.servers_client.show_password(self.server['id']) - - @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein, - "This API extension policy was removed in Stein") - @utils.requires_ext(extension='OS-SRV-USG', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-usage"]) - @decorators.idempotent_id('f0437ead-b9fb-462a-9f3d-ce53fac9d57a') - def test_show_server_usage(self): - """Test show server usage, part of os-server-usage. - - TODO(felipemonteiro): Once multiple policy testing is supported, this - test should also check for additional policies mentioned here: - https://git.openstack.org/cgit/openstack/nova/tree/nova/policies/server_usage.py?h=17.0.0 - """ - expected_attrs = ('OS-SRV-USG:launched_at', - 'OS-SRV-USG:terminated_at') - - with self.override_role(): - body = self.servers_client.show_server(self.server['id'])['server'] - for expected_attr in expected_attrs: - if expected_attr not in body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @utils.requires_ext(extension='os-simple-tenant-usage', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-simple-tenant-usage:list"]) - @decorators.idempotent_id('2aef094f-0452-4df6-a66a-0ec22a92b16e') - def test_list_simple_tenant_usages(self): - """Test list tenant usages, part of os-simple-tenant-usage.""" - with self.override_role(): - self.tenant_usages_client.list_tenant_usages() - - @utils.requires_ext(extension='os-simple-tenant-usage', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-simple-tenant-usage:show"]) - @decorators.idempotent_id('fe7eacda-15c4-4bf7-93ef-1091c4546a9d') - def test_show_simple_tenant_usage(self): - """Test show tenant usage, part of os-simple-tenant-usage.""" - tenant_id = self.os_primary.credentials.tenant_id - - with self.override_role(): - self.tenant_usages_client.show_tenant_usage(tenant_id=tenant_id) - - @testtools.skipUnless(CONF.compute_feature_enabled.suspend, - "Suspend compute feature is not available.") - @decorators.idempotent_id('b775930f-237c-431c-83ae-d33ed1b9700b') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-suspend-server:suspend"]) - def test_suspend_server(self): - """Test suspend server, part of os-suspend-server.""" - with self.override_role(): - self.servers_client.suspend_server(self.server['id']) - self.addCleanup(self.servers_client.resume_server, self.server['id']) - waiters.wait_for_server_status( - self.servers_client, self.server['id'], 'SUSPENDED') - - @testtools.skipUnless(CONF.compute_feature_enabled.suspend, - "Suspend compute feature is not available.") - @decorators.idempotent_id('4d90bd02-11f8-45b1-a8a1-534665584675') - @rbac_rule_validation.action( - service="nova", - rules=["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'], 'SUSPENDED') - - with self.override_role(): - self.servers_client.resume_server(self.server['id']) - waiters.wait_for_server_status( - self.servers_client, self.server['id'], 'ACTIVE') - - -class MiscPolicyActionsNetworkRbacTest(rbac_base.BaseV2ComputeRbacTest): - """Test multiple policy actions that require a server to be created. - - Only applies to: - * policy "families" that require server creation - * small policy "families" -- i.e. containing one to three policies - * tests that require network resources - """ - - @classmethod - def skip_checks(cls): - super(MiscPolicyActionsNetworkRbacTest, cls).skip_checks() - # All tests below require Neutron availability. - if not CONF.service_available.neutron: - raise cls.skipException( - '%s skipped as Neutron is required' % cls.__name__) - - @classmethod - def setup_clients(cls): - super(MiscPolicyActionsNetworkRbacTest, cls).setup_clients() - cls.servers_admin_client = cls.os_admin.servers_client - - @classmethod - def setup_credentials(cls): - cls.prepare_instance_network() - super(MiscPolicyActionsNetworkRbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - def _cleanup_ports(network_id): - ports = cls.ports_client.list_ports(network_id=network_id)['ports'] - for port in ports: - test_utils.call_and_ignore_notfound_exc( - cls.ports_client.delete_port, - port['id']) - - super(MiscPolicyActionsNetworkRbacTest, cls).resource_setup() - cls.server = cls.create_test_server(wait_until='ACTIVE') - - # Create network the interface will be attached to - network_name = data_utils.rand_name(cls.__name__ + '-network') - post_body = {'name': network_name} - post_body['router:external'] = False - post_body['shared'] = True - post_body['port_security_enabled'] = True - cls.network = \ - cls.networks_client.create_network(**post_body)['network'] - cls.addClassResourceCleanup( - cls.networks_client.delete_network, - cls.network['id']) - - # Create subnet for network - cls.cidr = netaddr.IPNetwork(CONF.network.project_network_cidr) - cls.subnet = cls.subnets_client.create_subnet( - network_id=cls.network['id'], - cidr=cls.cidr, - ip_version=4)['subnet'] - cls.addClassResourceCleanup( - cls.subnets_client.delete_subnet, - cls.subnet['id']) - - # ports on the network need to be deleted before the network can - # be deleted - cls.addClassResourceCleanup(_cleanup_ports, cls.network['id']) - - def _delete_and_wait_for_interface_detach( - self, server_id, port_id): - req_id = self.interfaces_client.delete_interface( - server_id, port_id - ).response['x-openstack-request-id'] - waiters.wait_for_interface_detach( - self.servers_admin_client, server_id, port_id, req_id) - - def _delete_and_wait_for_interface_detach_ignore_timeout( - self, server_id, port_id): - try: - self._delete_and_wait_for_interface_detach( - server_id, port_id) - except lib_exc.TimeoutException: - pass - - def _attach_interface_to_server(self): - network_id = self.network['id'] - interface = self.interfaces_client.create_interface( - self.server['id'], net_id=network_id)['interfaceAttachment'] - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self._delete_and_wait_for_interface_detach_ignore_timeout, - self.server['id'], interface['port_id']) - waiters.wait_for_interface_status( - self.interfaces_client, self.server['id'], - interface['port_id'], 'ACTIVE') - return interface - - @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach, - "Interface attachment is not available.") - @utils.requires_ext(extension='os-attach-interfaces', service='compute') - @decorators.idempotent_id('ddf53cb6-4a0a-4e5a-91e3-6c32aaa3b9b6') - @rbac_rule_validation.action( - service="nova", - rules=[_ATTACH_INTERFACES_LIST]) - def test_list_interfaces(self): - """Test list interfaces, part of os-attach-interfaces.""" - with self.override_role(): - self.interfaces_client.list_interfaces(self.server['id']) - - @decorators.idempotent_id('1b9cf7db-dc50-48a2-8eb9-8c25af5e934a') - @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach, - "Interface attachment is not available.") - @utils.requires_ext(extension='os-attach-interfaces', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=[_ATTACH_INTERFACES_SHOW]) - def test_show_interface(self): - """Test show interfaces, part of os-attach-interfaces.""" - interface = self._attach_interface_to_server() - with self.override_role(): - self.interfaces_client.show_interface( - self.server['id'], interface['port_id']) - - @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach, - "Interface attachment is not available.") - @utils.requires_ext(extension='os-attach-interfaces', service='compute') - @decorators.idempotent_id('d2d3a24d-4738-4bce-a287-36d664746cde') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-attach-interfaces:create"]) - def test_create_interface(self): - """Test create interface, part of os-attach-interfaces.""" - network_id = self.network['id'] - with self.override_role(): - interface = self.interfaces_client.create_interface( - self.server['id'], net_id=network_id)['interfaceAttachment'] - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self._delete_and_wait_for_interface_detach_ignore_timeout, - self.server['id'], interface['port_id']) - waiters.wait_for_interface_status( - self.interfaces_client, self.server['id'], - interface['port_id'], 'ACTIVE') - - @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach, - "Interface attachment is not available.") - @utils.requires_ext(extension='os-attach-interfaces', service='compute') - @decorators.idempotent_id('55b05692-ed44-4608-a84c-cd4219c82799') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-attach-interfaces:delete"]) - def test_delete_interface(self): - """Test delete interface, part of os-attach-interfaces.""" - interface = self._attach_interface_to_server() - - with self.override_role(): - req_id = self.interfaces_client.delete_interface( - self.server['id'], interface['port_id']) - try: - # interface may be not found - we need to ignore that - waiters.wait_for_interface_detach( - self.servers_admin_client, self.server['id'], - interface['port_id'], req_id) - except lib_exc.NotFound: - pass - - @decorators.idempotent_id('6886d360-0d86-4760-b1a3-882d81fbebcc') - @utils.requires_ext(extension='os-ips', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:ips:index"]) - def test_list_addresses(self): - """Test list server addresses, part of ips policy family.""" - with self.override_role(): - self.servers_client.list_addresses(self.server['id']) - - @decorators.idempotent_id('fa43e7e5-0db9-48eb-9c6b-c11eb766b8e4') - @utils.requires_ext(extension='os-ips', service='compute') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:ips:show"]) - def test_list_addresses_by_network(self): - """Test list server addresses by network, part of ips policy family.""" - addresses = self.servers_client.list_addresses(self.server['id'])[ - 'addresses'] - address = next(iter(addresses)) - - with self.override_role(): - self.servers_client.list_addresses_by_network( - self.server['id'], address) - - @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach, - "Interface attachment is not available.") - @utils.requires_ext(extension='os-multinic', service='compute') - @rbac_rule_validation.action( - service="nova", rules=[_MULTINIC_ADD]) - @decorators.idempotent_id('bd3e2c74-130a-40f0-8085-124d93fe67da') - def test_add_fixed_ip(self): - """Test add fixed ip to server network, part of os-multinic.""" - interfaces = (self.interfaces_client.list_interfaces(self.server['id']) - ['interfaceAttachments']) - if interfaces: - network_id = interfaces[0]['net_id'] - else: - interface = self.interfaces_client.create_interface( - self.server['id'])['interfaceAttachment'] - network_id = interface['net_id'] - self.addCleanup( - self._delete_and_wait_for_interface_detach, - self.server['id'], interface['port_id']) - - with self.override_role(): - self.servers_client.add_fixed_ip(self.server['id'], - networkId=network_id) - # Get the Fixed IP from server. - server_detail = self.servers_client.show_server( - self.server['id'])['server'] - fixed_ip = None - for ip_set in server_detail['addresses']: - for ip in server_detail['addresses'][ip_set]: - if ip['OS-EXT-IPS:type'] == 'fixed': - fixed_ip = ip['addr'] - break - if fixed_ip is not None: - break - # Remove the fixed IP from server. - # TODO(gmann): separate the remve fixded ip test as it has - # separate policy now. - # self.servers_client.remove_fixed_ip(self.server['id'], - # address=fixed_ip) diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py deleted file mode 100644 index 8592e127..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py +++ /dev/null @@ -1,204 +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 oslo_log import log - -from tempest.common import utils -from tempest.common import waiters -from tempest import config -from tempest.lib.common import fixed_network -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base as base - -CONF = config.CONF -LOG = log.getLogger(__name__) - - -class ComputeServersRbacTest(base.BaseV2ComputeRbacTest): - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ComputeServersRbacTest, cls).setup_credentials() - - @classmethod - def setup_clients(cls): - super(ComputeServersRbacTest, cls).setup_clients() - cls.networks_client = cls.os_primary.networks_client - cls.ports_client = cls.os_primary.ports_client - cls.subnets_client = cls.os_primary.subnets_client - - @classmethod - def resource_setup(cls): - super(ComputeServersRbacTest, cls).resource_setup() - cls.server = cls.create_test_server(wait_until='ACTIVE') - cls.tenant_network = fixed_network.set_networks_kwarg( - cls.get_tenant_network() - ) - - def _get_instance_config(self): - instance_params = { - 'name': data_utils.rand_name(self.__class__.__name__ + '-Server'), - 'flavorRef': CONF.compute.flavor_ref, - 'imageRef': CONF.compute.image_ref - } - if 'networks' in self.tenant_network: - instance_params['networks'] = self.tenant_network['networks'] - - return instance_params - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:create"]) - @decorators.idempotent_id('4f34c73a-6ddc-4677-976f-71320fa855bd') - def test_create_server(self): - with self.override_role(): - instance_params = self._get_instance_config() - server = self.servers_client.create_server( - **instance_params - )['server'] - self.addCleanup(waiters.wait_for_server_termination, - self.servers_client, server['id']) - self.addCleanup(self.servers_client.delete_server, server['id']) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:create:forced_host"]) - @decorators.idempotent_id('0ae3c401-52ab-41bc-ab96-c598a65d9ae5') - def test_create_server_forced_host(self): - # Retrieve 'nova' zone host information from availiability_zone_list - zones = self.availability_zone_client.list_availability_zones( - detail=True)['availabilityZoneInfo'] - hosts = [zone['hosts'] for zone in zones if zone['zoneName'] == 'nova'] - - # We just need any host out of the hosts list to build the - # availability_zone attribute. So, picking the first one is fine. - # The first key of the dictionary specifies the host name. - host = list(hosts[0].keys())[0] - availability_zone = 'nova:' + host - with self.override_role(): - instance_params = self._get_instance_config() - instance_params['availability_zone'] = availability_zone - server = self.servers_client.create_server( - **instance_params - )['server'] - self.addCleanup(waiters.wait_for_server_termination, - self.servers_client, server['id']) - self.addCleanup(self.servers_client.delete_server, server['id']) - - @utils.services('volume') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:create:attach_volume"]) - @decorators.idempotent_id('eeddac5e-15aa-454f-838d-db608aae4dd8') - def test_create_server_attach_volume(self): - # To create a bootable volume, the UUID of the image from which - # to create the volume must be included as the imageRef attribute in - # the request body. - volume_id = self.create_volume( - imageRef=CONF.compute.image_ref, - size=CONF.volume.volume_size)['id'] - - bd_map_v2 = [{'uuid': volume_id, - 'source_type': 'volume', - 'destination_type': 'volume', - 'boot_index': 0, - 'delete_on_termination': False}] - with self.override_role(): - instance_params = self._get_instance_config() - # Use imageRef='' to avoid using the default image in tempest.conf. - instance_params['imageRef'] = '' - instance_params['block_device_mapping_v2'] = bd_map_v2 - server = self.servers_client.create_server( - **instance_params - )['server'] - waiters.wait_for_server_status( - self.servers_client, server['id'], 'ACTIVE') - # Delete the server and wait for the volume to become available to - # avoid clean up errors. - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - waiters.wait_for_volume_resource_status, - self.volumes_client, volume_id, 'available') - self.addCleanup(waiters.wait_for_server_termination, - self.servers_client, server['id']) - self.addCleanup(self.delete_server, server['id']) - - @utils.services('network') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:create:attach_network"]) - @decorators.idempotent_id('b44cd4ff-50a4-42ce-ada3-724e213cd540') - def test_create_server_attach_network(self): - def _create_network_resources(): - # Create network - network_name = data_utils.rand_name( - self.__class__.__name__ + '-network') - - network = self.networks_client.create_network( - name=network_name, port_security_enabled=True)['network'] - self.addCleanup(self.networks_client.delete_network, network['id']) - - # Create subnet for the network - subnet_name = data_utils.rand_name( - self.__class__.__name__ + '-subnet') - subnet = self.subnets_client.create_subnet( - name=subnet_name, - network_id=network['id'], - cidr=CONF.network.project_network_cidr, - ip_version=4)['subnet'] - self.addCleanup(self.subnets_client.delete_subnet, subnet['id']) - - return network - - network = _create_network_resources() - network_id = {'uuid': network['id']} - - with self.override_role(): - instance_params = self._get_instance_config() - instance_params['networks'] = [network_id] - server = self.servers_client.create_server( - **instance_params - )['server'] - self.addCleanup(waiters.wait_for_server_termination, - self.servers_client, server['id']) - self.addCleanup(self.servers_client.delete_server, server['id']) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:delete"]) - @decorators.idempotent_id('062e3440-e873-4b41-9317-bf6d8be50c12') - def test_delete_server(self): - server = self.create_test_server(wait_until='ACTIVE') - - with self.override_role(): - self.servers_client.delete_server(server['id']) - waiters.wait_for_server_termination( - self.servers_client, server['id']) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:servers:update"]) - @decorators.idempotent_id('077b17cb-5621-43b9-8adf-5725f0d7a863') - def test_update_server(self): - new_name = data_utils.rand_name(self.__class__.__name__ + '-server') - with self.override_role(): - self.servers_client.update_server(self.server['id'], - name=new_name) - waiters.wait_for_server_status(self.servers_client, - self.server['id'], 'ACTIVE') diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py deleted file mode 100644 index 8a386f66..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py +++ /dev/null @@ -1,103 +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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - - -class ServerTagsRbacTest(rbac_base.BaseV2ComputeRbacTest): - - min_microversion = '2.26' - max_microversion = 'latest' - - @classmethod - def skip_checks(cls): - super(ServerTagsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-server-tags', 'compute'): - msg = "os-server-tags extension is not enabled." - raise cls.skipException(msg) - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ServerTagsRbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(ServerTagsRbacTest, cls).resource_setup() - cls.server = cls.create_test_server(wait_until='ACTIVE') - - def _add_tag_to_server(self): - tag_name = data_utils.rand_name(self.__class__.__name__ + '-tag') - self.servers_client.update_tag(self.server['id'], tag_name) - self.addCleanup(self.servers_client.delete_all_tags, self.server['id']) - return tag_name - - @decorators.idempotent_id('99e73dd3-adec-4044-b46c-84bdded35d09') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-tags:index"]) - def test_list_tags(self): - with self.override_role(): - self.servers_client.list_tags(self.server['id']) - - @decorators.idempotent_id('9297c99e-94eb-429f-93cf-9b1838e33622') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-tags:show"]) - def test_check_tag_existence(self): - tag_name = self._add_tag_to_server() - with self.override_role(): - self.servers_client.check_tag_existence(self.server['id'], - tag_name) - - @decorators.idempotent_id('0d84ee94-d3ca-4635-8edf-b7f67ab8e4a3') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-tags:update"]) - def test_update_tag(self): - with self.override_role(): - self._add_tag_to_server() - - @decorators.idempotent_id('115c2694-00aa-41ee-99f6-9eab4040c182') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-tags:delete"]) - def test_delete_tag(self): - tag_name = self._add_tag_to_server() - with self.override_role(): - self.servers_client.delete_tag(self.server['id'], tag_name) - - @decorators.idempotent_id('a8e19b87-6580-4bc8-9933-e62561ff667d') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-tags:update_all"]) - def test_update_all_tags(self): - new_tag_name = data_utils.rand_name(self.__class__.__name__ + '-tag') - with self.override_role(): - self.servers_client.update_all_tags(self.server['id'], - [new_tag_name]) - - @decorators.idempotent_id('89d51936-e333-42f9-a045-132a4865ba1a') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-server-tags:delete_all"]) - def test_delete_all_tags(self): - with self.override_role(): - self.servers_client.delete_all_tags(self.server['id']) diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_volume_attachments_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_volume_attachments_rbac.py deleted file mode 100644 index 946bf3f3..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_server_volume_attachments_rbac.py +++ /dev/null @@ -1,221 +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. - -import time - -from oslo_log import log as logging -import testtools - -from tempest.common import waiters -from tempest import config -from tempest.lib import decorators -from tempest.lib import exceptions as lib_exc - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF -LOG = logging.getLogger(__name__) - - -# FIXME(felipemonteiro): `@decorators.attr(type='slow')` are added to tests -# below to in effect cause the tests to be non-voting in Zuul due to a high -# rate of spurious failures related to volume attachments. This will be -# revisited at a later date. -class ServerVolumeAttachmentRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(ServerVolumeAttachmentRbacTest, cls).setup_credentials() - - @classmethod - def setup_clients(cls): - super(ServerVolumeAttachmentRbacTest, cls).setup_clients() - cls.volumes_client = cls.os_primary.volumes_client_latest - - @classmethod - def skip_checks(cls): - super(ServerVolumeAttachmentRbacTest, cls).skip_checks() - if not CONF.service_available.cinder: - skip_msg = ("%s skipped as Cinder is not available" % cls.__name__) - raise cls.skipException(skip_msg) - - @classmethod - def resource_setup(cls): - super(ServerVolumeAttachmentRbacTest, cls).resource_setup() - cls.server = cls.create_test_server(wait_until='ACTIVE') - cls.volume = cls.create_volume() - - def _detach_volume_and_wait_until_available(self, server, volume): - self.servers_client.detach_volume(server['id'], - volume['id']) - waiters.wait_for_volume_resource_status(self.volumes_client, - volume['id'], 'available') - - def _recreate_volume(self): - try: - # In case detachment failed, update the DB status of the volume - # to avoid error getting thrown when deleting the volume. - self.volumes_client.reset_volume_status( - self.volume['id'], status='available', - attach_status='detached') - waiters.wait_for_volume_resource_status( - self.volumes_client, self.volume['id'], 'available') - # Next, forcibly delete the volume. - self.volumes_client.force_delete_volume(self.volume['id']) - self.volumes_client.wait_for_resource_deletion(self.volume['id']) - except lib_exc.TimeoutException: - LOG.exception('Failed to delete volume %s', self.volume['id']) - # Finally, re-create the volume. - self.__class__.volume = self.create_volume() - - def _restore_volume_status(self): - # Forcibly detach any attachments still attached to the volume. - try: - attachments = self.volumes_client.show_volume( - self.volume['id'])['volume']['attachments'] - if attachments: - # Tests below only ever create one attachment for the volume. - attachment = attachments[0] - self.volumes_client.force_detach_volume( - self.volume['id'], connector=None, - attachment_id=attachment['id']) - waiters.wait_for_volume_resource_status(self.volumes_client, - self.volume['id'], - 'available') - except lib_exc.TimeoutException: - # If all else fails, rebuild the volume. - self._recreate_volume() - - def setUp(self): - super(ServerVolumeAttachmentRbacTest, self).setUp() - self._restore_volume_status() - - def wait_for_server_volume_swap(self, server_id, old_volume_id, - new_volume_id): - """Waits for a server to swap the old volume to a new one.""" - volume_attachments = self.servers_client.list_volume_attachments( - server_id)['volumeAttachments'] - attached_volume_ids = [attachment['volumeId'] - for attachment in volume_attachments] - start = int(time.time()) - - while (old_volume_id in attached_volume_ids) \ - or (new_volume_id not in attached_volume_ids): - time.sleep(self.servers_client.build_interval) - volume_attachments = self.servers_client.list_volume_attachments( - server_id)['volumeAttachments'] - attached_volume_ids = [attachment['volumeId'] - for attachment in volume_attachments] - - if int(time.time()) - start >= self.servers_client.build_timeout: - old_vol_bdm_status = 'in BDM' \ - if old_volume_id in attached_volume_ids else 'not in BDM' - new_vol_bdm_status = 'in BDM' \ - if new_volume_id in attached_volume_ids else 'not in BDM' - message = ('Failed to swap old volume %(old_volume_id)s ' - '(current %(old_vol_bdm_status)s) to new volume ' - '%(new_volume_id)s (current %(new_vol_bdm_status)s)' - ' on server %(server_id)s within the required time ' - '(%(timeout)s s)' % - {'old_volume_id': old_volume_id, - 'old_vol_bdm_status': old_vol_bdm_status, - 'new_volume_id': new_volume_id, - 'new_vol_bdm_status': new_vol_bdm_status, - 'server_id': server_id, - 'timeout': self.servers_client.build_timeout}) - raise lib_exc.TimeoutException(message) - - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-volumes-attachments:index"]) - @decorators.idempotent_id('529b668b-6edb-41d5-8886-d7dbd0614678') - def test_list_volume_attachments(self): - with self.override_role(): - self.servers_client.list_volume_attachments(self.server['id']) - - @decorators.attr(type='slow') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-volumes-attachments:create"]) - @decorators.idempotent_id('21c2c3fd-fbe8-41b1-8ef8-115ec47d54c1') - def test_create_volume_attachment(self): - with self.override_role(): - self.servers_client.attach_volume(self.server['id'], - volumeId=self.volume['id']) - # On teardown detach the volume and wait for it to be available. This - # is so we don't error out when trying to delete the volume during - # teardown. - self.addCleanup(waiters.wait_for_volume_resource_status, - self.volumes_client, self.volume['id'], 'available') - # Ignore 404s on detach in case the server is deleted or the volume - # is already detached. - self.addCleanup(self._detach_volume, self.server, self.volume) - waiters.wait_for_volume_resource_status(self.volumes_client, - self.volume['id'], 'in-use') - - @decorators.attr(type='slow') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-volumes-attachments:show"]) - @decorators.idempotent_id('997df9c2-6e54-47b6-ab74-e4fdb500f385') - def test_show_volume_attachment(self): - attachment = self.attach_volume(self.server, self.volume) - - with self.override_role(): - self.servers_client.show_volume_attachment( - self.server['id'], attachment['id']) - - @decorators.skip_because(bug='2008051', bug_type='storyboard') - @decorators.attr(type='slow') - @testtools.skipUnless(CONF.compute_feature_enabled.swap_volume, - 'In-place swapping of volumes not supported.') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-volumes-attachments:update"]) - @decorators.idempotent_id('bd667186-eca6-4b78-ab6a-3e2fabcb971f') - def test_update_volume_attachment(self): - volume1 = self.volume - volume2 = self.create_volume() - # Attach "volume1" to server - self.attach_volume(self.server, volume1) - - with self.override_role(): - # Swap volume from "volume1" to "volume2" - self.servers_client.update_attached_volume( - self.server['id'], volume1['id'], volumeId=volume2['id']) - self.addCleanup(self._detach_volume_and_wait_until_available, - self.server, volume2) - waiters.wait_for_volume_resource_status(self.volumes_client, - volume1['id'], 'available') - waiters.wait_for_volume_resource_status(self.volumes_client, - volume2['id'], 'in-use') - self.wait_for_server_volume_swap(self.server['id'], volume1['id'], - volume2['id']) - - @decorators.attr(type='slow') - @rbac_rule_validation.action( - service="nova", - rules=["os_compute_api:os-volumes-attachments:delete"]) - @decorators.idempotent_id('12b03e90-d087-46af-9c4d-507d021c4984') - def test_delete_volume_attachment(self): - self.attach_volume(self.server, self.volume) - - with self.override_role(): - self.servers_client.detach_volume(self.server['id'], - self.volume['id']) - waiters.wait_for_volume_resource_status(self.volumes_client, - self.volume['id'], 'available') diff --git a/patrole_tempest_plugin/tests/api/compute/test_services_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_services_rbac.py deleted file mode 100644 index da4923d6..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_services_rbac.py +++ /dev/null @@ -1,46 +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.common import utils -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_nova_policies_ussuri: - _OS_COMPUTE_API_OS_SERVICES = "os_compute_api:os-services:list" -else: - _OS_COMPUTE_API_OS_SERVICES = "os_compute_api:os-services" - - -class ServicesRbacTest(rbac_base.BaseV2ComputeRbacTest): - - @classmethod - def skip_checks(cls): - super(ServicesRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-services', 'compute'): - raise cls.skipException( - '%s skipped as os-services not enabled' % cls.__name__) - - @rbac_rule_validation.action( - service="nova", - rules=[_OS_COMPUTE_API_OS_SERVICES]) - @decorators.idempotent_id('7472261b-9c6d-453a-bcb3-aecaa29ad281') - def test_list_services(self): - with self.override_role(): - self.services_client.list_services()['services'] diff --git a/patrole_tempest_plugin/tests/api/compute/test_tenant_networks_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_tenant_networks_rbac.py deleted file mode 100644 index a71901c1..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_tenant_networks_rbac.py +++ /dev/null @@ -1,65 +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 import config - -from tempest.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_nova_policies_victoria: - _TENANT_NET_LIST = "os_compute_api:os-tenant-networks:list" -else: - _TENANT_NET_LIST = "os_compute_api:os-tenant-networks" - - -class TenantNetworksRbacTest(rbac_base.BaseV2ComputeRbacTest): - - # Tests will fail with a 404 starting from microversion 2.36. - # See the following link for details: - # https://docs.openstack.org/api-ref/compute/#project-networks-os-tenant-networks-deprecated - max_microversion = '2.35' - - @classmethod - def setup_clients(cls): - super(TenantNetworksRbacTest, cls).setup_clients() - cls.tenant_networks_client = cls.os_primary.tenant_networks_client - - @classmethod - def skip_checks(cls): - super(TenantNetworksRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-tenant-networks', 'compute'): - msg = "os-tenant-networks extension not enabled." - raise cls.skipException(msg) - if not CONF.service_available.neutron: - raise cls.skipException( - '%s skipped as Neutron is required' % cls.__name__) - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True) - super(TenantNetworksRbacTest, cls).setup_credentials() - - @decorators.idempotent_id('42b39ba1-14aa-4799-9518-34367d0da67a') - @rbac_rule_validation.action( - service="nova", - rules=[_TENANT_NET_LIST]) - def test_list_show_tenant_networks(self): - with self.override_role(): - self.tenant_networks_client.list_tenant_networks() diff --git a/patrole_tempest_plugin/tests/api/compute/test_volume_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_volume_rbac.py deleted file mode 100644 index 1d1b06a9..00000000 --- a/patrole_tempest_plugin/tests/api/compute/test_volume_rbac.py +++ /dev/null @@ -1,167 +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.common import waiters -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.compute import rbac_base - -from tempest import config - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_nova_policies_victoria: - _VOLUME_LIST = "os_compute_api:os-volumes:list" - _VOLUME_CREATE = "os_compute_api:os-volumes:create" - _VOLUME_SHOW = "os_compute_api:os-volumes:show" - _VOLUME_DELETE = "os_compute_api:os-volumes:delete" - _SNAPSHOT_LIST = "os_compute_api:os-volumes:snapshots:list" - _SNAPSHOT_CREATE = "os_compute_api:os-volumes:snapshots:create" - _SNAPSHOT_SHOW = "os_compute_api:os-volumes:snapshots:show" - _SNAPSHOT_DELETE = "os_compute_api:os-volumes:snapshots:delete" -else: - _VOLUME_LIST = "os_compute_api:os-volumes" - _VOLUME_CREATE = "os_compute_api:os-volumes" - _VOLUME_SHOW = "os_compute_api:os-volumes" - _VOLUME_DELETE = "os_compute_api:os-volumes" - _SNAPSHOT_LIST = "os_compute_api:os-volumes" - _SNAPSHOT_CREATE = "os_compute_api:os-volumes" - _SNAPSHOT_SHOW = "os_compute_api:os-volumes" - _SNAPSHOT_DELETE = "os_compute_api:os-volumes" - - -class VolumeRbacTest(rbac_base.BaseV2ComputeRbacTest): - """RBAC tests for the Nova Volume client.""" - - # These tests will fail with a 404 starting from microversion 2.36. - # For more information, see: - # https://docs.openstack.org/api-ref/compute/#volume-extension-os-volumes-os-snapshots-deprecated - max_microversion = '2.35' - - @classmethod - def skip_checks(cls): - super(VolumeRbacTest, cls).skip_checks() - if not CONF.service_available.cinder: - skip_msg = ("%s skipped as Cinder is not available" % cls.__name__) - raise cls.skipException(skip_msg) - if not CONF.volume_feature_enabled.snapshot: - skip_msg = ("Cinder volume snapshots are disabled") - raise cls.skipException(skip_msg) - - @classmethod - def resource_setup(cls): - super(VolumeRbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - - def _delete_snapshot(self, snapshot_id): - waiters.wait_for_volume_resource_status( - self.snapshots_extensions_client, snapshot_id, - 'available') - self.snapshots_extensions_client.delete_snapshot(snapshot_id) - self.snapshots_extensions_client.wait_for_resource_deletion( - snapshot_id) - - @decorators.idempotent_id('2402013e-a624-43e3-9518-44a5d1dbb32d') - @rbac_rule_validation.action( - service="nova", - rules=[_VOLUME_CREATE]) - def test_create_volume(self): - with self.override_role(): - volume = self.volumes_extensions_client.create_volume( - size=CONF.volume.volume_size)['volume'] - waiters.wait_for_volume_resource_status(self.volumes_client, - volume['id'], 'available') - # Use non-deprecated volumes_client for deletion. - self.addCleanup(self.volumes_client.delete_volume, volume['id']) - - @decorators.idempotent_id('69b3888c-dff2-47b0-9fa4-0672619c9054') - @rbac_rule_validation.action( - service="nova", - rules=[_VOLUME_LIST]) - def test_list_volumes(self): - with self.override_role(): - self.volumes_extensions_client.list_volumes() - - @decorators.idempotent_id('4ba0a820-040f-488b-86bb-be2e920ea12c') - @rbac_rule_validation.action( - service="nova", - rules=[_VOLUME_SHOW]) - def test_show_volume(self): - with self.override_role(): - self.volumes_extensions_client.show_volume(self.volume['id']) - - @decorators.idempotent_id('6e7870f2-1bb2-4b58-96f8-6782071ef327') - @rbac_rule_validation.action( - service="nova", - rules=[_VOLUME_DELETE]) - def test_delete_volume(self): - volume = self.create_volume() - with self.override_role(): - self.volumes_extensions_client.delete_volume(volume['id']) - - @decorators.idempotent_id('0c3eaa4f-69d6-4a13-9dda-19585f36b1c1') - @rbac_rule_validation.action( - service="nova", - rules=[_SNAPSHOT_CREATE]) - def test_create_snapshot(self): - s_name = data_utils.rand_name(self.__class__.__name__ + '-Snapshot') - with self.override_role(): - snapshot = self.snapshots_extensions_client.create_snapshot( - volume_id=self.volume['id'], display_name=s_name)['snapshot'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self._delete_snapshot, snapshot['id']) - - @decorators.idempotent_id('e944e816-416c-11e7-a919-92ebcb67fe33') - @rbac_rule_validation.action( - service="nova", - rules=[_SNAPSHOT_LIST]) - def test_list_snapshots(self): - with self.override_role(): - self.snapshots_extensions_client.list_snapshots() - - @decorators.idempotent_id('19c2e6bd-585b-472f-a8d7-71ea9299c655') - @rbac_rule_validation.action( - service="nova", - rules=[_SNAPSHOT_SHOW]) - def test_show_snapshot(self): - s_name = data_utils.rand_name(self.__class__.__name__ + '-Snapshot') - snapshot = self.snapshots_extensions_client.create_snapshot( - volume_id=self.volume['id'], display_name=s_name)['snapshot'] - self.addCleanup(self._delete_snapshot, snapshot['id']) - - with self.override_role(): - self.snapshots_extensions_client.show_snapshot(snapshot['id']) - - @decorators.idempotent_id('f4f5635c-416c-11e7-a919-92ebcb67fe33') - @rbac_rule_validation.action( - service="nova", - rules=[_SNAPSHOT_DELETE]) - def test_delete_snapshot(self): - s_name = data_utils.rand_name(self.__class__.__name__ + '-Snapshot') - snapshot = self.snapshots_extensions_client.create_snapshot( - volume_id=self.volume['id'], display_name=s_name)['snapshot'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self._delete_snapshot, snapshot['id']) - waiters.wait_for_volume_resource_status( - self.snapshots_extensions_client, snapshot['id'], - 'available') - - with self.override_role(): - self.snapshots_extensions_client.delete_snapshot(snapshot['id']) - self.snapshots_extensions_client.wait_for_resource_deletion( - snapshot['id']) diff --git a/patrole_tempest_plugin/tests/api/identity/__init__.py b/patrole_tempest_plugin/tests/api/identity/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/api/identity/rbac_base.py b/patrole_tempest_plugin/tests/api/identity/rbac_base.py deleted file mode 100644 index aa5cd4bd..00000000 --- a/patrole_tempest_plugin/tests/api/identity/rbac_base.py +++ /dev/null @@ -1,280 +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 oslo_log import log as logging - -from tempest.api.identity import base -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils - -from patrole_tempest_plugin import rbac_utils - -LOG = logging.getLogger(__name__) - - -class BaseIdentityRbacTest(rbac_utils.RbacUtilsMixin, - base.BaseIdentityTest): - - @classmethod - def setup_test_role(cls): - """Set up a test role.""" - name = data_utils.rand_name(cls.__name__ + '-test_role') - role = cls.roles_client.create_role(name=name)['role'] - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.roles_client.delete_role, role['id']) - - return role - - @classmethod - def setup_test_service(cls): - """Setup a test service.""" - name = data_utils.rand_name(cls.__name__ + '-service') - serv_type = data_utils.rand_name('type') - desc = data_utils.rand_name(cls.__name__ + '-description') - - service = cls.services_client.create_service( - name=name, - type=serv_type, - description=desc)['service'] - - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.services_client.delete_service, service['id']) - - return service - - @classmethod - def setup_test_user(cls, password=None, **kwargs): - """Set up a test user.""" - username = data_utils.rand_name(cls.__name__ + '-test_user') - email = username + '@testmail.tm' - - user = cls.users_client.create_user( - name=username, - email=email, - password=password, - **kwargs)['user'] - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.users_client.delete_user, user['id']) - - return user - - -class BaseIdentityV3RbacTest(BaseIdentityRbacTest): - - identity_version = 'v3' - - @classmethod - def setup_clients(cls): - super(BaseIdentityV3RbacTest, cls).setup_clients() - cls.application_credentials_client = \ - cls.os_primary.application_credentials_client - cls.creds_client = cls.os_primary.credentials_client - cls.consumers_client = cls.os_primary.oauth_consumers_client - cls.domains_client = cls.os_primary.domains_client - cls.domain_config_client = cls.os_primary.domain_config_client - cls.endpoints_client = cls.os_primary.endpoints_v3_client - cls.endpoint_filter_client = cls.os_primary.endpoint_filter_client - cls.endpoint_groups_client = cls.os_primary.endpoint_groups_client - cls.groups_client = cls.os_primary.groups_client - cls.identity_client = cls.os_primary.identity_v3_client - cls.oauth_token_client = cls.os_primary.oauth_token_client - cls.projects_client = cls.os_primary.projects_client - cls.project_tags_client = cls.os_primary.project_tags_client - cls.policies_client = cls.os_primary.policies_client - cls.regions_client = cls.os_primary.regions_client - cls.role_assignments_client = cls.os_primary.role_assignments_client - cls.roles_client = cls.os_primary.roles_v3_client - cls.services_client = cls.os_primary.identity_services_v3_client - cls.token_client = cls.os_primary.token_v3_client - cls.trusts_client = cls.os_primary.trusts_client - cls.users_client = cls.os_primary.users_v3_client - - @classmethod - def resource_setup(cls): - super(BaseIdentityV3RbacTest, cls).resource_setup() - cls.credentials = [] - cls.domains = [] - cls.groups = [] - cls.policies = [] - cls.projects = [] - cls.regions = [] - cls.trusts = [] - cls.tokens = [] - - @classmethod - def resource_cleanup(cls): - for credential in cls.credentials: - test_utils.call_and_ignore_notfound_exc( - cls.creds_client.delete_credential, credential['id']) - - # Delete each domain at the end of the test, but each domain must be - # disabled first. - for domain in cls.domains: - test_utils.call_and_ignore_notfound_exc( - cls.domains_client.update_domain, domain['id'], enabled=False) - test_utils.call_and_ignore_notfound_exc( - cls.domains_client.delete_domain, domain['id']) - - for group in cls.groups: - test_utils.call_and_ignore_notfound_exc( - cls.groups_client.delete_group, group['id']) - - for policy in cls.policies: - test_utils.call_and_ignore_notfound_exc( - cls.policies_client.delete_policy, policy['id']) - - for project in cls.projects: - test_utils.call_and_ignore_notfound_exc( - cls.projects_client.delete_project, project['id']) - - for region in cls.regions: - test_utils.call_and_ignore_notfound_exc( - cls.regions_client.delete_region, region['id']) - - for trust in cls.trusts: - test_utils.call_and_ignore_notfound_exc( - cls.trusts_client.delete_trust, trust['id']) - - for token in cls.tokens: - test_utils.call_and_ignore_notfound_exc( - cls.identity_client.delete_token, token) - - super(BaseIdentityV3RbacTest, cls).resource_cleanup() - - @classmethod - def setup_test_endpoint(cls, service=None): - """Creates a service and an endpoint for test.""" - interface = 'public' - url = data_utils.rand_url() - region_name = data_utils.rand_name( - cls.__name__ + '-region') - # Endpoint creation requires a service - if service is None: - service = cls.setup_test_service() - params = { - 'service_id': service['id'], - 'region': region_name, - 'interface': interface, - 'url': url - } - - endpoint = cls.endpoints_client.create_endpoint(**params)['endpoint'] - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.regions_client.delete_region, endpoint['region']) - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.endpoints_client.delete_endpoint, endpoint['id']) - - return endpoint - - @classmethod - def setup_test_credential(cls, user=None): - """Creates a credential for test.""" - keys = [data_utils.rand_uuid_hex(), - data_utils.rand_uuid_hex()] - blob = '{"access": "%s", "secret": "%s"}' % (keys[0], keys[1]) - - credential = cls.creds_client.create_credential( - user_id=user['id'], - project_id=user['project_id'], - blob=blob, - type='ec2')['credential'] - cls.credentials.append(credential) - - return credential - - @classmethod - def setup_test_domain(cls): - """Set up a test domain.""" - domain = cls.domains_client.create_domain( - name=data_utils.rand_name(cls.__name__), - description=data_utils.rand_name( - cls.__name__ + '-desc'))['domain'] - cls.domains.append(domain) - - return domain - - @classmethod - def setup_test_group(cls): - """Creates a group for test.""" - name = data_utils.rand_name(cls.__name__ + '-test_group') - group = cls.groups_client.create_group(name=name)['group'] - cls.groups.append(group) - - return group - - @classmethod - def setup_test_policy(cls): - """Creates a policy for test.""" - blob = data_utils.rand_name(cls.__name__ + '-test_blob') - policy_type = data_utils.rand_name( - cls.__name__ + '-policy_type') - - policy = cls.policies_client.create_policy( - blob=blob, - policy=policy_type, - type="application/json")['policy'] - cls.policies.append(policy) - - return policy - - @classmethod - def setup_test_project(cls): - """Set up a test project.""" - project = cls.projects_client.create_project( - name=data_utils.rand_name( - cls.__name__), - description=data_utils.rand_name( - cls.__name__ + '-desc'))['project'] - cls.projects.append(project) - - return project - - @classmethod - def setup_test_region(cls): - """Creates a region for test.""" - description = data_utils.rand_name( - cls.__name__ + '-test_region_desc') - id = data_utils.rand_name(cls.__name__) - - region = cls.regions_client.create_region( - id=id, - description=description)['region'] - cls.regions.append(region) - - return region - - @classmethod - def setup_test_trust(cls, trustee_user_id, trustor_user_id, **kwargs): - """Setup a test trust.""" - trust = cls.trusts_client.create_trust( - trustee_user_id=trustee_user_id, trustor_user_id=trustor_user_id, - impersonation=False, **kwargs)['trust'] - cls.trusts.append(trust) - - return trust - - @classmethod - def setup_test_token(cls, user_id, password): - """Set up a test token.""" - token = cls.token_client.auth(user_id=user_id, - password=password).response - token_id = token['x-subject-token'] - cls.tokens.append(token_id) - return token_id diff --git a/patrole_tempest_plugin/tests/api/identity/v3/__init__.py b/patrole_tempest_plugin/tests/api/identity/v3/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_application_credentials_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_application_credentials_rbac.py deleted file mode 100644 index 2d9e3116..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_application_credentials_rbac.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright 2018 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 import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -CONF = config.CONF - - -class ApplicationCredentialsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @classmethod - def skip_checks(cls): - super(ApplicationCredentialsV3RbacTest, cls).skip_checks() - if not CONF.identity_feature_enabled.application_credentials: - raise cls.skipException("Application credentials are not available" - " in this environment") - - @classmethod - def resource_setup(cls): - super(ApplicationCredentialsV3RbacTest, cls).resource_setup() - cls.user_id = cls.os_primary.credentials.user_id - - def _create_application_credential(self, name=None, **kwargs): - name = name or data_utils.rand_name('application_credential') - application_credential = ( - self.application_credentials_client.create_application_credential( - self.user_id, name=name, **kwargs))['application_credential'] - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.application_credentials_client.delete_application_credential, - self.user_id, - application_credential['id']) - return application_credential - - @decorators.idempotent_id('b53bee14-e9df-4929-b257-6def76c12e4d') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:create_application_credential"]) - def test_create_application_credential(self): - with self.override_role(): - self._create_application_credential() - - @decorators.idempotent_id('58b3c3a0-5ad0-44f7-8da7-0736f71f7168') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:list_application_credentials"]) - def test_list_application_credentials(self): - with self.override_role(): - self.application_credentials_client.list_application_credentials( - user_id=self.user_id) - - @decorators.idempotent_id('d7b13968-a8a6-47fd-8e1d-7cc7f565c7f8') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:get_application_credential"]) - def test_show_application_credential(self): - app_cred = self._create_application_credential() - with self.override_role(): - self.application_credentials_client.show_application_credential( - user_id=self.user_id, application_credential_id=app_cred['id']) - - @decorators.idempotent_id('521b7c0f-1dd5-47a6-ae95-95c0323d7735') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:delete_application_credential"]) - def test_delete_application_credential(self): - app_cred = self._create_application_credential() - with self.override_role(): - self.application_credentials_client.delete_application_credential( - user_id=self.user_id, application_credential_id=app_cred['id']) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_auth_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_auth_rbac.py deleted file mode 100644 index 3cfc6709..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_auth_rbac.py +++ /dev/null @@ -1,45 +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 patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityAuthV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - """Tests the APIs that enforce the auth policy actions. - - For more information about the auth policy actions, see: - https://git.openstack.org/cgit/openstack/keystone/tree/keystone/common/policies/auth.py - """ - - # TODO(felipemonteiro): Add tests for identity:get_auth_catalog - # once the endpoints are implemented in Tempest's - # identity v3 client. - - @decorators.idempotent_id('2a9fbf7f-6feb-4161-ae4b-faf7d6421b1a') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_auth_projects"]) - def test_list_auth_projects(self): - with self.override_role(): - self.identity_client.list_auth_projects() - - @decorators.idempotent_id('6a40af0d-7265-4657-b6b2-87a2828e263e') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_auth_domains"]) - def test_list_auth_domain(self): - with self.override_role(): - self.identity_client.list_auth_domains() diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_credentials_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_credentials_rbac.py deleted file mode 100644 index aa77aa3c..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_credentials_rbac.py +++ /dev/null @@ -1,96 +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. - -import testtools - -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - -CONF = config.CONF - - -@testtools.skipIf( - CONF.policy_feature_enabled.removed_keystone_policies_stein, - "This policy is unavailable in Stein so cannot be tested.") -class IdentityCredentialsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - def _create_user_project_and_credential(self): - project = self.setup_test_project() - user = self.setup_test_user(project_id=project['id']) - credential = self.setup_test_credential(user=user) - return credential - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_credential"]) - @decorators.idempotent_id('c1ab6d34-c59f-4ae1-bae9-bb3c1089b48e') - def test_create_credential(self): - project = self.setup_test_project() - user = self.setup_test_user(project_id=project['id']) - with self.override_role(): - self.setup_test_credential(user=user) - - @testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source, - 'Skipped because environment has an immutable user ' - 'source and solely provides read-only access to users.') - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_credential"]) - @decorators.idempotent_id('cfb05ce3-bffb-496e-a3c2-9515d730da63') - def test_update_credential(self): - credential = self._create_user_project_and_credential() - new_keys = [data_utils.rand_uuid_hex(), - data_utils.rand_uuid_hex()] - - with self.override_role(): - self.creds_client.update_credential( - credential['id'], - credential=credential, - access_key=new_keys[0], - secret_key=new_keys[1], - project_id=credential['project_id']) - - @testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source, - 'Skipped because environment has an immutable user ' - 'source and solely provides read-only access to users.') - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_credential"]) - @decorators.idempotent_id('87ab42af-8d41-401b-90df-21e72919fcde') - def test_delete_credential(self): - credential = self._create_user_project_and_credential() - - with self.override_role(): - self.creds_client.delete_credential(credential['id']) - - @testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source, - 'Skipped because environment has an immutable user ' - 'source and solely provides read-only access to users.') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_credential"]) - @decorators.idempotent_id('1b6eeae6-f1e8-4cdf-8903-1c002b1fc271') - def test_show_credential(self): - credential = self._create_user_project_and_credential() - - with self.override_role(): - self.creds_client.show_credential(credential['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_credentials"]) - @decorators.idempotent_id('3de303e2-12a7-4811-805a-f18906472038') - def test_list_credentials(self): - with self.override_role(): - self.creds_client.list_credentials() diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_domain_configuration_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_domain_configuration_rbac.py deleted file mode 100644 index 821b942d..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_domain_configuration_rbac.py +++ /dev/null @@ -1,164 +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 import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - -CONF = config.CONF - - -class DomainConfigurationV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - """RBAC tests for domain configuration client. - - Provides coverage for the following policy actions: - https://git.openstack.org/cgit/openstack/keystone/tree/keystone/common/policies/domain_config.py - """ - - identity = {"driver": "ldap"} - ldap = {"url": "ldap://myldap.com:389/", - "user_tree_dn": "ou=Users,dc=my_new_root,dc=org"} - - @classmethod - def resource_setup(cls): - super(DomainConfigurationV3RbacTest, cls).resource_setup() - cls.domain_id = cls.setup_test_domain()['id'] - - def setUp(self): - super(DomainConfigurationV3RbacTest, self).setUp() - self._create_domain_config(self.domain_id) - - def _create_domain_config(self, domain_id): - domain_config = self.domain_config_client.create_domain_config( - domain_id, identity=self.identity, ldap=self.ldap)['config'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.domain_config_client.delete_domain_config, - domain_id) - return domain_config - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_domain_config"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd115') - def test_create_domain_config(self): - with self.override_role(): - self._create_domain_config(self.domain_id) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_domain_config"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd118') - def test_show_domain_config(self): - with self.override_role(): - self.domain_config_client.show_domain_config(self.domain_id) - - @decorators.idempotent_id('1b539f95-4991-4e09-960f-fa771e1007d7') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_domain_config"]) - def test_show_domain_group_config(self): - with self.override_role(): - self.domain_config_client.show_domain_group_config( - self.domain_id, 'identity') - - @decorators.idempotent_id('590c774d-a294-44f8-866e-aac9f4ab3809') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_domain_config"]) - def test_show_domain_group_option_config(self): - with self.override_role(): - self.domain_config_client.show_domain_group_option_config( - self.domain_id, 'identity', 'driver') - - @decorators.idempotent_id('21053885-1ce3-4167-b5e3-e470253481da') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:get_security_compliance_domain_config"]) - def test_show_security_compliance_domain_config(self): - # The "security_compliance" group can only be shown for the default - # domain. - with self.override_role(): - self.domain_config_client.show_domain_group_config( - CONF.identity.default_domain_id, 'security_compliance') - - @decorators.idempotent_id('d1addd10-9ae4-4360-9961-47324fd22f23') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_domain_config_default"]) - def test_show_default_config_settings(self): - with self.override_role(): - self.domain_config_client.show_default_config_settings() - - @decorators.idempotent_id('63183377-251f-4622-81f0-6b58a8a285c9') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_domain_config_default"]) - def test_show_default_group_config(self): - with self.override_role(): - self.domain_config_client.show_default_group_config('identity') - - @decorators.idempotent_id('6440e9c1-e8da-474d-9118-89996fffe5f8') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_domain_config_default"]) - def test_show_default_group_option(self): - with self.override_role(): - self.domain_config_client.show_default_group_option('identity', - 'driver') - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_domain_config"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd116') - def test_update_domain_config(self): - updated_config = {'ldap': {'url': data_utils.rand_url()}} - with self.override_role(): - self.domain_config_client.update_domain_config( - self.domain_id, **updated_config) - - @decorators.idempotent_id('6e32bf96-dbe9-4ac8-b814-0e79fa948285') - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_domain_config"]) - def test_update_domain_group_config(self): - with self.override_role(): - self.domain_config_client.update_domain_group_config( - self.domain_id, 'identity', identity=self.identity) - - @decorators.idempotent_id('d2c510da-a077-4c67-9522-27745ef2812b') - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_domain_config"]) - def test_update_domain_group_option_config(self): - with self.override_role(): - self.domain_config_client.update_domain_group_option_config( - self.domain_id, 'identity', 'driver', driver='ldap') - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_domain_config"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd117') - def test_delete_domain_config(self): - with self.override_role(): - self.domain_config_client.delete_domain_config(self.domain_id) - - @decorators.idempotent_id('f479694b-df02-4d5a-88b6-c8b52f9341eb') - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_domain_config"]) - def test_delete_domain_group_config(self): - with self.override_role(): - self.domain_config_client.delete_domain_group_config( - self.domain_id, 'identity') - - @decorators.idempotent_id('f594bde3-31c9-414f-922d-0ddafdc0ca40') - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_domain_config"]) - def test_delete_domain_group_option_config(self): - with self.override_role(): - self.domain_config_client.delete_domain_group_option_config( - self.domain_id, 'identity', 'driver') diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_domains_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_domains_rbac.py deleted file mode 100644 index 2ad50cf9..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_domains_rbac.py +++ /dev/null @@ -1,69 +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.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityDomainsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_domain"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd110') - def test_create_domain(self): - with self.override_role(): - self.setup_test_domain() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_domain"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd111') - def test_update_domain(self): - domain = self.setup_test_domain() - new_domain_name = data_utils.rand_name( - self.__class__.__name__) - with self.override_role(): - self.domains_client.update_domain(domain['id'], - domain=domain, - name=new_domain_name) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_domain"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd112') - def test_delete_domain(self): - domain = self.setup_test_domain() - # A domain must be deactivated to be deleted - self.domains_client.update_domain(domain['id'], - domain=domain, - enabled=False) - with self.override_role(): - self.domains_client.delete_domain(domain['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_domain"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd113') - def test_show_domain(self): - domain = self.setup_test_domain() - with self.override_role(): - self.domains_client.show_domain(domain['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_domains"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd114') - def test_list_domains(self): - with self.override_role(): - self.domains_client.list_domains() diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_endpoints_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_endpoints_rbac.py deleted file mode 100644 index 5554b737..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_endpoints_rbac.py +++ /dev/null @@ -1,68 +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.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityEndpointsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_endpoint"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd127') - def test_create_endpoint(self): - service = self.setup_test_service() - with self.override_role(): - self.setup_test_endpoint(service=service) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_endpoint"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd128') - def test_update_endpoint(self): - endpoint = self.setup_test_endpoint() - new_url = data_utils.rand_url() - - with self.override_role(): - self.endpoints_client.update_endpoint( - endpoint["id"], - url=new_url) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_endpoint"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd129') - def test_delete_endpoint(self): - endpoint = self.setup_test_endpoint() - - with self.override_role(): - self.endpoints_client.delete_endpoint(endpoint['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_endpoint"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd130') - def test_show_endpoint(self): - endpoint = self.setup_test_endpoint() - - with self.override_role(): - self.endpoints_client.show_endpoint(endpoint['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_endpoints"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd131') - def test_list_endpoints(self): - with self.override_role(): - self.endpoints_client.list_endpoints() diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_ep_filter_groups_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_ep_filter_groups_rbac.py deleted file mode 100644 index 48a4e584..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_ep_filter_groups_rbac.py +++ /dev/null @@ -1,109 +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.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class EndpointFilterGroupsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - interface = 'public' - - @classmethod - def resource_setup(cls): - super(EndpointFilterGroupsV3RbacTest, cls).resource_setup() - cls.service_id = cls.setup_test_service()['id'] - - def setUp(self): - super(EndpointFilterGroupsV3RbacTest, self).setUp() - self.endpoint_group_id = self._create_endpoint_group() - - def _create_endpoint_group(self, ignore_not_found=False): - # Create an endpoint group - ep_group_name = data_utils.rand_name( - self.__class__.__name__ + '-EPFilterGroup') - filters = { - 'filters': { - 'interface': self.interface, - 'service_id': self.service_id - } - } - endpoint_group = self.endpoint_groups_client.create_endpoint_group( - name=ep_group_name, **filters)['endpoint_group'] - - if ignore_not_found: - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.endpoint_groups_client.delete_endpoint_group, - endpoint_group['id']) - else: - self.addCleanup(self.endpoint_groups_client.delete_endpoint_group, - endpoint_group['id']) - - return endpoint_group['id'] - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_endpoint_group"]) - @decorators.idempotent_id('b4765906-52ec-477b-b441-a8508ced68e3') - def test_create_endpoint_group(self): - with self.override_role(): - self._create_endpoint_group(ignore_not_found=True) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_endpoint_groups"]) - @decorators.idempotent_id('089aa3a7-ba1f-4f70-a1cf-f298a845058a') - def test_list_endpoint_groups(self): - with self.override_role(): - self.endpoint_groups_client.list_endpoint_groups() - - @decorators.idempotent_id('5c16368d-1485-4c28-9803-db3fa3510623') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_endpoint_group"]) - def test_check_endpoint_group(self): - with self.override_role(): - self.endpoint_groups_client.check_endpoint_group( - self.endpoint_group_id) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_endpoint_group"]) - @decorators.idempotent_id('bd2b6fb8-661f-4255-84b2-50fea4a1dc61') - def test_show_endpoint_group(self): - with self.override_role(): - self.endpoint_groups_client.show_endpoint_group( - self.endpoint_group_id) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_endpoint_group"]) - @decorators.idempotent_id('028b9198-ec35-4bd5-8f72-e23dfb7a0c8e') - def test_update_endpoint_group(self): - updated_name = data_utils.rand_name( - self.__class__.__name__ + '-EPFilterGroup') - - with self.override_role(): - self.endpoint_groups_client.update_endpoint_group( - self.endpoint_group_id, name=updated_name) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_endpoint_group"]) - @decorators.idempotent_id('88cc105e-70d9-48ac-927e-200ef41e070c') - def test_delete_endpoint_group(self): - endpoint_group_id = self._create_endpoint_group(ignore_not_found=True) - - with self.override_role(): - self.endpoint_groups_client.delete_endpoint_group( - endpoint_group_id) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_ep_filter_projects_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_ep_filter_projects_rbac.py deleted file mode 100644 index 8385d6d7..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_ep_filter_projects_rbac.py +++ /dev/null @@ -1,90 +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.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class EndpointFilterProjectsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @classmethod - def resource_setup(cls): - super(EndpointFilterProjectsV3RbacTest, cls).resource_setup() - cls.project = cls.setup_test_project() - cls.endpoint = cls.setup_test_endpoint() - - def _add_endpoint_to_project(self, ignore_not_found=False): - self.endpoint_filter_client.add_endpoint_to_project( - self.project['id'], self.endpoint['id']) - - if ignore_not_found: - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.endpoint_filter_client.delete_endpoint_from_project, - self.project['id'], self.endpoint['id']) - else: - self.addCleanup( - self.endpoint_filter_client.delete_endpoint_from_project, - self.project['id'], self.endpoint['id']) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:add_endpoint_to_project"]) - @decorators.idempotent_id('9199ec13-816d-4efe-b8b1-e1cd026b9747') - def test_add_endpoint_to_project(self): - # Adding endpoints to projects - with self.override_role(): - self._add_endpoint_to_project(ignore_not_found=True) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:list_projects_for_endpoint"]) - @decorators.idempotent_id('f53dca42-ec8a-48e9-924b-0bbe6c99727f') - def test_list_projects_for_endpoint(self): - with self.override_role(): - self.endpoint_filter_client.list_projects_for_endpoint( - self.endpoint['id']) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:check_endpoint_in_project"]) - @decorators.idempotent_id('0c1425eb-833c-4aa1-a21d-52ffa41fdc6a') - def test_check_endpoint_in_project(self): - self._add_endpoint_to_project() - with self.override_role(): - self.endpoint_filter_client.check_endpoint_in_project( - self.project['id'], self.endpoint['id']) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:list_endpoints_for_project"]) - @decorators.idempotent_id('5d86c659-c6ad-41e0-854e-3823e95c7cc2') - def test_list_endpoints_in_project(self): - with self.override_role(): - self.endpoint_filter_client.list_endpoints_in_project( - self.project['id']) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:remove_endpoint_from_project"]) - @decorators.idempotent_id('b4e21c10-4f47-427b-9b8a-f5b5601adfda') - def test_remove_endpoint_from_project(self): - self._add_endpoint_to_project(ignore_not_found=True) - with self.override_role(): - self.endpoint_filter_client.delete_endpoint_from_project( - self.project['id'], self.endpoint['id']) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_groups_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_groups_rbac.py deleted file mode 100644 index 1e79501f..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_groups_rbac.py +++ /dev/null @@ -1,121 +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. - -import testtools - -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - -CONF = config.CONF - - -class IdentityGroupsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - def _create_user_and_add_to_new_group(self): - """Creates a user and adds to a group for test.""" - group = self.setup_test_group() - user = self.setup_test_user() - self.groups_client.add_group_user(group['id'], user['id']) - return (group['id'], user['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_group"]) - @decorators.idempotent_id('88377f51-9074-4d64-a22f-f8931d048c9a') - def test_create_group(self): - with self.override_role(): - self.setup_test_group() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_group"]) - @decorators.idempotent_id('790fb7be-a657-4a64-9b83-c43425cf180b') - def test_update_group(self): - group = self.setup_test_group() - new_group_name = data_utils.rand_name( - self.__class__.__name__ + '-group') - - with self.override_role(): - self.groups_client.update_group(group['id'], name=new_group_name) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_group"]) - @decorators.idempotent_id('646b52da-2a5f-486a-afb0-51fdc86a6c12') - def test_delete_group(self): - group = self.setup_test_group() - - with self.override_role(): - self.groups_client.delete_group(group['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_group"]) - @decorators.idempotent_id('d530f0ad-42b9-429b-ad05-e53ac95a040e') - def test_show_group(self): - group = self.setup_test_group() - - with self.override_role(): - self.groups_client.show_group(group['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_groups"]) - @decorators.idempotent_id('c4d0f76b-735f-4fd0-868b-0006bc420ff4') - def test_list_groups(self): - with self.override_role(): - self.groups_client.list_groups() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:add_user_to_group"]) - @decorators.idempotent_id('fdd49b74-3ed3-4736-9f0e-9027a32017ac') - def test_add_user_group(self): - group = self.setup_test_group() - user = self.setup_test_user() - - with self.override_role(): - self.groups_client.add_group_user(group['id'], user['id']) - - @testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source, - 'Skipped because environment has an immutable user ' - 'source and solely provides read-only access to users.') - @rbac_rule_validation.action(service="keystone", - rules=["identity:remove_user_from_group"]) - @decorators.idempotent_id('8a60d11c-7d2b-47e5-a0f3-9ea900ca66fe') - def test_remove_user_group(self): - group_id, user_id = self._create_user_and_add_to_new_group() - - with self.override_role(): - self.groups_client.delete_group_user(group_id, user_id) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_users_in_group"]) - @decorators.idempotent_id('b3e394a7-079e-4a0d-a4ff-9b266293d1ee') - def test_list_user_group(self): - group = self.setup_test_group() - - with self.override_role(): - self.groups_client.list_group_users(group['id']) - - @testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source, - 'Skipped because environment has an immutable user ' - 'source and solely provides read-only access to users.') - @rbac_rule_validation.action(service="keystone", - rules=["identity:check_user_in_group"]) - @decorators.idempotent_id('d3603241-fd87-4a2d-94f9-f32469d1aaba') - def test_check_user_group(self): - group_id, user_id = self._create_user_and_add_to_new_group() - - with self.override_role(): - self.groups_client.check_group_user_existence(group_id, user_id) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_oauth_consumers_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_oauth_consumers_rbac.py deleted file mode 100644 index 4198a467..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_oauth_consumers_rbac.py +++ /dev/null @@ -1,78 +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.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityConsumersV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - def _create_consumer(self): - description = data_utils.rand_name( - self.__class__.__name__) - consumer = self.consumers_client.create_consumer( - description)['consumer'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.consumers_client.delete_consumer, - consumer['id']) - return consumer - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_consumer"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d970') - def test_create_consumer(self): - with self.override_role(): - self._create_consumer() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_consumer"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d971') - def test_delete_consumer(self): - consumer = self._create_consumer() - - with self.override_role(): - self.consumers_client.delete_consumer(consumer['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_consumer"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d972') - def test_update_consumer(self): - consumer = self._create_consumer() - updated_description = data_utils.rand_name( - self.__class__.__name__) - - with self.override_role(): - self.consumers_client.update_consumer(consumer['id'], - updated_description) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_consumer"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d973') - def test_show_consumer(self): - consumer = self._create_consumer() - - with self.override_role(): - self.consumers_client.show_consumer(consumer['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_consumers"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d975') - def test_list_consumers(self): - with self.override_role(): - self.consumers_client.list_consumers() diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_oauth_tokens_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_oauth_tokens_rbac.py deleted file mode 100644 index 86cb4a83..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_oauth_tokens_rbac.py +++ /dev/null @@ -1,138 +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.common.utils import data_utils -from tempest.lib.common.utils import test_utils - -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - -CONF = config.CONF - - -class IdentityOAuthTokensV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @classmethod - def resource_setup(cls): - super(IdentityOAuthTokensV3RbacTest, cls).resource_setup() - # Authorize token on admin role since primary user has admin - # credentials before switching roles. Populate role_ids with admin - # role id. - cls.role_ids = [cls.get_role_by_name(CONF.identity.admin_role)['id']] - cls.project_id = cls.os_primary.credentials.project_id - cls.user_id = cls.os_primary.credentials.user_id - - def _create_consumer(self): - description = data_utils.rand_name( - self.__class__.__name__ + '-Consumer') - consumer = self.consumers_client.create_consumer( - description)['consumer'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.consumers_client.delete_consumer, - consumer['id']) - return consumer - - def _create_consumer_and_request_token(self): - # Create consumer - consumer = self._create_consumer() - - # Create request token - request_token = self.oauth_token_client.create_request_token( - consumer['id'], consumer['secret'], self.project_id) - - return consumer, request_token - - def _create_access_token(self): - consumer, request_token = self._create_consumer_and_request_token() - - # Authorize request token - resp = self.oauth_token_client.authorize_request_token( - request_token['oauth_token'], self.role_ids)['token'] - auth_verifier = resp['oauth_verifier'] - - # Create access token - body = self.oauth_token_client.create_access_token( - consumer['id'], - consumer['secret'], - request_token['oauth_token'], - request_token['oauth_token_secret'], - auth_verifier) - access_key = body['oauth_token'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.oauth_token_client.revoke_access_token, - self.user_id, access_key) - - return access_key - - @rbac_rule_validation.action(service="keystone", - rules=["identity:authorize_request_token"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d976') - def test_authorize_request_token(self): - _, request_token = self._create_consumer_and_request_token() - - with self.override_role(): - self.oauth_token_client.authorize_request_token( - request_token['oauth_token'], - self.role_ids) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_access_token"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d977') - def test_get_access_token(self): - access_token = self._create_access_token() - - with self.override_role(): - self.oauth_token_client.get_access_token(self.user_id, - access_token) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_access_token_role"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d980') - def test_get_access_token_role(self): - access_token = self._create_access_token() - - with self.override_role(): - self.oauth_token_client.get_access_token_role( - self.user_id, access_token, self.role_ids[0]) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_access_tokens"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d979') - def test_list_access_tokens(self): - with self.override_role(): - self.oauth_token_client.list_access_tokens(self.user_id) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_access_token_roles"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d978') - def test_list_access_token_roles(self): - access_token = self._create_access_token() - - with self.override_role(): - self.oauth_token_client.list_access_token_roles( - self.user_id, access_token) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_access_token"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d981') - def test_revoke_access_token(self): - access_token = self._create_access_token() - - with self.override_role(): - self.oauth_token_client.revoke_access_token( - self.user_id, access_token) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_policies_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_policies_rbac.py deleted file mode 100644 index 8bb405be..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_policies_rbac.py +++ /dev/null @@ -1,67 +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.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityPoliciesV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_policy"]) - @decorators.idempotent_id('de2f7ecb-fbf0-41f3-abf4-b97b5e082fd5') - def test_create_policy(self): - with self.override_role(): - self.setup_test_policy() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_policy"]) - @decorators.idempotent_id('9cfed3c6-0b27-4d15-be67-e06e0cfb01b9') - def test_update_policy(self): - policy = self.setup_test_policy() - updated_policy_type = data_utils.rand_name( - self.__class__.__name__ + '-policy_type') - - with self.override_role(): - self.policies_client.update_policy(policy['id'], - type=updated_policy_type) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_policy"]) - @decorators.idempotent_id('dcd93f75-1e1b-4fbe-bee0-9c4c7b201735') - def test_delete_policy(self): - policy = self.setup_test_policy() - - with self.override_role(): - self.policies_client.delete_policy(policy['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_policy"]) - @decorators.idempotent_id('d7e415c2-945a-4504-9571-0e2d0dd8594b') - def test_show_policy(self): - policy = self.setup_test_policy() - - with self.override_role(): - self.policies_client.show_policy(policy['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_policies"]) - @decorators.idempotent_id('35a56161-4054-4237-8a78-7ce805dce202') - def test_list_policies(self): - with self.override_role(): - self.policies_client.list_policies() diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_policy_association_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_policy_association_rbac.py deleted file mode 100644 index c35ae815..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_policy_association_rbac.py +++ /dev/null @@ -1,152 +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.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityPolicyAssociationRbacTest( - rbac_base.BaseIdentityV3RbacTest): - - def setUp(self): - super(IdentityPolicyAssociationRbacTest, self).setUp() - self.policy_id = self.setup_test_policy()['id'] - self.service_id = self.setup_test_service()['id'] - self.endpoint_id = self.setup_test_endpoint()['id'] - self.region_id = self.setup_test_region()['id'] - - def _update_policy_association_for_endpoint(self, policy_id, endpoint_id): - self.policies_client.update_policy_association_for_endpoint( - policy_id, endpoint_id) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.policies_client.delete_policy_association_for_endpoint, - policy_id, endpoint_id) - - def _update_policy_association_for_service(self, policy_id, service_id): - self.policies_client.update_policy_association_for_service( - policy_id, service_id) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.policies_client.delete_policy_association_for_service, - policy_id, service_id) - - def _update_policy_association_for_region_and_service( - self, policy_id, service_id, region_id): - self.policies_client.update_policy_association_for_region_and_service( - policy_id, service_id, region_id) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.policies_client. - delete_policy_association_for_region_and_service, - policy_id, service_id, region_id) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:create_policy_association_for_endpoint"]) - @decorators.idempotent_id('1b3f4f62-4f4a-4d27-be27-9a113058597f') - def test_update_policy_association_for_endpoint(self): - with self.override_role(): - self._update_policy_association_for_endpoint( - self.policy_id, self.endpoint_id) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:check_policy_association_for_endpoint"]) - @decorators.idempotent_id('25ce8c89-e751-465c-8d35-52bacd774beb') - def test_show_policy_association_for_endpoint(self): - self._update_policy_association_for_endpoint( - self.policy_id, self.endpoint_id) - with self.override_role(): - self.policies_client.show_policy_association_for_endpoint( - self.policy_id, self.endpoint_id) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:delete_policy_association_for_endpoint"]) - @decorators.idempotent_id('95cad2d8-bcd0-4c4e-a8f7-cc80601e43a1') - def test_delete_policy_association_for_endpoint(self): - self._update_policy_association_for_endpoint( - self.policy_id, self.endpoint_id) - with self.override_role(): - self.policies_client.delete_policy_association_for_endpoint( - self.policy_id, self.endpoint_id) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:create_policy_association_for_service"]) - @decorators.idempotent_id('57fb80fe-6ce2-4995-b710-4692b3fc3cdc') - def test_update_policy_association_for_service(self): - with self.override_role(): - self._update_policy_association_for_service( - self.policy_id, self.service_id) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:check_policy_association_for_service"]) - @decorators.idempotent_id('5cbe285f-4888-4f98-978f-30210ff28b74') - def test_show_policy_association_for_service(self): - self._update_policy_association_for_service( - self.policy_id, self.service_id) - with self.override_role(): - self.policies_client.show_policy_association_for_service( - self.policy_id, self.service_id) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:delete_policy_association_for_service"]) - @decorators.idempotent_id('f754455c-02a4-4fb6-8c73-64ef453f955f') - def test_delete_policy_association_for_service(self): - self._update_policy_association_for_service( - self.policy_id, self.service_id) - with self.override_role(): - self.policies_client.delete_policy_association_for_service( - self.policy_id, self.service_id) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:create_policy_association_for_region_and_service"]) - @decorators.idempotent_id('54d2a93e-c84d-4079-8ea9-2fb227c262a1') - def test_update_policy_association_for_region_and_service(self): - with self.override_role(): - self._update_policy_association_for_region_and_service( - self.policy_id, self.service_id, self.region_id) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:check_policy_association_for_region_and_service"]) - @decorators.idempotent_id('0763b780-52c1-47bc-9316-1fe12a2ab0bc') - def test_show_policy_association_for_region_and_service(self): - self._update_policy_association_for_region_and_service( - self.policy_id, self.service_id, self.region_id) - with self.override_role(): - self.policies_client\ - .show_policy_association_for_region_and_service( - self.policy_id, self.service_id, self.region_id) - - @rbac_rule_validation.action( - service="keystone", - rules=["identity:delete_policy_association_for_region_and_service"]) - @decorators.idempotent_id('9c956888-81d4-4a24-8203-bff7b8a7834c') - def test_delete_policy_association_for_region_and_service(self): - self._update_policy_association_for_region_and_service( - self.policy_id, self.service_id, self.region_id) - with self.override_role(): - self.policies_client.\ - delete_policy_association_for_region_and_service( - self.policy_id, self.service_id, self.region_id) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_project_tags_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_project_tags_rbac.py deleted file mode 100644 index ae43b38b..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_project_tags_rbac.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright 2018 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 import config -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - -CONF = config.CONF - - -class ProjectTagsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @classmethod - def skip_checks(cls): - super(ProjectTagsV3RbacTest, cls).skip_checks() - if not CONF.identity_feature_enabled.project_tags: - raise cls.skipException("Project tags feature disabled") - - @classmethod - def resource_setup(cls): - super(ProjectTagsV3RbacTest, cls).resource_setup() - cls.project_id = cls.setup_test_project()['id'] - - def tearDown(self): - self.project_tags_client.delete_all_project_tags(self.project_id) - super(ProjectTagsV3RbacTest, self).tearDown() - - @decorators.idempotent_id('acbd7b2d-0a4d-4990-9fab-eccad69d4238') - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_project_tag"]) - def test_update_project_tag(self): - tag = data_utils.rand_name(self.__class__.__name__ + '-Tag') - with self.override_role(): - self.project_tags_client.update_project_tag(self.project_id, tag) - - @decorators.idempotent_id('e122d7d1-bb6d-43af-b489-afa8c609b9ae') - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_project_tags"]) - def test_list_project_tags(self): - with self.override_role(): - self.project_tags_client.list_project_tags(self.project_id) - - @decorators.idempotent_id('716f9081-4626-4594-a82c-e7dc037464ac') - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_project_tags"]) - def test_update_all_project_tags(self): - tags = [ - data_utils.rand_name(self.__class__.__name__ + '-Tag') - for _ in range(2) - ] - with self.override_role(): - self.project_tags_client.update_all_project_tags( - self.project_id, tags) - - @decorators.idempotent_id('974cb1da-d7d4-4863-99da-4a3f0c801729') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_project_tag"]) - def test_check_project_tag_existence(self): - tag = data_utils.rand_name(self.__class__.__name__ + '-Tag') - self.project_tags_client.update_project_tag(self.project_id, tag) - - with self.override_role(): - self.project_tags_client.check_project_tag_existence( - self.project_id, tag) - - @decorators.idempotent_id('ffe0c8e1-f9eb-43c5-8097-1e938fc08e07') - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_project_tag"]) - def test_delete_project_tag(self): - tag = data_utils.rand_name(self.__class__.__name__ + '-Tag') - self.project_tags_client.update_project_tag(self.project_id, tag) - - with self.override_role(): - self.project_tags_client.delete_project_tag(self.project_id, tag) - - @decorators.idempotent_id('94d0ef63-e9e3-4287-9c5e-bd5464467d77') - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_project_tags"]) - def test_delete_all_project_tags(self): - with self.override_role(): - self.project_tags_client.delete_all_project_tags(self.project_id) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_projects_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_projects_rbac.py deleted file mode 100644 index af587994..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_projects_rbac.py +++ /dev/null @@ -1,67 +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.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityProjectV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_project"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d904') - def test_create_project(self): - with self.override_role(): - self.setup_test_project() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_project"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d905') - def test_update_project(self): - project = self.setup_test_project() - new_desc = data_utils.rand_name( - self.__class__.__name__ + '-description') - - with self.override_role(): - self.projects_client.update_project(project['id'], - description=new_desc) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_project"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d906') - def test_delete_project(self): - project = self.setup_test_project() - - with self.override_role(): - self.projects_client.delete_project(project['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_project"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d907') - def test_show_project(self): - project = self.setup_test_project() - - with self.override_role(): - self.projects_client.show_project(project['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_projects"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d908') - def test_list_projects(self): - with self.override_role(): - self.projects_client.list_projects() diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_regions_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_regions_rbac.py deleted file mode 100644 index 5a4de23e..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_regions_rbac.py +++ /dev/null @@ -1,67 +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.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityRegionsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_region"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd119') - def test_create_region(self): - with self.override_role(): - self.setup_test_region() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_region"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd120') - def test_update_region(self): - region = self.setup_test_region() - new_description = data_utils.rand_name( - self.__class__.__name__ + '-test_update_region') - - with self.override_role(): - self.regions_client.update_region(region['id'], - description=new_description) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_region"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd121') - def test_delete_region(self): - region = self.setup_test_region() - - with self.override_role(): - self.regions_client.delete_region(region['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_region"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd122') - def test_show_region(self): - region = self.setup_test_region() - - with self.override_role(): - self.regions_client.show_region(region['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_regions"]) - @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd123') - def test_list_regions(self): - with self.override_role(): - self.regions_client.list_regions() diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_role_assignments_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_role_assignments_rbac.py deleted file mode 100644 index b0d3dfea..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_role_assignments_rbac.py +++ /dev/null @@ -1,41 +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 patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityRoleAssignmentsV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @decorators.idempotent_id('afe57adb-1b9c-43d9-84a9-f0cf4c94e416') - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_role_assignments"]) - def test_list_role_assignments(self): - with self.override_role(): - self.role_assignments_client.list_role_assignments() - - @decorators.idempotent_id('36c7a990-857e-415c-8717-38d7200a9894') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:list_role_assignments_for_tree"]) - def test_list_role_assignments_for_tree(self): - project = self.setup_test_project() - - with self.override_role(): - self.role_assignments_client.list_role_assignments( - include_subtree=True, - **{'scope.project.id': project['id']}) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py deleted file mode 100644 index c93afa1f..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py +++ /dev/null @@ -1,422 +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 import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - -CONF = config.CONF - - -class IdentityRolesV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @classmethod - def resource_setup(cls): - super(IdentityRolesV3RbacTest, cls).resource_setup() - cls.domain = cls.setup_test_domain() - cls.project = cls.setup_test_project() - cls.group = cls.setup_test_group() - cls.role = cls.setup_test_role() - cls.implies_role = cls.setup_test_role() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_role"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d904') - def test_create_role(self): - with self.override_role(): - self.setup_test_role() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_role"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d905') - def test_update_role(self): - new_role_name = data_utils.rand_name( - self.__class__.__name__ + '-test_update_role') - - with self.override_role(): - self.roles_client.update_role(self.role['id'], - name=new_role_name) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_role"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d906') - def test_delete_role(self): - role = self.setup_test_role() - - with self.override_role(): - self.roles_client.delete_role(role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_role"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d907') - def test_show_role(self): - with self.override_role(): - self.roles_client.show_role(self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_roles"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d908') - def test_list_roles(self): - with self.override_role(): - self.roles_client.list_roles() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_grant"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90c') - def test_create_group_role_on_project(self): - with self.override_role(): - self.roles_client.create_group_role_on_project( - self.project['id'], - self.group['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_group_on_project, - self.project['id'], - self.group['id'], - self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_grant"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d912') - def test_create_group_role_on_domain(self): - with self.override_role(): - self.roles_client.create_group_role_on_domain( - self.domain['id'], - self.group['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_group_on_domain, - self.domain['id'], - self.group['id'], - self.role['id']) - - @decorators.idempotent_id('8738d3d2-8c84-4423-b36c-7c59eaa08b73') - @rbac_rule_validation.action(service="keystone", - rules=["identity:check_grant"]) - def test_check_role_from_group_on_project_existence(self): - self.roles_client.create_group_role_on_project( - self.project['id'], - self.group['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_group_on_project, - self.project['id'], - self.group['id'], - self.role['id']) - - with self.override_role(): - self.roles_client.check_role_from_group_on_project_existence( - self.project['id'], - self.group['id'], - self.role['id']) - - @decorators.idempotent_id('e7d73bd0-cf5e-4c0c-9c93-cf53e23232d6') - @rbac_rule_validation.action(service="keystone", - rules=["identity:check_grant"]) - def test_check_role_from_group_on_domain_existence(self): - self.roles_client.create_group_role_on_domain( - self.domain['id'], - self.group['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_group_on_domain, - self.domain['id'], - self.group['id'], - self.role['id']) - - with self.override_role(): - self.roles_client.check_role_from_group_on_domain_existence( - self.domain['id'], - self.group['id'], - self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:revoke_grant"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90d') - def test_delete_role_from_group_on_project(self): - self.roles_client.create_group_role_on_project( - self.project['id'], - self.group['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_group_on_project, - self.project['id'], - self.group['id'], - self.role['id']) - - with self.override_role(): - self.roles_client.delete_role_from_group_on_project( - self.project['id'], - self.group['id'], - self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:revoke_grant"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d913') - def test_delete_role_from_group_on_domain(self): - self.roles_client.create_group_role_on_domain( - self.domain['id'], - self.group['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_group_on_domain, - self.domain['id'], - self.group['id'], - self.role['id']) - - with self.override_role(): - self.roles_client.delete_role_from_group_on_domain( - self.domain['id'], - self.group['id'], - self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_grants"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90e') - def test_list_group_roles_on_project(self): - with self.override_role(): - self.roles_client.list_group_roles_on_project( - self.project['id'], - self.group['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_grants"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d914') - def test_list_group_roles_on_domain(self): - with self.override_role(): - self.roles_client.list_group_roles_on_domain( - self.domain['id'], - self.group['id']) - - @decorators.idempotent_id('2aef3eaa-8156-4962-a01d-c9bb0e499e15') - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_implied_role"]) - def test_create_role_inference_rule(self): - with self.override_role(): - self.roles_client.create_role_inference_rule( - self.role['id'], self.implies_role['id']) - self.addCleanup(self.roles_client.delete_role_inference_rule, - self.role['id'], self.implies_role['id']) - - @decorators.idempotent_id('83f997b2-55c4-4894-b1f2-e175b19d1fa5') - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_implied_role"]) - def test_show_role_inference_rule(self): - self.roles_client.create_role_inference_rule( - self.role['id'], self.implies_role['id']) - self.addCleanup(self.roles_client.delete_role_inference_rule, - self.role['id'], self.implies_role['id']) - - with self.override_role(): - self.roles_client.show_role_inference_rule( - self.role['id'], self.implies_role['id']) - - @decorators.idempotent_id('f7bb39bf-0b06-468e-a8b0-60a4fb1f258d') - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_implied_roles"]) - def test_list_role_inferences_rules(self): - with self.override_role(): - self.roles_client.list_role_inferences_rules(self.role['id']) - - @decorators.idempotent_id('eca2d502-09bb-45cd-9773-bce2e7bcddd1') - @rbac_rule_validation.action(service="keystone", - rules=["identity:check_implied_role"]) - def test_check_role_inference_rule(self): - self.roles_client.create_role_inference_rule( - self.role['id'], self.implies_role['id']) - self.addCleanup(self.roles_client.delete_role_inference_rule, - self.role['id'], self.implies_role['id']) - - with self.override_role(): - self.roles_client.check_role_inference_rule( - self.role['id'], self.implies_role['id']) - - @decorators.idempotent_id('13a5db1e-dd4a-4ca1-81ec-d5452aaaf54b') - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_implied_role"]) - def test_delete_role_inference_rule(self): - self.roles_client.create_role_inference_rule( - self.role['id'], self.implies_role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_inference_rule, - self.role['id'], self.implies_role['id']) - - with self.override_role(): - self.roles_client.delete_role_inference_rule( - self.role['id'], self.implies_role['id']) - - @decorators.idempotent_id('05869f2b-4dd4-425a-905e-eec9a6f06374') - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_role_inference_rules"]) - def test_list_all_role_inference_rules(self): - with self.override_role(): - self.roles_client.list_all_role_inference_rules() - - -class IdentityRolesUserCreateV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - """Tests identity roles v3 API endpoints that require user creation. - This is in a separate class to better manage immutable user source feature - flag. - """ - - @classmethod - def skip_checks(cls): - super(IdentityRolesUserCreateV3RbacTest, cls).skip_checks() - if CONF.identity_feature_enabled.immutable_user_source: - raise cls.skipException('Skipped because environment has an ' - 'immutable user source and solely ' - 'provides read-only access to users.') - - @classmethod - def resource_setup(cls): - super(IdentityRolesUserCreateV3RbacTest, cls).resource_setup() - cls.domain = cls.setup_test_domain() - cls.project = cls.setup_test_project() - cls.group = cls.setup_test_group() - cls.role = cls.setup_test_role() - cls.implies_role = cls.setup_test_role() - cls.user = cls.setup_test_user() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_grant"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d909') - def test_create_user_role_on_project(self): - with self.override_role(): - self.roles_client.create_user_role_on_project( - self.project['id'], - self.user['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_user_on_project, - self.project['id'], - self.user['id'], - self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_grant"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90f') - def test_create_user_role_on_domain(self): - with self.override_role(): - self.roles_client.create_user_role_on_domain( - self.domain['id'], - self.user['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_user_on_domain, - self.domain['id'], - self.user['id'], - self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:check_grant"]) - @decorators.idempotent_id('22921b1e-1a33-4026-bff9-f236d6dd149c') - def test_check_user_role_existence_on_project(self): - self.roles_client.create_user_role_on_project( - self.project['id'], - self.user['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_user_on_project, - self.project['id'], - self.user['id'], - self.role['id']) - - with self.override_role(): - self.roles_client.check_user_role_existence_on_project( - self.project['id'], - self.user['id'], - self.role['id']) - - @decorators.idempotent_id('92f8e67d-85bf-407d-9814-edd5664abc47') - @rbac_rule_validation.action(service="keystone", - rules=["identity:check_grant"]) - def test_check_user_role_existence_on_domain(self): - self.roles_client.create_user_role_on_domain( - self.domain['id'], - self.user['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_user_on_domain, - self.domain['id'], - self.user['id'], - self.role['id']) - - with self.override_role(): - self.roles_client.check_user_role_existence_on_domain( - self.domain['id'], - self.user['id'], - self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:revoke_grant"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90a') - def test_delete_role_from_user_on_project(self): - self.roles_client.create_user_role_on_project( - self.project['id'], - self.user['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_user_on_project, - self.project['id'], - self.user['id'], - self.role['id']) - - with self.override_role(): - self.roles_client.delete_role_from_user_on_project( - self.project['id'], - self.user['id'], - self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:revoke_grant"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d910') - def test_delete_role_from_user_on_domain(self): - self.roles_client.create_user_role_on_domain( - self.domain['id'], - self.user['id'], - self.role['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.roles_client.delete_role_from_user_on_domain, - self.domain['id'], - self.user['id'], - self.role['id']) - - with self.override_role(): - self.roles_client.delete_role_from_user_on_domain( - self.domain['id'], - self.user['id'], - self.role['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_grants"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90b') - def test_list_user_roles_on_project(self): - with self.override_role(): - self.roles_client.list_user_roles_on_project( - self.project['id'], - self.user['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_grants"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d911') - def test_list_user_roles_on_domain(self): - with self.override_role(): - self.roles_client.list_user_roles_on_domain( - self.domain['id'], - self.user['id']) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_services_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_services_rbac.py deleted file mode 100644 index 5427f5f6..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_services_rbac.py +++ /dev/null @@ -1,68 +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.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentitySericesV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_service"]) - @decorators.idempotent_id('9a4bb317-f0bb-4005-8df0-4b672885b7c8') - def test_create_service(self): - with self.override_role(): - self.setup_test_service() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_service"]) - @decorators.idempotent_id('b39447d1-2cf6-40e5-a899-46f287f2ecf0') - def test_update_service(self): - service = self.setup_test_service() - new_name = data_utils.rand_name(self.__class__.__name__ + '-service') - - with self.override_role(): - self.services_client.update_service(service['id'], - service=service, - name=new_name, - type=service['type']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_service"]) - @decorators.idempotent_id('177b991a-438d-4bef-8e9f-9c6cc5a1c9e8') - def test_delete_service(self): - service = self.setup_test_service() - - with self.override_role(): - self.services_client.delete_service(service['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_service"]) - @decorators.idempotent_id('d89a9ac6-cd53-428d-84c0-5bc71f4a432d') - def test_show_service(self): - service = self.setup_test_service() - - with self.override_role(): - self.services_client.show_service(service['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_services"]) - @decorators.idempotent_id('706e6bea-3385-4718-919c-0b5121395806') - def test_list_services(self): - with self.override_role(): - self.services_client.list_services() diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_tokens_negative_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_tokens_negative_rbac.py deleted file mode 100644 index 45eb601e..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_tokens_negative_rbac.py +++ /dev/null @@ -1,97 +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.lib import exceptions as lib_exc - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin import rbac_utils -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityTokenV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - credentials = ['primary', 'alt', 'admin'] - - @classmethod - def skip_checks(cls): - super(IdentityTokenV3RbacTest, cls).skip_checks() - # In case of admin, the positive testcase would be used, hence - # skipping negative testcase. - if rbac_utils.is_admin(): - raise cls.skipException( - "Skipped as admin role doesn't require negative testing") - - def _setup_alt_token(self): - return self.setup_test_token( - self.os_alt.auth_provider.credentials.user_id, - self.os_alt.auth_provider.credentials.password) - - @decorators.idempotent_id('c83c8f1a-79cb-4dc4-b55f-c7d2bfd98b1e') - @decorators.attr(type=['negative']) - @rbac_rule_validation.action( - service="keystone", - rules=["identity:validate_token"], - extra_target_data={ - "target.token.user_id": - "os_alt.auth_provider.credentials.user_id" - }) - def test_show_token_negative(self): - # Explicit negative test for identity:validate_token policy action. - # Assert expected exception is Forbidden and then reraise it. - alt_token_id = self._setup_alt_token() - with self.override_role(): - e = self.assertRaises(lib_exc.Forbidden, - self.identity_client.show_token, - alt_token_id) - raise e - - @decorators.idempotent_id('2786a55d-a818-433a-af7a-41ebf72ab4da') - @decorators.attr(type=['negative']) - @rbac_rule_validation.action( - service="keystone", - rules=["identity:revoke_token"], - extra_target_data={ - "target.token.user_id": - "os_alt.auth_provider.credentials.user_id" - }) - def test_delete_token_negative(self): - # Explicit negative test for identity:revoke_token policy action. - # Assert expected exception is Forbidden and then reraise it. - alt_token_id = self._setup_alt_token() - with self.override_role(): - e = self.assertRaises(lib_exc.Forbidden, - self.identity_client.delete_token, - alt_token_id) - raise e - - @decorators.idempotent_id('1ea02ac0-9a96-44bd-bdc3-4dae3c10cc2e') - @decorators.attr(type=['negative']) - @rbac_rule_validation.action( - service="keystone", - rules=["identity:check_token"], - extra_target_data={ - "target.token.user_id": - "os_alt.auth_provider.credentials.user_id" - }) - def test_check_token_existence_negative(self): - # Explicit negative test for identity:check_token policy action. - # Assert expected exception is Forbidden and then reraise it. - alt_token_id = self._setup_alt_token() - with self.override_role(): - e = self.assertRaises(lib_exc.Forbidden, - self.identity_client.check_token_existence, - alt_token_id) - raise e diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_tokens_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_tokens_rbac.py deleted file mode 100644 index 0028a974..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_tokens_rbac.py +++ /dev/null @@ -1,67 +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 patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - - -class IdentityTokenV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @classmethod - def resource_setup(cls): - super(IdentityTokenV3RbacTest, cls).resource_setup() - cls.user_id = cls.os_primary.auth_provider.credentials.user_id - cls.password = cls.os_primary.auth_provider.credentials.password - - @decorators.idempotent_id('201e2fe5-2023-4bce-9189-78b51520a91e') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:validate_token"], - extra_target_data={ - "target.token.user_id": - "os_primary.auth_provider.credentials.user_id" - }) - def test_show_token(self): - token_id = self.setup_test_token(self.user_id, self.password) - with self.override_role(): - self.identity_client.show_token(token_id) - - @decorators.idempotent_id('42a299db-fe0a-4ea0-9824-0bfd13155886') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:revoke_token"], - extra_target_data={ - "target.token.user_id": - "os_primary.auth_provider.credentials.user_id" - }) - def test_delete_token(self): - token_id = self.setup_test_token(self.user_id, self.password) - with self.override_role(): - self.identity_client.delete_token(token_id) - - @decorators.idempotent_id('3554d218-8cd6-4730-a1b2-0e22f9b78f45') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:check_token"], - extra_target_data={ - "target.token.user_id": - "os_primary.auth_provider.credentials.user_id" - }) - def test_check_token_exsitence(self): - token_id = self.setup_test_token(self.user_id, self.password) - with self.override_role(): - self.identity_client.check_token_existence(token_id) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_trusts_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_trusts_rbac.py deleted file mode 100644 index da29433c..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_trusts_rbac.py +++ /dev/null @@ -1,192 +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. - -import testtools - -from tempest import config -from tempest.lib import decorators -from tempest.lib import exceptions as lib_exc - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - -CONF = config.CONF - - -class IdentityTrustV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - credentials = ['primary', 'alt', 'admin'] - - @classmethod - def skip_checks(cls): - super(IdentityTrustV3RbacTest, cls).skip_checks() - if not CONF.identity_feature_enabled.trust: - raise cls.skipException( - "%s skipped as trust feature isn't enabled" % cls.__name__) - if CONF.identity_feature_enabled.immutable_user_source: - raise cls.skipException('Skipped because environment has an ' - 'immutable user source and solely ' - 'provides read-only access to users.') - - @classmethod - def resource_setup(cls): - super(IdentityTrustV3RbacTest, cls).resource_setup() - # Use the primary user's credentials for the "trustor_user_id", since - # user_id:%(trust.trustor_user_id)s will thereby evaluate to - # "primary user's user_id:primary user's user_id" which evaluates to - # true. - cls.trustor_user_id = cls.os_primary.credentials.user_id - cls.trustor_project_id = cls.os_primary.credentials.project_id - cls.trustee_user_id = cls.setup_test_user()['id'] - - # The "unauthorized_user_id" does not have permissions to create a - # trust because the user_id in "user_id:%(trust.trustor_user_id)s" (the - # policy rule for creating a trust) corresponds to the primary user_id - # not the alt user_id. - cls.unauthorized_user_id = cls.os_alt.credentials.user_id - - # A role is guaranteed to exist (namely the admin role), because - # "trustor_user_id" and "trustor_project_id" are the primary tempest - # user and project, respectively. - cls.delegated_role_id = cls.roles_client.list_user_roles_on_project( - cls.trustor_project_id, cls.trustor_user_id)['roles'][0]['id'] - - cls.trust = cls.setup_test_trust(trustor_user_id=cls.trustor_user_id, - trustee_user_id=cls.trustee_user_id, - project_id=cls.trustor_project_id, - roles=[{'id': cls.delegated_role_id}]) - - @decorators.idempotent_id('7ab595a7-9b71-45fe-91d8-2793b0292f72') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:create_trust"], - extra_target_data={ - "trust.trustor_user_id": "os_primary.credentials.user_id" - }) - def test_create_trust(self): - with self.override_role(): - self.setup_test_trust(trustor_user_id=self.trustor_user_id, - trustee_user_id=self.trustee_user_id) - - @decorators.idempotent_id('bd72d22a-6e11-4840-bd93-17b382e7f0e0') - @decorators.attr(type=['negative']) - @rbac_rule_validation.action( - service="keystone", - rules=["identity:create_trust"], - extra_target_data={ - "trust.trustor_user_id": "os_alt.credentials.user_id" - }) - def test_create_trust_negative(self): - # Explicit negative test for identity:create_trust policy action. - # Assert expected exception is Forbidden and then reraise it. - with self.override_role(): - e = self.assertRaises(lib_exc.Forbidden, self.setup_test_trust, - trustor_user_id=self.unauthorized_user_id, - trustee_user_id=self.trustee_user_id) - raise e - - @decorators.idempotent_id('d9a6fd06-08f6-462c-a86c-ce009adf1230') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:delete_trust"], - extra_target_data={ - "target.trust.trustor_user_id": "os_primary.credentials.user_id" - }) - def test_delete_trust(self): - trust = self.setup_test_trust(trustor_user_id=self.trustor_user_id, - trustee_user_id=self.trustee_user_id) - - with self.override_role(): - self.trusts_client.delete_trust(trust['id']) - - @decorators.idempotent_id('f2e32896-bf66-4f4e-89cf-e7fba0ef1f38') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:list_trusts"]) - def test_list_trusts(self): - # Depending on the passed arguments to the list trusts API, different - # policy actions are enforced. - feature_flag = \ - CONF.policy_feature_enabled.keystone_policy_enforcement_train - with self.override_role(): - if feature_flag: - self.trusts_client.list_trusts() - else: - self.trusts_client.list_trusts( - trustor_user_id=self.trustor_user_id) - - @testtools.skipUnless( - CONF.policy_feature_enabled.keystone_policy_enforcement_train, - 'This test tests Keystone policy actions introduced in Train') - @decorators.idempotent_id('6273ab11-32ad-450e-be4e-deaa856d7051') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:list_trusts_for_trustor"], - extra_target_data={ - "target.trust.trustor_user_id": "os_primary.credentials.user_id" - }) - def test_list_trusts_for_trustor(self): - with self.override_role(): - self.trusts_client.list_trusts( - trustor_user_id=self.trustor_user_id) - - @testtools.skipUnless( - CONF.policy_feature_enabled.keystone_policy_enforcement_train, - 'This test tests Keystone policy actions introduced in Train') - @decorators.idempotent_id('90bbbd77-c1df-43f9-99dc-088d52b95eff') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:list_trusts_for_trustee"], - extra_target_data={ - "target.trust.trustee_user_id": "trustee_user_id" - }) - def test_list_trusts_for_trustee(self): - with self.override_role(): - self.trusts_client.list_trusts( - trustee_user_id=self.trustee_user_id) - - @decorators.idempotent_id('3c9ff92f-a73e-4f9b-8865-e017f38c70f5') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:list_roles_for_trust"], - extra_target_data={ - "target.trust.trustor_user_id": "os_primary.credentials.user_id" - }) - def test_list_roles_for_trust(self): - with self.override_role(): - self.trusts_client.list_trust_roles(self.trust['id']) - - @decorators.idempotent_id('3bb4f97b-cecd-4c7d-ad10-b88ee6c5d573') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:get_role_for_trust"], - extra_target_data={ - "target.trust.trustor_user_id": "os_primary.credentials.user_id" - }) - def test_show_trust_role(self): - with self.override_role(): - self.trusts_client.show_trust_role( - self.trust['id'], self.delegated_role_id) - - @decorators.idempotent_id('0184e0fb-641e-4b52-ab73-81c1ce6ca5c1') - @rbac_rule_validation.action( - service="keystone", - rules=["identity:get_trust"], - extra_target_data={ - "target.trust.trustor_user_id": "os_primary.credentials.user_id" - }) - def test_show_trust(self): - with self.override_role(): - self.trusts_client.show_trust(self.trust['id']) diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_users_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_users_rbac.py deleted file mode 100644 index 0d2a04d0..00000000 --- a/patrole_tempest_plugin/tests/api/identity/v3/test_users_rbac.py +++ /dev/null @@ -1,96 +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. - -import testtools - -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.identity import rbac_base - -CONF = config.CONF - - -class IdentityUserV3RbacTest(rbac_base.BaseIdentityV3RbacTest): - - @classmethod - def resource_setup(cls): - super(IdentityUserV3RbacTest, cls).resource_setup() - cls.default_user_id = cls.os_primary.credentials.user_id - - @testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source, - "Configured to use an immutable user source") - @rbac_rule_validation.action(service="keystone", - rules=["identity:create_user"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d904') - def test_create_user(self): - with self.override_role(): - self.setup_test_user() - - @testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source, - "Configured to use an immutable user source") - @rbac_rule_validation.action(service="keystone", - rules=["identity:update_user"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d905') - def test_update_user(self): - user = self.setup_test_user() - new_email = data_utils.rand_name( - self.__class__.__name__ + '-user_email') - - with self.override_role(): - self.users_client.update_user(user['id'], - name=user['name'], - email=new_email) - - @testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source, - "Configured to use an immutable user source") - @rbac_rule_validation.action(service="keystone", - rules=["identity:delete_user"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d906') - def test_delete_user(self): - user = self.setup_test_user() - - with self.override_role(): - self.users_client.delete_user(user['id']) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_users"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d907') - def test_list_users(self): - with self.override_role(): - self.users_client.list_users() - - @rbac_rule_validation.action(service="keystone", - rules=["identity:get_user"]) - @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d908') - def test_show_own_user(self): - with self.override_role(): - self.users_client.show_user(self.default_user_id) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_groups_for_user"]) - @decorators.idempotent_id('bd5946d4-46d2-423d-a800-a3e7aabc18b3') - def test_list_own_user_group(self): - with self.override_role(): - self.users_client.list_user_groups(self.default_user_id) - - @rbac_rule_validation.action(service="keystone", - rules=["identity:list_user_projects"]) - @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d909') - def test_list_own_user_projects(self): - with self.override_role(): - self.users_client.list_user_projects(self.default_user_id) diff --git a/patrole_tempest_plugin/tests/api/image/__init__.py b/patrole_tempest_plugin/tests/api/image/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/api/image/rbac_base.py b/patrole_tempest_plugin/tests/api/image/rbac_base.py deleted file mode 100644 index 9019bc45..00000000 --- a/patrole_tempest_plugin/tests/api/image/rbac_base.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2017 AT&T Corporation. -# 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.image import base as image_base - -from patrole_tempest_plugin import rbac_utils - - -class BaseV2ImageRbacTest(rbac_utils.RbacUtilsMixin, - image_base.BaseV2ImageTest): - - @classmethod - def setup_clients(cls): - super(BaseV2ImageRbacTest, cls).setup_clients() - cls.namespaces_client = cls.os_primary.namespaces_client - cls.resource_types_client = cls.os_primary.resource_types_client - cls.namespace_properties_client =\ - cls.os_primary.namespace_properties_client - cls.namespace_objects_client = cls.os_primary.namespace_objects_client - cls.namespace_tags_client = cls.os_primary.namespace_tags_client diff --git a/patrole_tempest_plugin/tests/api/image/test_image_namespace_objects_rbac.py b/patrole_tempest_plugin/tests/api/image/test_image_namespace_objects_rbac.py deleted file mode 100644 index ebb848f3..00000000 --- a/patrole_tempest_plugin/tests/api/image/test_image_namespace_objects_rbac.py +++ /dev/null @@ -1,106 +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.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.image import rbac_base - - -class ImageNamespacesObjectsRbacTest(rbac_base.BaseV2ImageRbacTest): - - @rbac_rule_validation.action(service="glance", - rules=["add_metadef_object"]) - @decorators.idempotent_id("772156f2-e33d-432e-8521-12385746c2f0") - def test_create_metadef_object_in_namespace(self): - """Create Metadef Object Namespace Test - - RBAC test for the glance add_metadef_object policy - """ - namespace = self.create_namespace() - # create a md object, it will be cleaned automatically after - # cleanup of namespace - object_name = data_utils.rand_name( - self.__class__.__name__ + '-test-object') - with self.override_role(): - self.namespace_objects_client.create_namespace_object( - namespace['namespace'], - name=object_name) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.namespace_objects_client.delete_namespace_object, - namespace['namespace'], object_name) - - @rbac_rule_validation.action(service="glance", - rules=["get_metadef_objects"]) - @decorators.idempotent_id("48b50ecb-237d-4909-be62-b6a05c47b64d") - def test_list_metadef_objects_in_namespace(self): - """List Metadef Object Namespace Test - - RBAC test for the glance get_metadef_objects policy - """ - namespace = self.create_namespace() - with self.override_role(): - # list md objects - self.namespace_objects_client.list_namespace_objects( - namespace['namespace']) - - @rbac_rule_validation.action(service="glance", - rules=["modify_metadef_object"]) - @decorators.idempotent_id("cd130b1d-89fa-479c-a90e-498d895fb455") - def test_update_metadef_object_in_namespace(self): - """Update Metadef Object Namespace Test - - RBAC test for the glance modify_metadef_object policy - """ - namespace = self.create_namespace() - object_name = data_utils.rand_name( - self.__class__.__name__ + '-test-object') - self.namespace_objects_client.create_namespace_object( - namespace['namespace'], - name=object_name) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.namespace_objects_client.delete_namespace_object, - namespace['namespace'], object_name) - - # Toggle role and modify object - new_name = "Object New Name" - with self.override_role(): - self.namespace_objects_client.update_namespace_object( - namespace['namespace'], object_name, name=new_name) - - @rbac_rule_validation.action(service="glance", - rules=["get_metadef_object"]) - @decorators.idempotent_id("93c61420-5b80-4a0e-b6f3-4ccc6e90b865") - def test_show_metadef_object_in_namespace(self): - """Show Metadef Object Namespace Test - - RBAC test for the glance get_metadef_object policy - """ - namespace = self.create_namespace() - object_name = data_utils.rand_name( - self.__class__.__name__ + '-test-object') - self.namespace_objects_client.create_namespace_object( - namespace['namespace'], - name=object_name) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.namespace_objects_client.delete_namespace_object, - namespace['namespace'], object_name) - # Toggle role and get object - with self.override_role(): - self.namespace_objects_client.show_namespace_object( - namespace['namespace'], - object_name) diff --git a/patrole_tempest_plugin/tests/api/image/test_image_namespace_property_rbac.py b/patrole_tempest_plugin/tests/api/image/test_image_namespace_property_rbac.py deleted file mode 100644 index cc3ba3bd..00000000 --- a/patrole_tempest_plugin/tests/api/image/test_image_namespace_property_rbac.py +++ /dev/null @@ -1,97 +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.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.image import rbac_base - - -class NamespacesPropertyRbacTest(rbac_base.BaseV2ImageRbacTest): - - @classmethod - def resource_setup(cls): - super(NamespacesPropertyRbacTest, cls).resource_setup() - body = cls.resource_types_client.list_resource_types() - cls.resource_name = body['resource_types'][0]['name'] - - @rbac_rule_validation.action(service="glance", - rules=["add_metadef_property"]) - @decorators.idempotent_id('383555ca-677b-43e9-b809-acc2b5a0176c') - def test_add_md_properties(self): - """Create Image Metadef Namespace Property Test - - RBAC test for the glance add_metadef_property policy - """ - namespace = self.create_namespace() - property_name = data_utils.rand_name( - self.__class__.__name__ + '-test-ns-property') - with self.override_role(): - self.namespace_properties_client.create_namespace_property( - namespace=namespace['namespace'], type="string", - title=property_name, name=self.resource_name) - - @rbac_rule_validation.action(service="glance", - rules=["get_metadef_properties"]) - @decorators.idempotent_id('d5177611-c2b5-4000-bd9c-1987af9222ea') - def test_get_md_properties(self): - """List Image Metadef Namespace Properties Test - - RBAC test for the glance get_metadef_properties policy - """ - namespace = self.create_namespace() - with self.override_role(): - self.namespace_properties_client.list_namespace_properties( - namespace=namespace['namespace']) - - @rbac_rule_validation.action(service="glance", - rules=["get_metadef_property"]) - @decorators.idempotent_id('cfeda2af-bcab-433e-80c7-4b40c774aed5') - def test_get_md_property(self): - """Get Image Metadef Namespace Property Test - - RBAC test for the glance get_metadef_property policy - """ - namespace = self.create_namespace() - property_name = data_utils.rand_name( - self.__class__.__name__ + '-test-ns-property') - self.namespace_properties_client.create_namespace_property( - namespace=namespace['namespace'], type="string", - title=property_name, name=self.resource_name) - - with self.override_role(): - self.namespace_properties_client.show_namespace_properties( - namespace['namespace'], self.resource_name) - - @rbac_rule_validation.action(service="glance", - rules=["modify_metadef_property"]) - @decorators.idempotent_id('fdaf9363-4010-4f2f-8192-1b28f6b22e69') - def test_modify_md_properties(self): - """Modify Image Metadef Namespace Policy Test - - RBAC test for the glance modify_metadef_property policy - """ - namespace = self.create_namespace() - property_name = data_utils.rand_name( - self.__class__.__name__ + '-test-ns-property') - self.namespace_properties_client.create_namespace_property( - namespace=namespace['namespace'], type="string", - title=property_name, name=self.resource_name) - - with self.override_role(): - self.namespace_properties_client.update_namespace_properties( - namespace['namespace'], self.resource_name, type="string", - title=property_name, name=self.resource_name) diff --git a/patrole_tempest_plugin/tests/api/image/test_image_namespace_rbac.py b/patrole_tempest_plugin/tests/api/image/test_image_namespace_rbac.py deleted file mode 100644 index 1883d7ce..00000000 --- a/patrole_tempest_plugin/tests/api/image/test_image_namespace_rbac.py +++ /dev/null @@ -1,75 +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.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.image import rbac_base - - -class ImageNamespacesRbacTest(rbac_base.BaseV2ImageRbacTest): - - @rbac_rule_validation.action(service="glance", - rules=["add_metadef_namespace"]) - @decorators.idempotent_id('e0730ead-b824-4ffc-b774-9469df0e4da6') - def test_create_metadef_namespace(self): - """Create Image Metadef Namespace Test - - RBAC test for the glance add_metadef_namespace policy - """ - namespace_name = data_utils.rand_name( - self.__class__.__name__ + '-test-ns') - with self.override_role(): - self.namespaces_client.create_namespace( - namespace=namespace_name, - protected=False) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.namespaces_client.delete_namespace, - namespace_name) - - @rbac_rule_validation.action(service="glance", - rules=["get_metadef_namespaces"]) - @decorators.idempotent_id('f0b12538-9047-489e-98a5-2d78f48ce789') - def test_list_metadef_namespaces(self): - """List Image Metadef Namespace Test - - RBAC test for the glance get_metadef_namespaces policy - """ - with self.override_role(): - self.namespaces_client.list_namespaces() - - @rbac_rule_validation.action(service="glance", - rules=["modify_metadef_namespace"]) - @decorators.idempotent_id('72c14a7e-927d-4f1a-9e1f-25475552922b') - def test_modify_metadef_namespace(self): - """Modify Image Metadef Namespace Test - - RBAC test for the glance modify_metadef_namespace policy - """ - namespace_name = data_utils.rand_name( - self.__class__.__name__ + '-test-ns') - body = self.namespaces_client.create_namespace( - namespace=namespace_name, - protected=False) - with self.override_role(): - self.namespaces_client.update_namespace( - body['namespace'], description="My new description") - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.namespaces_client.delete_namespace, - namespace_name) diff --git a/patrole_tempest_plugin/tests/api/image/test_image_namespace_tags_rbac.py b/patrole_tempest_plugin/tests/api/image/test_image_namespace_tags_rbac.py deleted file mode 100644 index cc367ee2..00000000 --- a/patrole_tempest_plugin/tests/api/image/test_image_namespace_tags_rbac.py +++ /dev/null @@ -1,108 +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.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.image import rbac_base as base - - -class NamespaceTagsRbacTest(base.BaseV2ImageRbacTest): - """RBAC tests for namespace_tags_client. - - Performs RBAC testing for the endpoints in namespace_tags_client, except - for - - 1) delete_namespace_tag - 2) delete_namespace_tags - - because Glance does not currently do policy enforcement for them. - """ - - @classmethod - def resource_setup(cls): - super(NamespaceTagsRbacTest, cls).resource_setup() - cls.namespace = cls.namespaces_client.create_namespace( - namespace=data_utils.rand_name( - cls.__name__ + '-namespace'))['namespace'] - cls.addClassResourceCleanup( - cls.namespaces_client.delete_namespace, - cls.namespace) - - def _create_namespace_tag(self, multiple=False): - tag_count = 2 if multiple else 1 - namespace_tag_names = [] - - for i in range(tag_count): - tag_name = data_utils.rand_name(self.__class__.__name__ + '-tag') - namespace_tag_names.append({'name': tag_name}) - - if multiple: - namespace_tags = self.namespace_tags_client.create_namespace_tags( - self.namespace, tags=namespace_tag_names)['tags'] - else: - namespace_tags = self.namespace_tags_client.create_namespace_tag( - self.namespace, namespace_tag_names[0]['name']) - - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.namespace_tags_client.delete_namespace_tags, - self.namespace) - - return [nt['name'] for nt in namespace_tags] if multiple \ - else namespace_tags['name'] - - @decorators.idempotent_id('50bedccb-9d0b-4138-8d95-31a89250edf6') - @rbac_rule_validation.action(service="glance", - rules=["add_metadef_tag"]) - def test_create_namespace_tag(self): - with self.override_role(): - self._create_namespace_tag() - - @decorators.idempotent_id('4acf70cc-05da-4b1e-87b2-d5e4475164e7') - @rbac_rule_validation.action(service="glance", - rules=["get_metadef_tag"]) - def test_show_namespace_tag(self): - tag_name = self._create_namespace_tag() - with self.override_role(): - self.namespace_tags_client.show_namespace_tag(self.namespace, - tag_name) - - @decorators.idempotent_id('01593828-3edb-461e-8abc-8fdeb3927e37') - @rbac_rule_validation.action(service="glance", - rules=["modify_metadef_tag"]) - def test_update_namespace_tag(self): - tag_name = self._create_namespace_tag() - updated_tag_name = data_utils.rand_name( - self.__class__.__name__ + '-tag') - - with self.override_role(): - self.namespace_tags_client.update_namespace_tag( - self.namespace, tag_name, name=updated_tag_name) - - @decorators.idempotent_id('20ffaf76-ebdc-4267-a1ad-194346f5cc91') - @rbac_rule_validation.action(service="glance", - rules=["add_metadef_tags"]) - def test_create_namespace_tags(self): - with self.override_role(): - self._create_namespace_tag(multiple=True) - - @decorators.idempotent_id('d37c1501-e787-449d-89b3-754a942a459a') - @rbac_rule_validation.action(service="glance", - rules=["get_metadef_tags"]) - def test_list_namespace_tags(self): - with self.override_role(): - self.namespace_tags_client.list_namespace_tags(self.namespace) diff --git a/patrole_tempest_plugin/tests/api/image/test_image_resource_types_rbac.py b/patrole_tempest_plugin/tests/api/image/test_image_resource_types_rbac.py deleted file mode 100644 index b2780c99..00000000 --- a/patrole_tempest_plugin/tests/api/image/test_image_resource_types_rbac.py +++ /dev/null @@ -1,69 +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.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.image import rbac_base - - -class ImageResourceTypesRbacTest(rbac_base.BaseV2ImageRbacTest): - - @classmethod - def resource_setup(cls): - super(ImageResourceTypesRbacTest, cls).resource_setup() - cls.namespace_name = data_utils.rand_name( - cls.__name__ + '-test-ns') - cls.namespaces_client.create_namespace( - namespace=cls.namespace_name, - protected=False) - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.namespaces_client.delete_namespace, cls.namespace_name) - - @rbac_rule_validation.action(service="glance", - rules=["list_metadef_resource_types"]) - @decorators.idempotent_id('0416fc4d-cfdc-447b-88b6-d9f1dd0382f7') - def test_list_metadef_resource_types(self): - """List Metadef Resource Type Image Test - - RBAC test for the glance list_metadef_resource_type policy. - """ - with self.override_role(): - self.resource_types_client.list_resource_types() - - @rbac_rule_validation.action(service="glance", - rules=["get_metadef_resource_type"]) - @decorators.idempotent_id('3698d53c-71ae-4803-a2c3-c272c054f25c') - def test_get_metadef_resource_type(self): - """Get Metadef Resource Type Image Test - - RBAC test for the glance get_metadef_resource_type policy. - """ - with self.override_role(): - self.resource_types_client.list_resource_type_association( - self.namespace_name) - - @rbac_rule_validation.action( - service="glance", - rules=["add_metadef_resource_type_association"]) - @decorators.idempotent_id('ef9fbc60-3e28-4164-a25c-d30d892f7939') - def test_add_metadef_resource_type(self): - type_name = data_utils.rand_name() - with self.override_role(): - self.resource_types_client.create_resource_type_association( - self.namespace_name, name=type_name) diff --git a/patrole_tempest_plugin/tests/api/image/test_images_member_rbac.py b/patrole_tempest_plugin/tests/api/image/test_images_member_rbac.py deleted file mode 100644 index 18515e23..00000000 --- a/patrole_tempest_plugin/tests/api/image/test_images_member_rbac.py +++ /dev/null @@ -1,124 +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 patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.image import rbac_base as base - - -class ImagesMemberRbacTest(base.BaseV2ImageRbacTest): - - credentials = ['primary', 'alt', 'admin'] - - @classmethod - def resource_setup(cls): - super(ImagesMemberRbacTest, cls).resource_setup() - cls.tenant_id = cls.image_member_client.tenant_id - cls.alt_tenant_id = cls.os_alt.image_member_client_v2.tenant_id - - @classmethod - def setup_clients(cls): - super(ImagesMemberRbacTest, cls).setup_clients() - cls.image_client = cls.os_primary.image_client_v2 - cls.image_member_client = cls.os_primary.image_member_client_v2 - cls.alt_image_member_client = cls.os_alt.image_member_client_v2 - - @rbac_rule_validation.action(service="glance", - rules=["add_member"]) - @decorators.idempotent_id('b1b85ace-6484-11e6-881e-080027d0d606') - def test_add_image_member(self): - - """Add image member - - RBAC test for the glance add_member policy - """ - image_id = self.create_image()['id'] - # Toggle role and add image member - with self.override_role(): - self.image_member_client.create_image_member( - image_id, member=self.alt_tenant_id) - - @rbac_rule_validation.action(service="glance", - rules=["delete_member"]) - @decorators.idempotent_id('ba075234-6484-11e6-881e-080027d0d606') - def test_delete_image_member(self): - - """Delete image member - - RBAC test for the glance delete_member policy - """ - image_id = self.create_image()['id'] - self.image_member_client.create_image_member(image_id, - member=self.alt_tenant_id) - # Toggle role and delete image member - with self.override_role(): - self.image_member_client.delete_image_member(image_id, - self.alt_tenant_id) - - @rbac_rule_validation.action(service="glance", - rules=["get_member"], - expected_error_codes=[404]) - @decorators.idempotent_id('c01fd308-6484-11e6-881e-080027d0d606') - def test_show_image_member(self): - - """Show image member - - RBAC test for the glance get_member policy - """ - image_id = self.create_image()['id'] - self.image_member_client.create_image_member( - image_id, - member=self.alt_tenant_id) - - # Toggle role and get image member - with self.override_role(): - self.image_member_client.show_image_member(image_id, - self.alt_tenant_id) - - @rbac_rule_validation.action(service="glance", - rules=["modify_member"]) - @decorators.idempotent_id('ca448bb2-6484-11e6-881e-080027d0d606') - def test_update_image_member(self): - - """Update image member - - RBAC test for the glance modify_member policy - """ - image_id = self.create_image(visibility='shared')['id'] - self.image_member_client.create_image_member( - image_id, - member=self.alt_tenant_id) - # Toggle role and update member - with self.override_role(): - self.alt_image_member_client.update_image_member( - image_id, self.alt_tenant_id, - status='accepted') - - @rbac_rule_validation.action(service="glance", - rules=["get_members"]) - @decorators.idempotent_id('d0a2dc20-6484-11e6-881e-080027d0d606') - def test_list_image_members(self): - - """List image member - - RBAC test for the glance get_members policy - """ - image_id = self.create_image()['id'] - self.image_member_client.create_image_member(image_id, - member=self.alt_tenant_id) - # Toggle role and list image members - with self.override_role(): - self.image_member_client.list_image_members(image_id) diff --git a/patrole_tempest_plugin/tests/api/image/test_images_rbac.py b/patrole_tempest_plugin/tests/api/image/test_images_rbac.py deleted file mode 100644 index 00292b9e..00000000 --- a/patrole_tempest_plugin/tests/api/image/test_images_rbac.py +++ /dev/null @@ -1,233 +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. - -import six - -from oslo_log import log as logging -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.image import rbac_base - -LOG = logging.getLogger(__name__) - - -class BasicOperationsImagesRbacTest(rbac_base.BaseV2ImageRbacTest): - - @classmethod - def setup_clients(cls): - super(BasicOperationsImagesRbacTest, cls).setup_clients() - cls.image_client = cls.os_primary.image_client_v2 - - def _create_image(self, **kwargs): - image_name = data_utils.rand_name(self.__class__.__name__ + '-Image') - image = self.create_image(name=image_name, - container_format='bare', - disk_format='raw', - **kwargs) - return image - - def _upload_image(self, image_id): - file_content = data_utils.random_bytes() - LOG.debug("Image file content type %s", - type(file_content)) - image_file = six.BytesIO(file_content) - return self.image_client.store_image_file(image_id, image_file) - - @rbac_rule_validation.action(service="glance", - rules=["add_image"]) - @decorators.idempotent_id('0f148510-63bf-11e6-b348-080027d0d606') - def test_create_image(self): - - """Create Image Test - - RBAC test for the glance create_image endpoint - """ - with self.override_role(): - self._create_image() - - @rbac_rule_validation.action(service="glance", - rules=["upload_image"]) - @decorators.idempotent_id('fdc0c7e2-ad58-4c5a-ba9d-1f6046a5b656') - def test_upload_image(self): - - """Upload Image Test - - RBAC test for the glance upload_image endpoint - """ - image = self._create_image() - - with self.override_role(): - self._upload_image(image['id']) - - @decorators.idempotent_id('f0c268f3-cb51-49aa-9bd5-d30cf647322f') - @rbac_rule_validation.action(service="glance", - rules=["download_image"]) - def test_download_image(self): - - """Download Image Test - - RBAC test for the glance download_image endpoint - """ - image = self._create_image() - self._upload_image(image['id']) - - with self.override_role(): - self.image_client.show_image_file(image['id']) - - @rbac_rule_validation.action(service="glance", - rules=["delete_image"]) - @decorators.idempotent_id('3b5c341e-645b-11e6-ac4f-080027d0d606') - def test_delete_image(self): - - """Delete created image - - RBAC test for the glance delete_image endpoint - """ - image = self._create_image() - - with self.override_role(): - self.image_client.delete_image(image['id']) - self.image_client.wait_for_resource_deletion(image['id']) - - @rbac_rule_validation.action(service="glance", - rules=["get_image"]) - @decorators.idempotent_id('3085c7c6-645b-11e6-ac4f-080027d0d606') - def test_show_image(self): - - """Get created image - - RBAC test for the glance create_image endpoint - """ - image = self._create_image() - - with self.override_role(): - self.image_client.show_image(image['id']) - - @rbac_rule_validation.action(service="glance", - rules=["get_images"]) - @decorators.idempotent_id('bf1a4e94-645b-11e6-ac4f-080027d0d606') - def test_list_images(self): - - """List all the images - - RBAC test for the glance list_images endpoint - """ - with self.override_role(): - self.image_client.list_images()['images'] - - @rbac_rule_validation.action(service="glance", - rules=["modify_image"]) - @decorators.idempotent_id('32ecf48c-645e-11e6-ac4f-080027d0d606') - def test_update_image(self): - - """Update given images - - RBAC test for the glance update_image endpoint - """ - image = self._create_image() - - updated_image_name = data_utils.rand_name( - self.__class__.__name__ + '-image') - with self.override_role(): - self.image_client.update_image(image['id'], [ - dict(replace='/name', value=updated_image_name)]) - - @decorators.idempotent_id('244050d9-1b9a-446a-b3c5-f26f3ba8eb75') - @rbac_rule_validation.action(service="glance", - rules=["modify_image"]) - def test_create_image_tag(self): - - """Create image tag - - RBAC test for the glance add_image_tag endpoint - """ - image = self._create_image() - - with self.override_role(): - self.image_client.add_image_tag( - image['id'], - data_utils.rand_name(self.__class__.__name__ + '-tag')) - - @decorators.idempotent_id('c4a0bf9c-b78b-48c6-a31f-72c95f943c6e') - @rbac_rule_validation.action(service="glance", - rules=["modify_image"]) - def test_delete_image_tag(self): - - """Delete image tag - - RBAC test for the glance delete_image_tag endpoint - """ - image = self._create_image() - tag_name = data_utils.rand_name(self.__class__.__name__ + '-tag') - self.image_client.add_image_tag(image['id'], tag_name) - - with self.override_role(): - self.image_client.delete_image_tag(image['id'], tag_name) - - @rbac_rule_validation.action(service="glance", - rules=["publicize_image"]) - @decorators.idempotent_id('0ea4809c-6461-11e6-ac4f-080027d0d606') - def test_publicize_image(self): - - """Publicize Image Test - - RBAC test for the glance publicize_image endpoint - """ - with self.override_role(): - self._create_image(visibility='public') - - @decorators.idempotent_id('0f2d8427-134a-4d3c-a102-5fcdf5443d09') - @rbac_rule_validation.action(service="glance", - rules=["communitize_image"]) - def test_communitize_image(self): - - """Communitize Image Test - - RBAC test for the glance communitize_image policy - """ - with self.override_role(): - self._create_image(visibility='community') - - @rbac_rule_validation.action(service="glance", - rules=["deactivate"]) - @decorators.idempotent_id('b488458c-65df-11e6-9947-080027824017') - def test_deactivate_image(self): - - """Deactivate Image Test - - RBAC test for the glance deactivate_image endpoint - """ - image = self._create_image() - self._upload_image(image['id']) - - with self.override_role(): - self.image_client.deactivate_image(image['id']) - - @rbac_rule_validation.action(service="glance", - rules=["reactivate"]) - @decorators.idempotent_id('d3fa28b8-65df-11e6-9947-080027824017') - def test_reactivate_image(self): - - """Reactivate Image Test - - RBAC test for the glance reactivate_image endpoint - """ - image = self._create_image() - self._upload_image(image['id']) - - with self.override_role(): - self.image_client.reactivate_image(image['id']) diff --git a/patrole_tempest_plugin/tests/api/network/README.rst b/patrole_tempest_plugin/tests/api/network/README.rst deleted file mode 100644 index 6eaae080..00000000 --- a/patrole_tempest_plugin/tests/api/network/README.rst +++ /dev/null @@ -1,47 +0,0 @@ -.. _network-rbac-tests: - -Network RBAC Tests -================== - -What are these tests? ---------------------- - -These tests are RBAC tests for Neutron and its associated plugins. They are -broken up into the following categories: - -* :ref:`neutron-rbac-tests` -* :ref:`neutron-extension-rbac-tests` - -.. _neutron-rbac-tests: - -Neutron tests -^^^^^^^^^^^^^ - -Neutron RBAC tests inherit from the base class ``BaseNetworkRbacTest``. They -test many of the Neutron policies found in the service's `policy.json file`_. -These tests are gated in many `Zuul jobs`_ (master, n-1, n-2) against many -roles (member, admin). - -.. _neutron-extension-rbac-tests: - -Neutron extension tests -^^^^^^^^^^^^^^^^^^^^^^^ - -The Neutron RBAC plugin tests focus on testing RBAC for various Neutron -extensions, or, stated differently: tests that rely on -`neutron-tempest-plugin`_. - -These tests inherit from the base class ``BaseNetworkExtRbacTest``. If an -extension or plugin is not enabled in the cloud, the corresponding tests are -gracefully skipped. - -.. note:: - - Patrole should import as few dependencies from ``neutron_tempest_plugin`` as - possible (such as ``neutron_tempest_plugin.api.clients`` for the service - clients) because the module is not a `stable interface`_. - -.. _policy.json file: https://git.openstack.org/cgit/openstack/neutron/tree/etc/policy.json?h=12.0.0 -.. _Zuul jobs: https://git.openstack.org/cgit/openstack/patrole/tree/.zuul.yaml -.. _neutron-tempest-plugin: https://git.openstack.org/cgit/openstack/neutron-tempest-plugin -.. _stable interface: https://git.openstack.org/cgit/openstack/neutron-tempest-plugin/plain/neutron_tempest_plugin/README.rst diff --git a/patrole_tempest_plugin/tests/api/network/__init__.py b/patrole_tempest_plugin/tests/api/network/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/api/network/rbac_base.py b/patrole_tempest_plugin/tests/api/network/rbac_base.py deleted file mode 100644 index ca94e5f4..00000000 --- a/patrole_tempest_plugin/tests/api/network/rbac_base.py +++ /dev/null @@ -1,84 +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 oslo_serialization import jsonutils as json - -from tempest.api.network import base as network_base -from tempest.lib.common.utils import test_utils - -from patrole_tempest_plugin import rbac_utils - - -class BaseNetworkRbacTest(rbac_utils.RbacUtilsMixin, - network_base.BaseNetworkTest): - pass - - -class BaseNetworkExtRbacTest(BaseNetworkRbacTest): - """Base class to be used with tests that require neutron-tempest-plugin. - """ - - @classmethod - def get_auth_providers(cls): - """Register auth_provider from neutron-tempest-plugin. - """ - providers = super(BaseNetworkExtRbacTest, cls).get_auth_providers() - if cls.is_neutron_tempest_plugin_available(): - providers.append(cls.ntp_client.auth_provider) - return providers - - @classmethod - def skip_checks(cls): - super(BaseNetworkExtRbacTest, cls).skip_checks() - - if not cls.is_neutron_tempest_plugin_available(): - msg = ("neutron-tempest-plugin not installed.") - raise cls.skipException(msg) - - @classmethod - def is_neutron_tempest_plugin_available(cls): - try: - import neutron_tempest_plugin # noqa - return True - except ImportError: - return False - - @classmethod - def get_client_manager(cls, credential_type=None, roles=None, - force_new=None): - manager = super(BaseNetworkExtRbacTest, cls).get_client_manager( - credential_type=credential_type, - roles=roles, - force_new=force_new - ) - - # Import neutron-tempest-plugin clients - if cls.is_neutron_tempest_plugin_available(): - from neutron_tempest_plugin.api import clients - neutron_tempest_manager = clients.Manager(manager.credentials) - neutron_tempest_manager.auth_provider.set_auth() - cls.ntp_client = neutron_tempest_manager.network_client - - return manager - - @classmethod - def create_service_profile(cls): - service_profile = cls.ntp_client.create_service_profile( - metainfo=json.dumps({'foo': 'bar'})) - service_profile_id = service_profile["service_profile"]["id"] - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.ntp_client.delete_service_profile, service_profile_id) - return service_profile_id diff --git a/patrole_tempest_plugin/tests/api/network/test_address_scope_rbac.py b/patrole_tempest_plugin/tests/api/network/test_address_scope_rbac.py deleted file mode 100644 index 9ca52b4f..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_address_scope_rbac.py +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2018 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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class AddressScopeExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(AddressScopeExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('address-scope', 'network'): - msg = "address-scope extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(AddressScopeExtRbacTest, cls).resource_setup() - cls.network = cls.create_network() - - def _create_address_scope(self, name=None, **kwargs): - name = name or data_utils.rand_name(self.__class__.__name__) - address_scope = self.ntp_client.create_address_scope(name=name, - ip_version=6, - **kwargs) - address_scope = address_scope['address_scope'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_address_scope, - address_scope['id']) - return address_scope - - @rbac_rule_validation.action(service="neutron", - rules=["create_address_scope"], - expected_error_codes=[403]) - @decorators.idempotent_id('8cb2d6b5-23c2-4648-997b-7a6ae55be3ad') - def test_create_address_scope(self): - - """Create Address Scope - - RBAC test for the neutron create_address_scope policy - """ - with self.override_role(): - self._create_address_scope() - - @rbac_rule_validation.action(service="neutron", - rules=["create_address_scope", - "create_address_scope:shared"], - expected_error_codes=[403, 403]) - @decorators.idempotent_id('0c3f55c0-6ebe-4251-afca-62c5cb4632ca') - def test_create_address_scope_shared(self): - - """Create Shared Address Scope - - RBAC test for the neutron create_address_scope:shared policy - """ - with self.override_role(): - self._create_address_scope(shared=True) - - @rbac_rule_validation.action(service="neutron", - rules=["get_address_scope"], - expected_error_codes=[404]) - @decorators.idempotent_id('a53f741b-46f6-412f-936f-ac920d449da8') - def test_get_address_scope(self): - - """Get Address Scope - - RBAC test for the neutron get_address_scope policy - """ - address_scope = self._create_address_scope() - with self.override_role(): - self.ntp_client.show_address_scope(address_scope['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_address_scope", - "update_address_scope"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('3ce4d606-e067-4ef5-840f-96c680226e73') - def test_update_address_scope(self): - - """Update Address Scope - - RBAC test for neutron update_address_scope policy - """ - address_scope = self._create_address_scope() - name = data_utils.rand_name(self.__class__.__name__) - with self.override_role(): - self.ntp_client.update_address_scope(address_scope['id'], - name=name) - - @rbac_rule_validation.action(service="neutron", - rules=["get_address_scope", - "update_address_scope", - "update_address_scope:shared"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('77d3a9d2-721a-4d9f-9654-6b52f113df85') - def test_update_address_scope_shared(self): - - """Update Shared Address Scope - - RBAC test for neutron update_address_scope:shared policy - """ - address_scope = self._create_address_scope(shared=True) - with self.override_role(): - self.ntp_client.update_address_scope(address_scope['id'], - shared=True) - - @rbac_rule_validation.action(service="neutron", - rules=["get_address_scope", - "delete_address_scope"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('277d8e47-e498-4452-b969-a91f747296ba') - def test_delete_address_scope(self): - - """Delete Address Scope - - RBAC test for neutron delete_address_scope policy - """ - address_scope = self._create_address_scope() - with self.override_role(): - self.ntp_client.delete_address_scope(address_scope['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_address_scope"]) - @decorators.idempotent_id('c093fd34-96ee-4abe-8fa5-916dc29653e3') - def test_list_address_scopes(self): - """List Address Scopes - - RBAC test for the neutron ``list_address_scopes`` function and - the ``get_address_scope`` policy - """ - admin_resource_id = self._create_address_scope()['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.ntp_client.list_address_scopes( - id=admin_resource_id)["address_scopes"] diff --git a/patrole_tempest_plugin/tests/api/network/test_agents_rbac.py b/patrole_tempest_plugin/tests/api/network/test_agents_rbac.py deleted file mode 100644 index 3a341289..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_agents_rbac.py +++ /dev/null @@ -1,285 +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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class AgentsRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def skip_checks(cls): - super(AgentsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('agent', 'network'): - msg = "agent extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(AgentsRbacTest, cls).resource_setup() - agents = cls.agents_client.list_agents()['agents'] - cls.agent = agents[0] - - @decorators.idempotent_id('f88e38e0-ab52-4b97-8ffa-48a27f9d199b') - @rbac_rule_validation.action(service="neutron", - rules=["get_agent"], - expected_error_codes=[404]) - def test_show_agent(self): - """Show agent test. - - RBAC test for the neutron get_agent policy - """ - with self.override_role(): - self.agents_client.show_agent(self.agent['id']) - - @decorators.idempotent_id('8ca68fdb-eaf6-4880-af82-ba0982949dec') - @rbac_rule_validation.action(service="neutron", - rules=["get_agent", "update_agent"], - expected_error_codes=[404, 403]) - def test_update_agent(self): - """Update agent test. - - RBAC test for the neutron update_agent policy - """ - original_status = self.agent['admin_state_up'] - agent_status = {'admin_state_up': original_status} - - with self.override_role(): - self.agents_client.update_agent(agent_id=self.agent['id'], - agent=agent_status) - - @decorators.idempotent_id('f7a085e2-71b1-4d39-be3e-fea4bc10ccb8') - @rbac_rule_validation.action(service="neutron", rules=["get_agent"]) - def test_list_agents(self): - """List agents test. - - RBAC test for the neutron ``list_agents`` function and - the ``get_agent`` policy - """ - admin_resource_id = self.agent['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.agents_client.list_agents( - id=admin_resource_id)["agents"] - - -class L3AgentSchedulerRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def skip_checks(cls): - super(L3AgentSchedulerRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('l3_agent_scheduler', 'network'): - msg = "l3_agent_scheduler extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(L3AgentSchedulerRbacTest, cls).resource_setup() - cls.router = cls.create_router() - cls.agent = None - - def setUp(self): - super(L3AgentSchedulerRbacTest, self).setUp() - if self.agent is not None: - return - - # Find an agent and validate that it is correct. - agents = self.agents_client.list_agents()['agents'] - agent = {'agent_type': None} - for a in agents: - if a['agent_type'] == 'L3 agent': - agent = a - break - self.assertEqual(agent['agent_type'], 'L3 agent', 'Could not find ' - 'L3 agent in agent list though l3_agent_scheduler ' - 'is enabled.') - self.agent = agent - - @decorators.idempotent_id('5d2bbdbc-40a5-43d2-828a-84dc93fcc453') - @rbac_rule_validation.action(service="neutron", - rules=["get_l3-routers"]) - def test_list_routers_on_l3_agent(self): - """List routers on L3 agent test. - - RBAC test for the neutron get_l3-routers policy - """ - with self.override_role(): - self.agents_client.list_routers_on_l3_agent(self.agent['id']) - - @decorators.idempotent_id('466b2a10-8747-4c09-855a-bd90a1c86ce7') - @rbac_rule_validation.action(service="neutron", - rules=["create_l3-router"]) - def test_create_router_on_l3_agent(self): - """Create router on L3 agent test. - - RBAC test for the neutron create_l3-router policy - """ - with self.override_role(): - self.agents_client.create_router_on_l3_agent( - self.agent['id'], router_id=self.router['id']) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.agents_client.delete_router_from_l3_agent, - self.agent['id'], router_id=self.router['id']) - - @decorators.idempotent_id('8138cfc9-3e48-4a34-adf6-894077aa1be4') - @rbac_rule_validation.action(service="neutron", - rules=["delete_l3-router"]) - def test_delete_router_from_l3_agent(self): - """Delete router from L3 agent test. - - RBAC test for the neutron delete_l3-router policy - """ - self.agents_client.create_router_on_l3_agent( - self.agent['id'], router_id=self.router['id']) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.agents_client.delete_router_from_l3_agent, - self.agent['id'], router_id=self.router['id']) - - with self.override_role(): - self.agents_client.delete_router_from_l3_agent( - self.agent['id'], router_id=self.router['id']) - - -class DHCPAgentSchedulersRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def skip_checks(cls): - super(DHCPAgentSchedulersRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('dhcp_agent_scheduler', 'network'): - msg = "dhcp_agent_scheduler extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(DHCPAgentSchedulersRbacTest, cls).resource_setup() - cls.agent = None - - def setUp(self): - super(DHCPAgentSchedulersRbacTest, self).setUp() - if self.agent is not None: - return - - # Find a DHCP agent and validate that it is correct. - agents = self.agents_client.list_agents()['agents'] - agent = {'agent_type': None} - for a in agents: - if a['agent_type'] == 'DHCP agent': - agent = a - break - self.assertEqual(agent['agent_type'], 'DHCP agent', 'Could not find ' - 'DHCP agent in agent list though dhcp_agent_scheduler' - ' is enabled.') - self.agent = agent - - def _create_and_prepare_network_for_agent(self, agent_id): - """Create network and ensure it is not hosted by agent_id.""" - network_id = self.create_network()['id'] - - if self._check_network_in_dhcp_agent(network_id, agent_id): - self.agents_client.delete_network_from_dhcp_agent( - agent_id=agent_id, network_id=network_id) - - return network_id - - def _check_network_in_dhcp_agent(self, network_id, agent_id): - networks = self.agents_client.list_networks_hosted_by_one_dhcp_agent( - agent_id)['networks'] or [] - return network_id in [network['id'] for network in networks] - - @decorators.idempotent_id('dc84087b-4c2a-4878-8ed0-40370e19da17') - @rbac_rule_validation.action(service="neutron", - rules=["get_dhcp-networks"]) - def test_list_networks_hosted_by_one_dhcp_agent(self): - """List networks hosted by one DHCP agent test. - - RBAC test for the neutron get_dhcp-networks policy - """ - with self.override_role(): - self.agents_client.list_networks_hosted_by_one_dhcp_agent( - self.agent['id']) - - @decorators.idempotent_id('14e014ac-f355-46d3-b6d8-98f2c9ec1610') - @rbac_rule_validation.action(service="neutron", - rules=["create_dhcp-network"]) - def test_add_dhcp_agent_to_network(self): - """Add DHCP agent to network test. - - RBAC test for the neutron create_dhcp-network policy - """ - network_id = self._create_and_prepare_network_for_agent( - self.agent['id']) - - with self.override_role(): - self.agents_client.add_dhcp_agent_to_network( - self.agent['id'], network_id=network_id) - # Clean up is not necessary and might result in 409 being raised. - - @decorators.idempotent_id('937a4302-4b49-407d-9980-5843d7badc38') - @rbac_rule_validation.action(service="neutron", - rules=["delete_dhcp-network"]) - def test_delete_network_from_dhcp_agent(self): - """Delete DHCP agent from network test. - - RBAC test for the neutron delete_dhcp-network policy - """ - network_id = self._create_and_prepare_network_for_agent( - self.agent['id']) - self.agents_client.add_dhcp_agent_to_network( - self.agent['id'], network_id=network_id) - # Clean up is not necessary and might result in 409 being raised. - - with self.override_role(): - self.agents_client.delete_network_from_dhcp_agent( - self.agent['id'], network_id=network_id) - - -class L3AgentsExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(L3AgentsExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('l3_agent_scheduler', 'network'): - msg = "l3_agent_scheduler extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(L3AgentsExtRbacTest, cls).resource_setup() - name = data_utils.rand_name(cls.__name__ + '-Router') - cls.router = cls.ntp_client.create_router(name)['router'] - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.ntp_client.delete_router, - cls.router['id']) - - @decorators.idempotent_id('5d2bbdbc-40a5-43d2-828a-84dc93bcd321') - @rbac_rule_validation.action(service="neutron", - rules=["get_l3-agents"]) - def test_list_l3_agents_on_router(self): - """List L3 agents on router test. - - RBAC test for the neutron get_l3-agents policy - """ - with self.override_role(): - # NOTE: It is not empty list since it's a special case where - # policy.enforce is called from the controller. - self.ntp_client.list_l3_agents_hosting_router(self.router['id']) diff --git a/patrole_tempest_plugin/tests/api/network/test_auto_allocated_topology_rbac.py b/patrole_tempest_plugin/tests/api/network/test_auto_allocated_topology_rbac.py deleted file mode 100644 index aee5e99f..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_auto_allocated_topology_rbac.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2018 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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class AutoAllocationTopologyExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(AutoAllocationTopologyExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('auto-allocated-topology', - 'network'): - msg = "auto-allocated-topology extension not enabled." - raise cls.skipException(msg) - - @decorators.idempotent_id('299CB831-F6B2-49CA-882B-E9A8E36945A2') - @rbac_rule_validation.action(service="neutron", - rules=["get_auto_allocated_topology"], - expected_error_codes=[404]) - def test_show_auto_allocated_topology(self): - """Test show auto_allocated_topology. - - RBAC test for the neutron "get_auto_allocated_topology" policy - """ - with self.override_role(): - self.ntp_client.get_auto_allocated_topology( - tenant_id=self.os_primary.credentials.tenant_id) - - # Auto allocated topology has to be deleted here because - # Neutron provisions new auto allocated topology for a project - # when: - # - receives GET request for auto allocated topology and - # - there is no auto allocated topology already associated - # with the project. - self.ntp_client.delete_auto_allocated_topology( - tenant_id=self.os_primary.credentials.tenant_id) - - def _ensure_network_not_in_use(cls, network_id): - ports = cls.ntp_client.list_ports(network_id=network_id)["ports"] - - # Every subnet within network should have a router interface - expected_ports_count = len( - cls.ntp_client.show_network(network_id)["network"]["subnets"]) - # Every network should have a single dhcp interface - expected_ports_count += 1 - - if len(ports) != expected_ports_count: - msg = "Auto Allocated Topology in use." - raise cls.skipException(msg) - - @decorators.idempotent_id('A0606AFE-065E-4C09-8E51-58EE7FBA30A2') - @decorators.attr(type='slow') - @rbac_rule_validation.action(service="neutron", - rules=["get_auto_allocated_topology", - "delete_auto_allocated_topology"], - expected_error_codes=[404, 403]) - def test_delete_auto_allocated_topology(self): - """Test delete auto_allocated_topology. - - RBAC test for the neutron "delete_auto_allocated_topology" policy - """ - tenant_id = self.os_primary.credentials.tenant_id - net_id = self.ntp_client.get_auto_allocated_topology( - tenant_id=tenant_id)["auto_allocated_topology"]["id"] - - self._ensure_network_not_in_use(net_id) - - with self.override_role(): - self.ntp_client.delete_auto_allocated_topology( - tenant_id=self.os_primary.credentials.tenant_id) diff --git a/patrole_tempest_plugin/tests/api/network/test_availability_zones_rbac.py b/patrole_tempest_plugin/tests/api/network/test_availability_zones_rbac.py deleted file mode 100644 index b5331e3b..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_availability_zones_rbac.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2018 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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class AvailabilityZoneExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(AvailabilityZoneExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('availability_zone', - 'network'): - msg = "network_availability_zone extension not enabled." - raise cls.skipException(msg) - - @rbac_rule_validation.action(service="neutron", - rules=["get_availability_zone"]) - @decorators.idempotent_id('3c521be8-c32e-11e8-a611-080027758b73') - def test_list_availability_zone_rbac(self): - - """List all available zones. - - RBAC test for the neutron ``list_availability_zones`` - function and the ``get_availability_zone`` policy - """ - admin_resources = (self.ntp_client.list_availability_zones() - ["availability_zones"]) - with self.override_role_and_validate_list( - admin_resources=admin_resources) as ctx: - ctx.resources = (self.ntp_client.list_availability_zones() - ['availability_zones']) diff --git a/patrole_tempest_plugin/tests/api/network/test_dscp_marking_rule_rbac.py b/patrole_tempest_plugin/tests/api/network/test_dscp_marking_rule_rbac.py deleted file mode 100644 index 444dcd29..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_dscp_marking_rule_rbac.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright 2018 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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class DscpMarkingRuleExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(DscpMarkingRuleExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('qos', 'network'): - msg = "qos extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(DscpMarkingRuleExtRbacTest, cls).resource_setup() - name = data_utils.rand_name(cls.__name__ + '-qos') - cls.policy_id = cls.ntp_client.create_qos_policy( - name=name)["policy"]["id"] - cls.addClassResourceCleanup( - cls.ntp_client.delete_qos_policy, cls.policy_id) - - def create_policy_dscp_marking_rule(cls): - rule = cls.ntp_client.create_dscp_marking_rule(cls.policy_id, 10) - rule_id = rule['dscp_marking_rule']['id'] - cls.addCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.ntp_client.delete_dscp_marking_rule, cls.policy_id, rule_id) - return rule_id - - @decorators.idempotent_id('2717AB75-E4CF-4CA4-AF04-5BEC0C808AA5') - @rbac_rule_validation.action(service="neutron", - rules=["create_policy_dscp_marking_rule"]) - def test_create_policy_dscp_marking_rule(self): - """Create policy_dscp_marking_rule. - - RBAC test for the neutron "create_policy_dscp_marking_rule" policy - """ - - with self.override_role(): - self.create_policy_dscp_marking_rule() - - @decorators.idempotent_id('3D68F50E-B948-4B25-8A72-F6F4890BBC6F') - @rbac_rule_validation.action(service="neutron", - rules=["get_policy_dscp_marking_rule"], - expected_error_codes=[404]) - def test_show_policy_dscp_marking_rule(self): - """Show policy_dscp_marking_rule. - - RBAC test for the neutron "get_policy_dscp_marking_rule" policy - """ - rule_id = self.create_policy_dscp_marking_rule() - - with self.override_role(): - self.ntp_client.show_dscp_marking_rule(self.policy_id, rule_id) - - @decorators.idempotent_id('33830794-8731-45C3-BC97-17718555DD7C') - @rbac_rule_validation.action(service="neutron", - rules=["get_policy_dscp_marking_rule", - "update_policy_dscp_marking_rule"], - expected_error_codes=[404, 403]) - def test_update_policy_dscp_marking_rule(self): - """Update policy_dscp_marking_rule. - - RBAC test for the neutron "update_policy_dscp_marking_rule" policy - """ - rule_id = self.create_policy_dscp_marking_rule() - - with self.override_role(): - self.ntp_client.update_dscp_marking_rule( - self.policy_id, rule_id, dscp_mark=16) - - @decorators.idempotent_id('7BF564DD-3648-4D12-8A8B-6D5E576D1843') - @rbac_rule_validation.action(service="neutron", - rules=["get_policy_dscp_marking_rule", - "delete_policy_dscp_marking_rule"], - expected_error_codes=[404, 403]) - def test_delete_policy_dscp_marking_rule(self): - """Delete policy_dscp_marking_rule. - - RBAC test for the neutron "delete_policy_dscp_marking_rule" policy - """ - rule_id = self.create_policy_dscp_marking_rule() - - with self.override_role(): - self.ntp_client.delete_dscp_marking_rule(self.policy_id, rule_id) - - @decorators.idempotent_id('c012fd4f-3a3e-4af4-9075-dd3e170daecd') - @rbac_rule_validation.action(service="neutron", - rules=["get_policy_dscp_marking_rule"]) - def test_list_policy_dscp_marking_rules(self): - """List policy_dscp_marking_rules. - - RBAC test for the neutron ``list_dscp_marking_rules`` function and - the ``get_policy_dscp_marking_rule`` policy - """ - admin_resource_id = self.create_policy_dscp_marking_rule() - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.ntp_client.list_dscp_marking_rules( - policy_id=self.policy_id)["dscp_marking_rules"] diff --git a/patrole_tempest_plugin/tests/api/network/test_flavor_service_profile_rbac.py b/patrole_tempest_plugin/tests/api/network/test_flavor_service_profile_rbac.py deleted file mode 100644 index 0ada6ace..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_flavor_service_profile_rbac.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2018 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.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class FlavorsServiceProfileExtRbacTest(base.BaseNetworkExtRbacTest): - @classmethod - def resource_setup(cls): - super(FlavorsServiceProfileExtRbacTest, cls).resource_setup() - providers = cls.ntp_client.list_service_providers() - if not providers["service_providers"]: - raise cls.skipException("No service_providers available.") - cls.service_type = providers["service_providers"][0]["service_type"] - - cls.flavor_id = cls.create_flavor() - cls.service_profile_id = cls.create_service_profile() - - @classmethod - def create_flavor(cls): - flavor = cls.ntp_client.create_flavor(service_type=cls.service_type) - flavor_id = flavor["flavor"]["id"] - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.ntp_client.delete_flavor, flavor_id) - return flavor_id - - def create_flavor_service_profile(self, flavor_id, service_profile_id): - self.ntp_client.create_flavor_service_profile( - flavor_id, service_profile_id) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_flavor_service_profile, - flavor_id, service_profile_id) - - @decorators.idempotent_id('aa84b4c5-0dd6-4c34-aa81-3a76507f9b81') - @rbac_rule_validation.action(service="neutron", - rules=["create_flavor_service_profile"]) - def test_create_flavor_service_profile(self): - """Create flavor_service_profile. - - RBAC test for the neutron "create_flavor_service_profile" policy - """ - with self.override_role(): - self.create_flavor_service_profile(self.flavor_id, - self.service_profile_id) - - @decorators.idempotent_id('3b680d9e-946a-4670-ab7f-0e4576675833') - @rbac_rule_validation.action(service="neutron", - rules=["delete_flavor_service_profile"]) - def test_delete_flavor_service_profile(self): - """Delete flavor_service_profile. - - RBAC test for the neutron "delete_flavor_service_profile" policy - """ - self.create_flavor_service_profile(self.flavor_id, - self.service_profile_id) - - with self.override_role(): - self.ntp_client.delete_flavor_service_profile( - self.flavor_id, self.service_profile_id) diff --git a/patrole_tempest_plugin/tests/api/network/test_flavors_rbac.py b/patrole_tempest_plugin/tests/api/network/test_flavors_rbac.py deleted file mode 100644 index 67e0d1e6..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_flavors_rbac.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright 2018 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.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class FlavorsExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def resource_setup(cls): - super(FlavorsExtRbacTest, cls).resource_setup() - providers = cls.ntp_client.list_service_providers() - if not providers["service_providers"]: - raise cls.skipException("No service_providers available.") - cls.service_type = providers["service_providers"][0]["service_type"] - - @decorators.idempotent_id('2632a61b-831e-4da5-82c8-a5f7d448589b') - @rbac_rule_validation.action(service="neutron", - rules=["create_flavor"]) - def test_create_flavor(self): - """Create flavor. - - RBAC test for the neutron "create_flavor" policy - """ - with self.override_role(): - flavor = self.ntp_client.create_flavor( - service_type=self.service_type) - - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_flavor, flavor["flavor"]["id"]) - - @decorators.idempotent_id('9c53164c-117d-4b44-a5cb-96f08386513f') - @rbac_rule_validation.action(service="neutron", - rules=["get_flavor", - "update_flavor"], - expected_error_codes=[404, 403]) - def test_update_flavor(self): - """Update flavor. - - RBAC test for the neutron "update_flavor" policy - """ - flavor = self.ntp_client.create_flavor(service_type=self.service_type) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_flavor, flavor["flavor"]["id"]) - - name = data_utils.rand_name(self.__class__.__name__ + '-Flavor') - with self.override_role(): - self.ntp_client.update_flavor(flavor["flavor"]["id"], name=name) - - @decorators.idempotent_id('1de15f9e-5080-4259-ab41-e230bb312de8') - @rbac_rule_validation.action(service="neutron", - rules=["get_flavor", - "delete_flavor"], - expected_error_codes=[404, 403]) - def test_delete_flavor(self): - """Delete flavor. - - RBAC test for the neutron "delete_flavor" policy - """ - flavor = self.ntp_client.create_flavor(service_type=self.service_type) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_flavor, flavor["flavor"]["id"]) - - with self.override_role(): - self.ntp_client.delete_flavor(flavor["flavor"]["id"]) - - @decorators.idempotent_id('c2baf35f-e6c1-4833-9114-aadd9b1f6aaa') - @rbac_rule_validation.action(service="neutron", - rules=["get_flavor"], - expected_error_codes=[404]) - def test_show_flavor(self): - """Show flavor. - - RBAC test for the neutron "get_flavor" policy - """ - flavor = self.ntp_client.create_flavor(service_type=self.service_type) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_flavor, flavor["flavor"]["id"]) - - with self.override_role(): - self.ntp_client.show_flavor(flavor["flavor"]["id"]) - - @decorators.idempotent_id('ab10bd5d-987e-4255-966f-947670ffd0fa') - @rbac_rule_validation.action(service="neutron", - rules=["get_flavor"]) - def test_list_flavors(self): - """List flavors. - - RBAC test for the neutron "get_flavor" policy for "list_flavors" action - """ - flavor = self.ntp_client.create_flavor(service_type=self.service_type) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_flavor, flavor["flavor"]["id"]) - - with self.override_role_and_validate_list( - admin_resource_id=flavor["flavor"]["id"] - ) as ctx: - ctx.resources = self.ntp_client.list_flavors()['flavors'] diff --git a/patrole_tempest_plugin/tests/api/network/test_floating_ips_rbac.py b/patrole_tempest_plugin/tests/api/network/test_floating_ips_rbac.py deleted file mode 100644 index b580cb05..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_floating_ips_rbac.py +++ /dev/null @@ -1,146 +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. - -import netaddr - -from tempest import config -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - -CONF = config.CONF - - -class FloatingIpsRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def resource_setup(cls): - super(FloatingIpsRbacTest, cls).resource_setup() - # Create an external network for floating ip creation. - cls.fip_extnet = cls.create_network(**{'router:external': True}) - # Update router:external attribute to False for proper subnet resource - # cleanup by base class. - cls.fip_extnet_id = cls.fip_extnet['id'] - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.networks_client.update_network, cls.fip_extnet_id, - **{'router:external': False}) - - # Create a subnet for the external network - cls.cidr = netaddr.IPNetwork(CONF.network.project_network_cidr) - cls.create_subnet(cls.fip_extnet, - cidr=cls.cidr, - mask_bits=24) - - def _create_floatingip(self, floating_ip_address=None): - if floating_ip_address is not None: - body = self.floating_ips_client.create_floatingip( - floating_network_id=self.fip_extnet_id, - floating_ip_address=floating_ip_address) - else: - body = self.floating_ips_client.create_floatingip( - floating_network_id=self.fip_extnet_id) - - floating_ip = body['floatingip'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.floating_ips_client.delete_floatingip, - floating_ip['id']) - - return floating_ip - - @rbac_rule_validation.action(service="neutron", - rules=["create_floatingip"]) - @decorators.idempotent_id('f8f7474c-b8a5-4174-af84-73097d6ced38') - def test_create_floating_ip(self): - """Create floating IP. - - RBAC test for the neutron create_floatingip policy - """ - with self.override_role(): - self._create_floatingip() - - @rbac_rule_validation.action( - service="neutron", - rules=["create_floatingip", - "create_floatingip:floating_ip_address"]) - @decorators.idempotent_id('a8bb826a-403d-4130-a55d-120a0a660806') - def test_create_floating_ip_floatingip_address(self): - """Create floating IP with address. - - RBAC test for the neutron create_floatingip:floating_ip_address policy - """ - fip = str(netaddr.IPAddress(self.cidr) + 10) - - with self.override_role(): - self._create_floatingip(floating_ip_address=fip) - - @rbac_rule_validation.action(service="neutron", - rules=["get_floatingip", "update_floatingip"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('2ab1b060-19f8-4ef6-a838-e2ab7b377c63') - def test_update_floating_ip(self): - """Update floating IP. - - RBAC test for the neutron update_floatingip policy - """ - floating_ip = self._create_floatingip() - with self.override_role(): - # Associate floating IP to the other port - self.floating_ips_client.update_floatingip( - floating_ip['id'], port_id=None) - - @rbac_rule_validation.action(service="neutron", - rules=["get_floatingip"], - expected_error_codes=[404]) - @decorators.idempotent_id('f8846fd0-c976-48fe-a148-105303931b32') - def test_show_floating_ip(self): - """Show floating IP. - - RBAC test for the neutron get_floatingip policy - """ - floating_ip = self._create_floatingip() - with self.override_role(): - # Show floating IP - self.floating_ips_client.show_floatingip(floating_ip['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_floatingip", "delete_floatingip"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('2611b068-30d4-4241-a78f-1b801a14db7e') - def test_delete_floating_ip(self): - """Delete floating IP. - - RBAC test for the neutron delete_floatingip policy - """ - floating_ip = self._create_floatingip() - with self.override_role(): - # Delete the floating IP - self.floating_ips_client.delete_floatingip(floating_ip['id']) - - @rbac_rule_validation.action(service="neutron", rules=["get_floatingip"]) - @decorators.idempotent_id('824965e3-8be8-46e2-be64-0d793533ad20') - def test_list_floating_ips(self): - """List Floating IPs. - - RBAC test for the neutron ``list_floatingips`` function and - the ``get_floatingip`` policy - """ - admin_resource_id = self._create_floatingip()['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.floating_ips_client.list_floatingips( - id=admin_resource_id)["floatingips"] diff --git a/patrole_tempest_plugin/tests/api/network/test_metering_label_rules_rbac.py b/patrole_tempest_plugin/tests/api/network/test_metering_label_rules_rbac.py deleted file mode 100644 index c0d226d9..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_metering_label_rules_rbac.py +++ /dev/null @@ -1,120 +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.common import utils -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - -CONF = config.CONF - - -class MeteringLabelRulesRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def skip_checks(cls): - super(MeteringLabelRulesRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('metering', 'network'): - msg = "metering extension not enabled." - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(MeteringLabelRulesRbacTest, cls).setup_clients() - cls.metering_labels_client = cls.os_primary.metering_labels_client - cls.metering_label_rules_client = \ - cls.os_primary.metering_label_rules_client - - @classmethod - def resource_setup(cls): - super(MeteringLabelRulesRbacTest, cls).resource_setup() - body = cls.metering_labels_client.create_metering_label( - name=data_utils.rand_name(cls.__name__)) - cls.label = body['metering_label'] - cls.addClassResourceCleanup( - cls.metering_labels_client.delete_metering_label, cls.label['id']) - - def _create_metering_label_rule(self, label): - body = self.metering_label_rules_client.create_metering_label_rule( - metering_label_id=label['id'], - remote_ip_prefix=CONF.network.project_network_cidr, - direction="ingress") - label_rule = body['metering_label_rule'] - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.metering_label_rules_client.delete_metering_label_rule, - label_rule['id']) - return label_rule - - @rbac_rule_validation.action(service="neutron", - rules=["create_metering_label_rule"]) - @decorators.idempotent_id('81e81776-9d41-4d5e-b5c4-59d5c54a31ad') - def test_create_metering_label_rule(self): - """Create metering label rule. - - RBAC test for the neutron create_metering_label_rule policy - """ - with self.override_role(): - self._create_metering_label_rule(self.label) - - @rbac_rule_validation.action(service="neutron", - rules=["get_metering_label_rule"], - expected_error_codes=[404]) - @decorators.idempotent_id('e21b40c3-d44d-412f-84ea-836ca8603bcb') - def test_show_metering_label_rule(self): - """Show metering label rule. - - RBAC test for the neutron get_metering_label_rule policy - """ - label_rule = self._create_metering_label_rule(self.label) - with self.override_role(): - self.metering_label_rules_client.show_metering_label_rule( - label_rule['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_metering_label_rule", - "delete_metering_label_rule"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('e3adc88c-05c0-43a7-8e32-63947ae4890e') - def test_delete_metering_label_rule(self): - """Delete metering label rule. - - RBAC test for the neutron delete_metering_label_rule policy - """ - label_rule = self._create_metering_label_rule(self.label) - with self.override_role(): - self.metering_label_rules_client.delete_metering_label_rule( - label_rule['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_metering_label_rule"]) - @decorators.idempotent_id('eaaf9eb5-ee53-4b6b-a4d3-a721dd39bc40') - def test_list_metering_label_rules(self): - """List metering label rules. - - RBAC test for the neutron ``list_metering_label_rules`` function and - the ``get_metering_label_rule`` policy - """ - admin_resource_id = self._create_metering_label_rule(self.label)['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = ( - self.metering_label_rules_client. - list_metering_label_rules(id=admin_resource_id) - ["metering_label_rules"]) diff --git a/patrole_tempest_plugin/tests/api/network/test_metering_labels_rbac.py b/patrole_tempest_plugin/tests/api/network/test_metering_labels_rbac.py deleted file mode 100644 index 63c47444..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_metering_labels_rbac.py +++ /dev/null @@ -1,102 +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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class MeteringLabelsRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def skip_checks(cls): - super(MeteringLabelsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('metering', 'network'): - msg = "metering extension not enabled." - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(MeteringLabelsRbacTest, cls).setup_clients() - cls.metering_labels_client = cls.os_primary.metering_labels_client - - def _create_metering_label(self): - body = self.metering_labels_client.create_metering_label( - name=data_utils.rand_name(self.__class__.__name__)) - - label = body['metering_label'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.metering_labels_client.delete_metering_label, - label['id']) - return label - - @rbac_rule_validation.action(service="neutron", - rules=["create_metering_label"]) - @decorators.idempotent_id('e8cfc8b8-c159-48f0-93b3-591625a02f8b') - def test_create_metering_label(self): - """Create metering label. - - RBAC test for the neutron "create_metering_label" policy - """ - with self.override_role(): - self._create_metering_label() - - @rbac_rule_validation.action(service="neutron", - rules=["get_metering_label"], - expected_error_codes=[404]) - @decorators.idempotent_id('c57f6636-c702-4755-8eac-5e73bc1f7d14') - def test_show_metering_label(self): - """Show metering label. - - RBAC test for the neutron "get_metering_label" policy - """ - label = self._create_metering_label() - with self.override_role(): - self.metering_labels_client.show_metering_label(label['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_metering_label", - "delete_metering_label"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('1621ccfe-2e3f-4d16-98aa-b620f9d00404') - def test_delete_metering_label(self): - """Delete metering label. - - RBAC test for the neutron "delete_metering_label" policy - """ - label = self._create_metering_label() - with self.override_role(): - self.metering_labels_client.delete_metering_label(label['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_metering_label"]) - @decorators.idempotent_id('d60d72b0-cb8f-44db-b10b-5092fa01cb0e') - def test_list_metering_labels(self): - """List metering label. - - RBAC test for the neutron ``list_metering_labels`` function and - the ``get_metering_label`` policy - """ - admin_resource_id = self._create_metering_label()['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = ( - self.metering_labels_client. - list_metering_labels(id=admin_resource_id) - ["metering_labels"]) diff --git a/patrole_tempest_plugin/tests/api/network/test_network_ip_availability_rbac.py b/patrole_tempest_plugin/tests/api/network/test_network_ip_availability_rbac.py deleted file mode 100644 index 3e33df63..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_network_ip_availability_rbac.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2018 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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class NetworkIpAvailabilityExtRbacTest(base.BaseNetworkExtRbacTest): - @classmethod - def skip_checks(cls): - super(NetworkIpAvailabilityExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('network-ip-availability', - 'network'): - msg = "network-ip-availability extension not enabled." - raise cls.skipException(msg) - - @rbac_rule_validation.action(service="neutron", - rules=["get_network_ip_availability"], - expected_error_codes=[404]) - @decorators.idempotent_id('93edc5ed-385f-4a8e-9b15-4370ec608253') - def test_get_network_ip_availability(self): - """Get network availability - - RBAC test for the neutron get_network_ip_availability policy - """ - - network_name = data_utils.rand_name( - self.__class__.__name__ + '-Network') - network = self.create_network(network_name=network_name) - - with self.override_role(): - self.ntp_client.show_network_ip_availability(network['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_network_ip_availability"]) - @decorators.idempotent_id('d4ceb5f0-2342-4412-a617-4e1aaf7fcaf0') - def test_get_network_ip_availabilities(self): - """List network ip availabilities - - RBAC test for the neutron "get_network_ip_availability" policy - for the "list_network_ip_availabilities" action. - """ - admin_resources = (self.ntp_client.list_network_ip_availabilities() - ["network_ip_availabilities"]) - with self.override_role_and_validate_list( - admin_resources=admin_resources) as ctx: - ctx.resources = (self.ntp_client.list_network_ip_availabilities() - ["network_ip_availabilities"]) diff --git a/patrole_tempest_plugin/tests/api/network/test_network_segments_rbac.py b/patrole_tempest_plugin/tests/api/network/test_network_segments_rbac.py deleted file mode 100644 index aa752ea7..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_network_segments_rbac.py +++ /dev/null @@ -1,121 +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 oslo_log import log - -from tempest.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - -LOG = log.getLogger(__name__) - - -class NetworkSegmentsRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def skip_checks(cls): - super(NetworkSegmentsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('multi-provider', 'network'): - msg = "multi-provider extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(NetworkSegmentsRbacTest, cls).resource_setup() - # Find the network type that is supported by the current cloud by - # checking which network type other networks currently have. This is - # done because there is no tempest.conf option enumerating supported - # network types. - networks = cls.networks_client.list_networks()['networks'] - network_types = [n['provider:network_type'] for n in networks - if n['provider:network_type'] != 'flat'] - if not network_types: - raise cls.skipException( - 'Could not find network with provider:network_type that is ' - 'not "flat".') - cls.network_type = network_types[0] - - def _create_network_segments(self): - segments = [{'provider:network_type': self.network_type}, - {'provider:network_type': self.network_type}] - - body = self.networks_client.create_network( - name=data_utils.rand_name(self.__class__.__name__), - segments=segments) - network = body['network'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.networks_client.delete_network, - network['id']) - return network - - @rbac_rule_validation.action(service="neutron", - rules=["create_network", - "create_network:segments"]) - @decorators.idempotent_id('9e1d0c3d-92e3-40e3-855e-bfbb72ea6e0b') - def test_create_network_segments(self): - """Create network with segments. - - RBAC test for the neutron create_network:segments policy - """ - with self.override_role(): - self._create_network_segments() - - @rbac_rule_validation.action(service="neutron", - rules=["get_network", "update_network", - "update_network:segments"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('0f45232a-7b59-4bb1-9a91-db77d0a8cc9b') - def test_update_network_segments(self): - """Update network segments. - - RBAC test for the neutron update_network:segments policy - """ - network = self._create_network_segments() - new_segments = [{'provider:network_type': self.network_type}] - - with self.override_role(): - self.networks_client.update_network(network['id'], - segments=new_segments) - - @rbac_rule_validation.action(service="neutron", - rules=["get_network", - "get_network:segments"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('094ff9b7-0c3b-4515-b19b-b9d2031337bd') - def test_show_network_segments(self): - """Show network segments. - - RBAC test for the neutron get_network:segments policy - """ - network = self._create_network_segments() - - with self.override_role(): - body = self.networks_client.show_network(network['id'], - fields='segments') - response_network = body['network'] - - # If user does not have access to the network segments attribute, - # no NotFound or Forbidden exception are thrown. Instead, - # the response will have an empty network body only. - if not response_network: - LOG.info("NotFound or Forbidden exception are not thrown when " - "role doesn't have access to the endpoint. Instead, " - "the response will have an empty network body.") - raise rbac_exceptions.RbacEmptyResponseBody() diff --git a/patrole_tempest_plugin/tests/api/network/test_networks_rbac.py b/patrole_tempest_plugin/tests/api/network/test_networks_rbac.py deleted file mode 100644 index a024b2c2..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_networks_rbac.py +++ /dev/null @@ -1,479 +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. - -import netaddr - -from tempest.common import utils -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 - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - -CONF = config.CONF - - -class NetworksRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def resource_setup(cls): - super(NetworksRbacTest, cls).resource_setup() - cls.network = cls.create_network() - cls.cidr = netaddr.IPNetwork(CONF.network.project_network_cidr) - cls.subnet = cls.create_subnet( - cls.network, cidr=cls.cidr, mask_bits=24, enable_dhcp=False) - - def _create_network(self, - router_external=None, - router_private=None, - provider_network_type=None, - provider_physical_network=None, - provider_segmentation_id=None, - **kwargs): - if router_external is not None: - kwargs['router:external'] = router_external - if router_private is not None: - kwargs['router:private'] = router_private - if provider_network_type is not None: - kwargs['provider:network_type'] = provider_network_type - if provider_physical_network is not None: - kwargs['provider:physical_network'] = provider_physical_network - if provider_segmentation_id is not None: - kwargs['provider:segmentation_id'] = provider_segmentation_id - - network_name = data_utils.rand_name( - self.__class__.__name__ + '-Network') - network = self.create_network(network_name=network_name, **kwargs) - return network - - def _update_network(self, - net_id=None, - admin=None, - shared_network=None, - router_external=None, - router_private=None, - provider_network_type=None, - provider_physical_network=None, - provider_segmentation_id=None, - segments=None, - **kwargs): - if not net_id: - net_id = self.network['id'] - - if admin is not None: - kwargs['admin_state_up'] = admin - if shared_network is not None: - kwargs['shared'] = shared_network - if router_external is not None: - kwargs['router:external'] = router_external - if router_private is not None: - kwargs['router:private'] = router_private - if provider_network_type is not None: - kwargs['provider:network_type'] = provider_network_type - if provider_physical_network is not None: - kwargs['provider:physical_network'] = provider_physical_network - if provider_segmentation_id is not None: - kwargs['provider:segmentation_id'] = provider_segmentation_id - if segments is not None: - kwargs['segments'] = segments - - updated_network = self.networks_client.update_network( - net_id, **kwargs)['network'] - return updated_network - - @rbac_rule_validation.action(service="neutron", - rules=["create_network"]) - @decorators.idempotent_id('95b9baab-1ece-4e2b-89c8-8d671d974e54') - def test_create_network(self): - - """Create Network Test - - RBAC test for the neutron create_network policy - """ - with self.override_role(): - self._create_network() - - @rbac_rule_validation.action(service="neutron", - rules=["create_network", - "create_network:is_default"]) - @decorators.idempotent_id('28602661-5ac7-407e-b739-e393f619f5e3') - def test_create_network_is_default(self): - - """Create Is Default Network Test - - RBAC test for the neutron create_network:is_default policy - """ - try: - with self.override_role(): - self._create_network(is_default=True) - except lib_exc.Conflict as exc: - # A default network might already exist - self.assertIn('A default external network already exists', - str(exc)) - - @rbac_rule_validation.action(service="neutron", - rules=["create_network", - "create_network:shared"]) - @decorators.idempotent_id('ccabf2a9-28c8-44b2-80e6-ffd65d43eef2') - def test_create_network_shared(self): - - """Create Shared Network Test - - RBAC test for the neutron create_network:shared policy - """ - with self.override_role(): - self._create_network(shared=True) - - @utils.requires_ext(extension='external-net', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["create_network", - "create_network:router:external"]) - @decorators.idempotent_id('51adf2a7-739c-41e0-8857-3b4c460cbd24') - def test_create_network_router_external(self): - - """Create External Router Network Test - - RBAC test for the neutron create_network:router:external policy - """ - with self.override_role(): - self._create_network(router_external=True) - - @utils.requires_ext(extension='provider', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["create_network", - "create_network:provider:physical_network"]) - @decorators.idempotent_id('76783fed-9ff3-4499-a0d1-82d99eec364e') - def test_create_network_provider_physical_network(self): - - """Create Network Physical Network Provider Test - - RBAC test for neutron create_network:provider:physical_network policy - """ - try: - with self.override_role(): - self._create_network(provider_physical_network='provider', - provider_network_type='flat') - except lib_exc.BadRequest as exc: - # There probably won't be a physical network called 'provider', but - # we aren't testing state of the network - self.assertIn("Invalid input for operation: physical_network " + - "'provider' unknown for flat provider network.", - str(exc)) - - @utils.requires_ext(extension='provider', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["create_network", - "create_network:provider:network_type"]) - @decorators.idempotent_id('3c42f7b8-b80c-44ef-8fa4-69ec4b1836bc') - def test_create_network_provider_network_type(self): - - """Create Provider Network Test - - RBAC test for the neutron create_network:provider:network_type policy - """ - with self.override_role(): - self._create_network(provider_physical_network='public', - provider_network_type='vlan') - - @utils.requires_ext(extension='provider', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["create_network", - "create_network:provider:segmentation_id"]) - @decorators.idempotent_id('b9decb7b-68ef-4504-b99b-41edbf7d2af5') - def test_create_network_provider_segmentation_id(self): - - """Create Provider Network Segmentation Id Test - - RBAC test for the neutron create_network:provider:segmentation_id - """ - with self.override_role(): - self._create_network(provider_physical_network='public', - provider_network_type='vlan', - provider_segmentation_id=200) - - @rbac_rule_validation.action(service="neutron", - rules=["get_network", "update_network"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('6485bb4e-e110-48ae-83e1-3ec8b40c3107') - def test_update_network(self): - - """Update Network Test - - RBAC test for the neutron update_network policy - """ - updated_name = data_utils.rand_name( - self.__class__.__name__ + '-Network') - - with self.override_role(): - self._update_network(name=updated_name) - - @rbac_rule_validation.action(service="neutron", - rules=["get_network", - "update_network", - "update_network:shared"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('37ea3e33-47d9-49fc-9bba-1af98fbd46d6') - def test_update_network_shared(self): - - """Update Shared Network Test - - RBAC test for the neutron update_network:shared policy - """ - with self.override_role(): - self._update_network(shared_network=True) - self.addCleanup(self._update_network, shared_network=False) - - @utils.requires_ext(extension='external-net', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_network", - "update_network", - "update_network:router:external"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('34884c22-499b-4960-97f1-e2ed8522a9c9') - def test_update_network_router_external(self): - - """Update Network Router External Test - - RBAC test for the neutron update_network:router:external policy - """ - network = self._create_network() - with self.override_role(): - self._update_network(net_id=network['id'], router_external=True) - - @decorators.skip_because(bug='2005489', bug_type='storyboard') - @utils.requires_ext(extension='provider', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["get_network", - "update_network", - "update_network:provider:network_type"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('d064ef96-662b-47b6-94b7-9106dcd7ba8c') - def test_update_network_provider_network_type(self): - - """Update Network Provider Network Type Test - - RBAC test for neutron update_network:provider:network_type policy - """ - try: - with self.override_role(): - self._update_network(self.network['id'], - provider_network_type='vlan') - except lib_exc.BadRequest as exc: - # Per the api documentation, most plugins don't support updating - # provider attributes - self.assertIn( - "Plugin does not support updating provider attributes", - str(exc)) - - @decorators.skip_because(bug='2005489', bug_type='storyboard') - @utils.requires_ext(extension='provider', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["get_network", - "update_network", - "update_network:provider:physical_network"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('e3a55660-f75c-494e-a1b1-a8b36cc789ef') - def test_update_network_provider_physical_network(self): - - """Update Network Provider Physical Network Test - - RBAC test for neutron update_network:provider:physical_network policy - """ - try: - with self.override_role(): - self._update_network(self.network['id'], - provider_physical_network='provider') - except lib_exc.BadRequest as exc: - # Per the api documenation, most plugins don't support updating - # provider attributes - self.assertIn( - "Plugin does not support updating provider attributes", - str(exc)) - - @decorators.skip_because(bug='2005489', bug_type='storyboard') - @utils.requires_ext(extension='provider', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["get_network", - "update_network", - "update_network:provider:segmentation_id"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('f6164228-b670-45fd-9ff9-b101930318c7') - def test_update_network_provider_segmentation_id(self): - - """Update Network Provider Segmentation Id Test - - RBAC test for neutron update_network:provider:segmentation_id policy - """ - try: - with self.override_role(): - self._update_network(self.network['id'], - provider_segmentation_id=400) - except lib_exc.BadRequest as exc: - # Per the api documenation, most plugins don't support updating - # provider attributes - self.assertIn( - "Plugin does not support updating provider attributes", - str(exc)) - - @rbac_rule_validation.action(service="neutron", - rules=["get_network"], - expected_error_codes=[404]) - @decorators.idempotent_id('0eb62d04-338a-4ff4-a8fa-534e52110534') - def test_show_network(self): - - """Show Network Test - - RBAC test for the neutron get_network policy - """ - with self.override_role(): - self.networks_client.show_network(self.network['id']) - - @utils.requires_ext(extension='external-net', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_network", - "get_network:router:external"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('529e4814-22e9-413f-af48-8fefcd637344') - def test_show_network_router_external(self): - - """Show Network Router External Test - - RBAC test for the neutron get_network:router:external policy - """ - kwargs = {'fields': 'router:external'} - - with self.override_role(): - retrieved_network = self.networks_client.show_network( - self.network['id'], **kwargs)['network'] - - if len(retrieved_network) == 0: - raise rbac_exceptions.RbacEmptyResponseBody() - - @utils.requires_ext(extension='provider', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_network", - "get_network:provider:network_type"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('6521dd60-0950-458b-8491-09d3c84ac0f4') - def test_show_network_provider_network_type(self): - - """Show Network Prodiver Network Type Test - - RBAC test for the neutron get_network:provider:network_type policy - """ - kwargs = {'fields': 'provider:network_type'} - - with self.override_role(): - retrieved_network = self.networks_client.show_network( - self.network['id'], **kwargs)['network'] - - if len(retrieved_network) == 0: - raise rbac_exceptions.RbacEmptyResponseBody() - - @utils.requires_ext(extension='provider', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["get_network", - "get_network:provider:physical_network"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('c049f11a-240c-4a85-ad43-a4d3fd0a5e39') - def test_show_network_provider_physical_network(self): - - """Show Network Provider Physical Network Test - - RBAC test for the neutron get_network:provider:physical_network policy - """ - kwargs = {'fields': 'provider:physical_network'} - - with self.override_role(): - retrieved_network = self.networks_client.show_network( - self.network['id'], **kwargs)['network'] - - if len(retrieved_network) == 0: - raise rbac_exceptions.RbacEmptyResponseBody() - - @utils.requires_ext(extension='provider', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["get_network", - "get_network:provider:segmentation_id"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('38d9f085-6365-4f81-bac9-c53c294d727e') - def test_show_network_provider_segmentation_id(self): - - """Show Network Provider Segmentation Id Test - - RBAC test for the neutron get_network:provider:segmentation_id policy - """ - kwargs = {'fields': 'provider:segmentation_id'} - - with self.override_role(): - retrieved_network = self.networks_client.show_network( - self.network['id'], **kwargs)['network'] - - if len(retrieved_network) == 0: - raise rbac_exceptions.RbacEmptyResponseBody() - - @rbac_rule_validation.action(service="neutron", - rules=["get_network", "delete_network"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('56ca50ed-ac58-49d6-b239-ed39e7124d5c') - def test_delete_network(self): - - """Delete Network Test - - RBAC test for the neutron delete_network policy - """ - network = self._create_network() - with self.override_role(): - self.networks_client.delete_network(network['id']) - - @utils.requires_ext(extension='dhcp_agent_scheduler', service='network') - @decorators.idempotent_id('b524f19f-fbb4-4d11-a85d-03bfae17bf0e') - @rbac_rule_validation.action(service="neutron", - rules=["get_dhcp-agents"]) - def test_list_dhcp_agents_on_hosting_network(self): - - """List DHCP Agents on Hosting Network Test - - RBAC test for the neutron "get_dhcp-agents" policy - """ - with self.override_role(): - self.networks_client.list_dhcp_agents_on_hosting_network( - self.network['id']) - - @rbac_rule_validation.action(service="neutron", rules=["get_network"]) - @decorators.idempotent_id('53d6d826-ec9a-4407-9362-b474187fae6d') - def test_list_networks(self): - """List Networks - - RBAC test for the neutron ``list_networks`` function and - the ``get_network`` policy - """ - - admin_resource_id = self.network['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.networks_client.list_networks( - id=admin_resource_id)["networks"] diff --git a/patrole_tempest_plugin/tests/api/network/test_policy_bandwidth_limit_rule_rbac.py b/patrole_tempest_plugin/tests/api/network/test_policy_bandwidth_limit_rule_rbac.py deleted file mode 100644 index cd750a07..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_policy_bandwidth_limit_rule_rbac.py +++ /dev/null @@ -1,109 +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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class PolicyBandwidthLimitRuleExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(PolicyBandwidthLimitRuleExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('qos', 'network'): - msg = "qos extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(PolicyBandwidthLimitRuleExtRbacTest, cls).resource_setup() - name = data_utils.rand_name(cls.__name__ + '-qos-policy') - cls.policy_id = cls.ntp_client.create_qos_policy( - name=name)["policy"]["id"] - cls.addClassResourceCleanup(cls.ntp_client.delete_qos_policy, - cls.policy_id) - - def _create_bandwidth_limit_rule(self): - rule = self.ntp_client.create_bandwidth_limit_rule( - self.policy_id, max_kbps=1000, max_burst_kbps=1000, - direction="egress") - rule_id = rule['bandwidth_limit_rule']['id'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_bandwidth_limit_rule, - self.policy_id, rule_id) - return rule_id - - @decorators.idempotent_id('E0FDCB39-E16D-4AF5-9165-3FEFD116E69D') - @rbac_rule_validation.action( - service="neutron", rules=["create_policy_bandwidth_limit_rule"]) - def test_create_policy_bandwidth_limit_rule(self): - """Create bandwidth_limit_rule. - - RBAC test for the neutron "create_policy_bandwidth_limit_rule" policy - """ - - with self.override_role(): - self._create_bandwidth_limit_rule() - - @decorators.idempotent_id('A092BD50-364F-4F55-B81A-37DAD6E77B95') - @rbac_rule_validation.action(service="neutron", - rules=["get_policy_bandwidth_limit_rule"], - expected_error_codes=[404]) - def test_show_policy_bandwidth_limit_rule(self): - """Show bandwidth_limit_rule. - - RBAC test for the neutron "get_policy_bandwidth_limit_rule" policy - """ - rule_id = self._create_bandwidth_limit_rule() - - with self.override_role(): - self.ntp_client.show_bandwidth_limit_rule(self.policy_id, rule_id) - - @decorators.idempotent_id('CAA27599-082B-44B9-AF09-8C9B8E777ED7') - @rbac_rule_validation.action(service="neutron", - rules=["get_policy_bandwidth_limit_rule", - "update_policy_bandwidth_limit_rule"], - expected_error_codes=[404, 403]) - def test_update_policy_bandwidth_limit_rule(self): - """Update bandwidth_limit_rule. - - RBAC test for the neutron "update_policy_bandwidth_limit_rule" policy - """ - rule_id = self._create_bandwidth_limit_rule() - - with self.override_role(): - self.ntp_client.update_bandwidth_limit_rule( - self.policy_id, rule_id, max_kbps=2000) - - @decorators.idempotent_id('BF6D9ED7-4B04-423D-857D-455DB0705852') - @rbac_rule_validation.action(service="neutron", - rules=["get_policy_bandwidth_limit_rule", - "delete_policy_bandwidth_limit_rule"], - expected_error_codes=[404, 403]) - def test_delete_policy_bandwidth_limit_rule(self): - """Delete bandwidth_limit_rule. - - RBAC test for the neutron "delete_policy_bandwidth_limit_rule" policy - """ - rule_id = self._create_bandwidth_limit_rule() - - with self.override_role(): - self.ntp_client.delete_bandwidth_limit_rule(self.policy_id, - rule_id) diff --git a/patrole_tempest_plugin/tests/api/network/test_policy_minimum_bandwidth_rule_rbac.py b/patrole_tempest_plugin/tests/api/network/test_policy_minimum_bandwidth_rule_rbac.py deleted file mode 100644 index 990a3576..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_policy_minimum_bandwidth_rule_rbac.py +++ /dev/null @@ -1,112 +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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class PolicyMinimumBandwidthRuleExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(PolicyMinimumBandwidthRuleExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('qos', 'network'): - msg = "qos extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(PolicyMinimumBandwidthRuleExtRbacTest, cls).resource_setup() - name = data_utils.rand_name(cls.__name__ + '-qos') - cls.policy_id = cls.ntp_client.create_qos_policy( - name=name)["policy"]["id"] - cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc, - cls.ntp_client.delete_qos_policy, - cls.policy_id) - - def create_minimum_bandwidth_rule(self): - rule = self.ntp_client.create_minimum_bandwidth_rule( - self.policy_id, direction="egress", min_kbps=1000) - rule_id = rule['minimum_bandwidth_rule']['id'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_minimum_bandwidth_rule, - self.policy_id, rule_id) - return rule_id - - @decorators.idempotent_id('25B5EF3A-DF2A-4C80-A498-3BE14A321D97') - @rbac_rule_validation.action( - service="neutron", rules=["create_policy_minimum_bandwidth_rule"]) - def test_create_policy_minimum_bandwidth_rule(self): - """Create policy_minimum_bandwidth_rule. - - RBAC test for the neutron "create_policy_minimum_bandwidth_rule" policy - """ - - with self.override_role(): - self.create_minimum_bandwidth_rule() - - @decorators.idempotent_id('01DD902C-47C5-45D2-9A0E-7AF05981DF21') - @rbac_rule_validation.action(service="neutron", - rules=["get_policy_minimum_bandwidth_rule"], - expected_error_codes=[404]) - def test_show_policy_minimum_bandwidth_rule(self): - """Show policy_minimum_bandwidth_rule. - - RBAC test for the neutron "get_policy_minimum_bandwidth_rule" policy - """ - rule_id = self.create_minimum_bandwidth_rule() - - with self.override_role(): - self.ntp_client.show_minimum_bandwidth_rule( - self.policy_id, rule_id) - - @decorators.idempotent_id('50AFE69B-455C-413A-BDC6-26B42DC8D55D') - @rbac_rule_validation.action( - service="neutron", - rules=["get_policy_minimum_bandwidth_rule", - "update_policy_minimum_bandwidth_rule"], - expected_error_codes=[404, 403]) - def test_update_policy_minimum_bandwidth_rule(self): - """Update policy_minimum_bandwidth_rule. - - RBAC test for the neutron "update_policy_minimum_bandwidth_rule" policy - """ - rule_id = self.create_minimum_bandwidth_rule() - - with self.override_role(): - self.ntp_client.update_minimum_bandwidth_rule( - self.policy_id, rule_id, min_kbps=2000) - - @decorators.idempotent_id('2112E325-C3B2-4071-8A93-B218F275A83B') - @rbac_rule_validation.action( - service="neutron", - rules=["get_policy_minimum_bandwidth_rule", - "delete_policy_minimum_bandwidth_rule"], - expected_error_codes=[404, 403]) - def test_delete_policy_minimum_bandwidth_rule(self): - """Delete policy_minimum_bandwidth_rule. - - RBAC test for the neutron "delete_policy_minimum_bandwidth_rule" policy - """ - rule_id = self.create_minimum_bandwidth_rule() - - with self.override_role(): - self.ntp_client.delete_minimum_bandwidth_rule( - self.policy_id, rule_id) diff --git a/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py b/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py deleted file mode 100644 index d699e12f..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py +++ /dev/null @@ -1,404 +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. -# - -import netaddr -import testtools - -from tempest.common import utils -from tempest.common.utils import net_utils -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - -CONF = config.CONF - - -class PortsRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def resource_setup(cls): - super(PortsRbacTest, cls).resource_setup() - # Create a network and subnet. - cls.network = cls.create_network() - cls.cidr = netaddr.IPNetwork(CONF.network.project_network_cidr) - cls.subnet = cls.create_subnet(cls.network, cidr=cls.cidr, - mask_bits=24) - cls.ip_range = netaddr.IPRange( - cls.subnet['allocation_pools'][0]['start'], - cls.subnet['allocation_pools'][0]['end']) - - cls.port = cls.create_port(cls.network) - ipaddr = cls.port['fixed_ips'][0]['ip_address'] - cls.port_ip_address = ipaddr - cls.port_mac_address = cls.port['mac_address'] - - def _get_unused_ip_address(self): - # Pick an unused ip address. - ip_list = net_utils.get_unused_ip_addresses(self.ports_client, - self.subnets_client, - self.network['id'], - self.subnet['id'], - 1) - return ip_list - - @rbac_rule_validation.action(service="neutron", - rules=["create_port"]) - @decorators.idempotent_id('0ec8c551-625c-4864-8a52-85baa7c40f22') - def test_create_port(self): - - with self.override_role(): - self.create_port(self.network) - - @decorators.idempotent_id('045ee797-4962-4913-b96a-5d7ea04099e7') - @rbac_rule_validation.action(service="neutron", - rules=["create_port", - "create_port:device_owner"]) - def test_create_port_device_owner(self): - with self.override_role(): - self.create_port(self.network, - device_owner='network:router_interface') - - @decorators.idempotent_id('c4fa8844-f5ef-4daa-bfa2-b89897dfaedf') - @rbac_rule_validation.action(service="neutron", - rules=["create_port", - "create_port:port_security_enabled"]) - def test_create_port_security_enabled(self): - with self.override_role(): - self.create_port(self.network, port_security_enabled=True) - - @utils.requires_ext(extension='binding', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["create_port", - "create_port:binding:host_id"]) - @decorators.idempotent_id('a54bd6b8-a7eb-4101-bfe8-093930b0d660') - def test_create_port_binding_host_id(self): - - post_body = {'network': self.network, - 'binding:host_id': "rbac_test_host"} - - with self.override_role(): - self.create_port(**post_body) - - @utils.requires_ext(extension='binding', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["create_port", - "create_port:binding:profile"]) - @decorators.idempotent_id('98fa38ab-c2ed-46a0-99f0-59f18cbd257a') - def test_create_port_binding_profile(self): - - binding_profile = {"foo": "1"} - - post_body = {'network': self.network, - 'binding:profile': binding_profile} - - with self.override_role(): - self.create_port(**post_body) - - @testtools.skipUnless( - CONF.policy_feature_enabled.create_port_fixed_ips_ip_address_policy, - '"create_port:fixed_ips:ip_address" must be available in the cloud.') - @rbac_rule_validation.action(service="neutron", - rules=["create_port", - "create_port:fixed_ips:ip_address"]) - @decorators.idempotent_id('2551e10d-006a-413c-925a-8c6f834c09ac') - def test_create_port_fixed_ips_ip_address(self): - - ip_list = self._get_unused_ip_address() - fixed_ips = [{'ip_address': ip_list[0]}, - {'subnet_id': self.subnet['id']}] - - post_body = {'network': self.network, - 'fixed_ips': fixed_ips} - - with self.override_role(): - self.create_port(**post_body) - - @rbac_rule_validation.action(service="neutron", - rules=["create_port", - "create_port:mac_address"]) - @decorators.idempotent_id('aee6d0be-a7f3-452f-aefc-796b4eb9c9a8') - def test_create_port_mac_address(self): - - post_body = {'network': self.network, - 'mac_address': data_utils.rand_mac_address()} - - with self.override_role(): - self.create_port(**post_body) - - @rbac_rule_validation.action(service="neutron", - rules=["create_port", - "create_port:allowed_address_pairs"]) - @decorators.idempotent_id('b638d1f4-d903-4ca8-aa2a-6fd603c5ec3a') - def test_create_port_allowed_address_pairs(self): - - # Create port with allowed address pair attribute - allowed_address_pairs = [{'ip_address': self.port_ip_address, - 'mac_address': self.port_mac_address}] - - post_body = {'network': self.network, - 'allowed_address_pairs': allowed_address_pairs} - - with self.override_role(): - self.create_port(**post_body) - - @rbac_rule_validation.action(service="neutron", - rules=["get_port"], - expected_error_codes=[404]) - @decorators.idempotent_id('a9d41cb8-78a2-4b97-985c-44e4064416f4') - def test_show_port(self): - with self.override_role(): - self.ports_client.show_port(self.port['id']) - - @utils.requires_ext(extension='binding', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_port", - "get_port:binding:vif_type"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('125aff0b-8fed-4f8e-8410-338616594b06') - def test_show_port_binding_vif_type(self): - - # Verify specific fields of a port - fields = ['binding:vif_type'] - - with self.override_role(): - retrieved_port = self.ports_client.show_port( - self.port['id'], fields=fields)['port'] - - # Rather than throwing a 403, the field is not present, so raise exc. - if fields[0] not in retrieved_port: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='binding:vif_type') - - @utils.requires_ext(extension='binding', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_port", - "get_port:binding:vif_details"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('e42bfd77-fcce-45ee-9728-3424300f0d6f') - def test_show_port_binding_vif_details(self): - - # Verify specific fields of a port - fields = ['binding:vif_details'] - - with self.override_role(): - retrieved_port = self.ports_client.show_port( - self.port['id'], fields=fields)['port'] - - # Rather than throwing a 403, the field is not present, so raise exc. - if fields[0] not in retrieved_port: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='binding:vif_details') - - @utils.requires_ext(extension='binding', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_port", - "get_port:binding:host_id"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('8e61bcdc-6f81-443c-833e-44410266551e') - def test_show_port_binding_host_id(self): - - # Verify specific fields of a port - fields = ['binding:host_id'] - post_body = {'network': self.network, - 'binding:host_id': data_utils.rand_name('host-id')} - port = self.create_port(**post_body) - - with self.override_role(): - retrieved_port = self.ports_client.show_port( - port['id'], fields=fields)['port'] - - # Rather than throwing a 403, the field is not present, so raise exc. - if fields[0] not in retrieved_port: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='binding:host_id') - - @utils.requires_ext(extension='binding', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_port", - "get_port:binding:profile"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('d497cea9-c4ad-42e0-acc9-8d257d6b01fc') - def test_show_port_binding_profile(self): - - # Verify specific fields of a port - fields = ['binding:profile'] - binding_profile = {"foo": "1"} - post_body = {'network': self.network, - 'binding:profile': binding_profile} - port = self.create_port(**post_body) - - with self.override_role(): - retrieved_port = self.ports_client.show_port( - port['id'], fields=fields)['port'] - - # Rather than throwing a 403, the field is not present, so raise exc. - if fields[0] not in retrieved_port: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='binding:profile') - - @rbac_rule_validation.action(service="neutron", - rules=["get_port", "update_port"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('afa80981-3c59-42fd-9531-3bcb2cd03711') - def test_update_port(self): - with self.override_role(): - self.ports_client.update_port(self.port['id'], - admin_state_up=False) - self.addCleanup(self.ports_client.update_port, self.port['id'], - admin_state_up=True) - - @decorators.idempotent_id('08d70f59-67cb-4fb1-bd6c-a5e59dd5db2b') - @rbac_rule_validation.action(service="neutron", - rules=["get_port", "update_port", - "update_port:device_owner"], - expected_error_codes=[404, 403, 403]) - def test_update_port_device_owner(self): - original_device_owner = self.port['device_owner'] - - with self.override_role(): - self.ports_client.update_port( - self.port['id'], device_owner='network:router_interface') - self.addCleanup(self.ports_client.update_port, self.port['id'], - device_owner=original_device_owner) - - @rbac_rule_validation.action(service="neutron", - rules=["get_port", "update_port", - "update_port:mac_address"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('507140c8-7b14-4d63-b627-2103691d887e') - def test_update_port_mac_address(self): - original_mac_address = self.port['mac_address'] - - with self.override_role(): - self.ports_client.update_port( - self.port['id'], mac_address=data_utils.rand_mac_address()) - self.addCleanup(self.ports_client.update_port, self.port['id'], - mac_address=original_mac_address) - - @testtools.skipUnless( - CONF.policy_feature_enabled.update_port_fixed_ips_ip_address_policy, - '"update_port:fixed_ips:ip_address" must be available in the cloud.') - @rbac_rule_validation.action(service="neutron", - rules=["get_port", "update_port", - "update_port:fixed_ips:ip_address"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('c091c825-532b-4c6f-a14f-affd3259c1c3') - def test_update_port_fixed_ips_ip_address(self): - - # Pick an ip address within the allocation_pools range. - post_body = {'network': self.network} - port = self.create_port(**post_body) - - ip_list = self._get_unused_ip_address() - fixed_ips = [{'ip_address': ip_list[0]}] - - with self.override_role(): - self.ports_client.update_port(port['id'], fixed_ips=fixed_ips) - - @rbac_rule_validation.action(service="neutron", - rules=["get_port", "update_port", - "update_port:port_security_enabled"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('795541af-6652-4e35-9581-fd58224f7545') - def test_update_port_security_enabled(self): - with self.override_role(): - self.ports_client.update_port(self.port['id'], - port_security_enabled=True) - - @utils.requires_ext(extension='binding', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_port", "update_port", - "update_port:binding:host_id"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('24206a72-0d90-4712-918c-5c9a1ebef64d') - def test_update_port_binding_host_id(self): - - post_body = {'network': self.network, - 'binding:host_id': 'rbac_test_host'} - port = self.create_port(**post_body) - - updated_body = {'port_id': port['id'], - 'binding:host_id': 'rbac_test_host_updated'} - - with self.override_role(): - self.ports_client.update_port(**updated_body) - - @utils.requires_ext(extension='binding', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_port", "update_port", - "update_port:binding:profile"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('990ea8d1-9257-4f71-a3bf-d6d0914625c5') - def test_update_port_binding_profile(self): - - binding_profile = {"foo": "1"} - post_body = {'network': self.network, - 'binding:profile': binding_profile} - - port = self.create_port(**post_body) - - new_binding_profile = {"foo": "2"} - updated_body = {'port_id': port['id'], - 'binding:profile': new_binding_profile} - - with self.override_role(): - self.ports_client.update_port(**updated_body) - - @rbac_rule_validation.action(service="neutron", - rules=["get_port", "update_port", - "update_port:allowed_address_pairs"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('729c2151-bb49-4f4f-9d58-3ed8819b7582') - def test_update_port_allowed_address_pairs(self): - - ip_list = self._get_unused_ip_address() - # Update allowed address pair attribute of port - address_pairs = [{'ip_address': ip_list[0], - 'mac_address': data_utils.rand_mac_address()}] - post_body = {'network': self.network} - port = self.create_port(**post_body) - - with self.override_role(): - self.ports_client.update_port(port['id'], - allowed_address_pairs=address_pairs) - - @rbac_rule_validation.action(service="neutron", - rules=["get_port", "delete_port"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('1cf8e582-bc09-46cb-b32a-82bf991ad56f') - def test_delete_port(self): - - port = self.create_port(self.network) - with self.override_role(): - self.ports_client.delete_port(port['id']) - - @rbac_rule_validation.action(service="neutron", rules=["get_port"]) - @decorators.idempotent_id('877ea70d-b000-4af4-9322-0a76b47b7890') - def test_list_ports(self): - """List Ports - - RBAC test for the neutron ``list_ports`` function and - the ``get_port`` policy - """ - admin_resource_id = self.port['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.ports_client.list_ports( - id=admin_resource_id)["ports"] diff --git a/patrole_tempest_plugin/tests/api/network/test_qos_rbac.py b/patrole_tempest_plugin/tests/api/network/test_qos_rbac.py deleted file mode 100644 index 2951e53f..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_qos_rbac.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2018 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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class QosExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(QosExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('qos', 'network'): - msg = "qos extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(QosExtRbacTest, cls).resource_setup() - cls.network = cls.create_network() - - def create_policy(self, name=None): - name = name or data_utils.rand_name(self.__class__.__name__) - policy = self.ntp_client.create_qos_policy(name)['policy'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_qos_policy, policy['id']) - return policy - - @rbac_rule_validation.action(service="neutron", - rules=["create_policy"], - expected_error_codes=[403]) - @decorators.idempotent_id('2ade2e48-7f82-4650-a69c-933d8d594636') - def test_create_policy(self): - - """Create Policy Test - - RBAC test for the neutron create_policy policy - """ - with self.override_role(): - self.create_policy() - - @rbac_rule_validation.action(service="neutron", - rules=["get_policy"], - expected_error_codes=[404]) - @decorators.idempotent_id('d004a8de-b226-4eb4-9fdc-8202a7f64c56') - def test_get_policy(self): - - """Show Policy Test - - RBAC test for the neutron get_policy policy - """ - policy = self.create_policy() - with self.override_role(): - self.ntp_client.show_qos_policy(policy['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_policy", "update_policy"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('fb74d56f-1dfc-490b-a9e1-454af583eefb') - def test_update_policy(self): - - """Update Policy Test - - RBAC test for the neutron update_policy policy - """ - policy = self.create_policy() - with self.override_role(): - self.ntp_client.update_qos_policy(policy['id'], - description='updated') - - @rbac_rule_validation.action(service="neutron", - rules=["get_policy", "delete_policy"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('ef4c23a6-4095-47a6-958e-1df585f7d8db') - def test_delete_policy(self): - - """Delete Policy Test - - RBAC test for the neutron delete_policy policy - """ - policy = self.create_policy() - with self.override_role(): - self.ntp_client.delete_qos_policy(policy['id']) - - @rbac_rule_validation.action(service="neutron", rules=["get_policy"]) - @decorators.idempotent_id('e84cec88-8478-4787-b603-5fcdd8ed7bd5') - def test_list_policies(self): - """List Policies Test - - RBAC test for the neutron ``list_qos_policies`` function and - the ``get_policy`` - """ - admin_resource_id = self.create_policy()['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.ntp_client.list_qos_policies( - id=admin_resource_id)["policies"] diff --git a/patrole_tempest_plugin/tests/api/network/test_rbac_policies_rbac.py b/patrole_tempest_plugin/tests/api/network/test_rbac_policies_rbac.py deleted file mode 100644 index c2bc9700..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_rbac_policies_rbac.py +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright 2018 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.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class RbacPoliciesExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def resource_setup(cls): - super(RbacPoliciesExtRbacTest, cls).resource_setup() - cls.tenant_id = cls.os_primary.credentials.tenant_id - cls.network_id = cls.create_network()['id'] - - def create_rbac_policy(self, tenant_id, network_id): - policy = self.ntp_client.create_rbac_policy( - target_tenant=tenant_id, - object_type="network", - object_id=network_id, - action="access_as_shared" - ) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_rbac_policy, policy["rbac_policy"]["id"]) - - return policy["rbac_policy"]["id"] - - @decorators.idempotent_id('effd9545-99ad-4c3c-92dd-ea422602c868') - @rbac_rule_validation.action(service="neutron", - rules=["create_rbac_policy", - "create_rbac_policy:target_tenant"]) - def test_create_rbac_policy(self): - """Create RBAC policy. - - RBAC test for the neutron "create_rbac_policy" policy - - We can't validate "create_rbac_policy:target_tenant" for all cases - since if "restrict_wildcard" rule is modified then Patrole won't be - able to determine the correct result since that requires relying on - Neutron's custom FieldCheck oslo.policy rule. - """ - - with self.override_role(): - self.create_rbac_policy(self.tenant_id, self.network_id) - - @decorators.idempotent_id('f5d836d8-3b64-412d-a283-ee29761017f3') - @rbac_rule_validation.action(service="neutron", - rules=["get_rbac_policy", - "update_rbac_policy", - "update_rbac_policy:target_tenant"], - expected_error_codes=[404, 403, 403]) - def test_update_rbac_policy(self): - """Update RBAC policy. - - RBAC test for the neutron "update_rbac_policy" policy - - We can't validate "create_rbac_policy:target_tenant" for all cases - since if "restrict_wildcard" rule is modified then Patrole won't be - able to determine the correct result since that requires relying on - Neutron's custom FieldCheck oslo.policy rule. - """ - policy_id = self.create_rbac_policy(self.tenant_id, self.network_id) - - with self.override_role(): - self.ntp_client.update_rbac_policy( - policy_id, target_tenant=self.tenant_id) - - @decorators.idempotent_id('9308ab18-426c-41b7-bce5-11081f7dd259') - @rbac_rule_validation.action(service="neutron", - rules=["get_rbac_policy"], - expected_error_codes=[404]) - def test_show_rbac_policy(self): - """Show RBAC policy. - - RBAC test for the neutron "get_rbac_policy" policy - """ - policy_id = self.create_rbac_policy(self.tenant_id, self.network_id) - - with self.override_role(): - self.ntp_client.show_rbac_policy(policy_id) - - @decorators.idempotent_id('54aa9bce-efea-47fb-b0e4-12012f82f285') - @rbac_rule_validation.action(service="neutron", - rules=["get_rbac_policy", - "delete_rbac_policy"], - expected_error_codes=[404, 403]) - def test_delete_rbac_policy(self): - """Delete RBAC policy. - - RBAC test for the neutron "delete_rbac_policy" policy - """ - policy_id = self.create_rbac_policy(self.tenant_id, self.network_id) - - with self.override_role(): - self.ntp_client.delete_rbac_policy(policy_id) - - @decorators.idempotent_id('5337d95a-2e75-47bb-a0ea-0a082be930bf') - @rbac_rule_validation.action(service="neutron", rules=["get_rbac_policy"]) - def test_list_rbac_policies(self): - """List RBAC policies. - - RBAC test for the neutron ``list_rbac_policies`` function and - the ``get_rbac_policy`` policy - """ - admin_resource_id = self.create_rbac_policy(self.tenant_id, - self.network_id) - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.ntp_client.list_rbac_policies( - id=admin_resource_id)["rbac_policies"] diff --git a/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py b/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py deleted file mode 100644 index 42318e9e..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py +++ /dev/null @@ -1,418 +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. - -import netaddr - -from tempest.common import utils -from tempest.common.utils import net_utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class RouterRbacTest(base.BaseNetworkRbacTest): - @classmethod - def skip_checks(cls): - super(RouterRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('router', 'network'): - msg = "router extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(RouterRbacTest, cls).resource_setup() - # Create a network with external gateway so that - # ``external_gateway_info`` policies can be validated. - post_body = {'router:external': True} - cls.network = cls.create_network(**post_body) - cls.subnet = cls.create_subnet(cls.network) - cls.ip_range = netaddr.IPRange( - cls.subnet['allocation_pools'][0]['start'], - cls.subnet['allocation_pools'][0]['end']) - cls.router = cls.create_router() - - def _get_unused_ip_address(self): - unused_ip = net_utils.get_unused_ip_addresses(self.ports_client, - self.subnets_client, - self.network['id'], - self.subnet['id'], - 1) - return unused_ip[0] - - @rbac_rule_validation.action(service="neutron", - rules=["create_router"]) - @decorators.idempotent_id('acc5005c-bdb6-4192-bc9f-ece9035bb488') - def test_create_router(self): - """Create Router - - RBAC test for the neutron create_router policy - """ - with self.override_role(): - router = self.routers_client.create_router() - self.addCleanup(self.routers_client.delete_router, - router['router']['id']) - - @decorators.idempotent_id('6139eb97-95c0-40d8-a109-99de11ab2e5e') - @utils.requires_ext(extension='l3-ha', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["create_router", - "create_router:ha"]) - def test_create_high_availability_router(self): - """Create high-availability router - - RBAC test for the neutron create_router:ha policy - """ - with self.override_role(): - router = self.routers_client.create_router(ha=True) - self.addCleanup(self.routers_client.delete_router, - router['router']['id']) - - @decorators.idempotent_id('c6254ca6-2728-412d-803d-d4aa3935e56d') - @utils.requires_ext(extension='dvr', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["create_router", - "create_router:distributed"]) - def test_create_distributed_router(self): - """Create distributed router - - RBAC test for the neutron create_router:distributed policy - """ - with self.override_role(): - router = self.routers_client.create_router(distributed=True) - self.addCleanup(self.routers_client.delete_router, - router['router']['id']) - - @utils.requires_ext(extension='ext-gw-mode', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["create_router", - "create_router:external_gateway_info:enable_snat"]) - @decorators.idempotent_id('3c5acd49-0ec7-4109-ab51-640557b48ebc') - def test_create_router_enable_snat(self): - """Create Router Snat - - RBAC test for the neutron - create_router:external_gateway_info:enable_snat policy - """ - name = data_utils.rand_name(self.__class__.__name__ + '-snat-router') - external_gateway_info = {'network_id': self.network['id'], - 'enable_snat': True} - - with self.override_role(): - router = self.routers_client.create_router( - name=name, external_gateway_info=external_gateway_info) - self.addCleanup(self.routers_client.delete_router, - router['router']['id']) - - @rbac_rule_validation.action( - service="neutron", - rules=["create_router", - "create_router:external_gateway_info:external_fixed_ips"]) - @decorators.idempotent_id('d0354369-a040-4349-b869-645c8aed13cd') - def test_create_router_external_fixed_ips(self): - """Create Router Fixed IPs - - RBAC test for the neutron - create_router:external_gateway_info:external_fixed_ips policy - """ - name = data_utils.rand_name(self.__class__.__name__ + '-snat-router') - - unused_ip = self._get_unused_ip_address() - external_fixed_ips = {'subnet_id': self.subnet['id'], - 'ip_address': unused_ip} - external_gateway_info = {'network_id': self.network['id'], - 'enable_snat': False, # Default is True. - 'external_fixed_ips': [external_fixed_ips]} - - with self.override_role(): - router = self.routers_client.create_router( - name=name, external_gateway_info=external_gateway_info) - self.addCleanup(self.routers_client.delete_router, - router['router']['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_router"], - expected_error_codes=[404]) - @decorators.idempotent_id('bfbdbcff-f115-4d3e-8cd5-6ada33fd0e21') - def test_show_router(self): - """Get Router - - RBAC test for the neutron get_router policy - """ - # Prevent other policies from being enforced by using barebones fields. - with self.override_role(): - self.routers_client.show_router(self.router['id'], fields=['id']) - - @decorators.idempotent_id('3ed26ea2-b419-410c-b4b5-576c1edafa06') - @utils.requires_ext(extension='dvr', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_router", - "get_router:distributed"], - expected_error_codes=[404, 403]) - def test_show_distributed_router(self): - """Get distributed router - - RBAC test for the neutron get_router:distributed policy - """ - router = self.routers_client.create_router(distributed=True)['router'] - self.addCleanup(self.routers_client.delete_router, router['id']) - - with self.override_role(): - retrieved_fields = self.routers_client.show_router( - router['id'], fields=['distributed'])['router'] - - # Rather than throwing a 403, the field is not present, so raise exc. - if 'distributed' not in retrieved_fields: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='distributed') - - @decorators.idempotent_id('defc502c-4159-4824-b4d9-3cdcc39015b2') - @utils.requires_ext(extension='l3-ha', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_router", "get_router:ha"], - expected_error_codes=[404, 403]) - def test_show_high_availability_router(self): - """GET high-availability router - - RBAC test for the neutron get_router:ha policy - """ - router = self.routers_client.create_router(ha=True)['router'] - self.addCleanup(self.routers_client.delete_router, router['id']) - - with self.override_role(): - retrieved_fields = self.routers_client.show_router( - router['id'], fields=['ha'])['router'] - - # Rather than throwing a 403, the field is not present, so raise exc. - if 'ha' not in retrieved_fields: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='ha') - - @rbac_rule_validation.action(service="neutron", - rules=["get_router", "update_router"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('3d182f4e-0023-4218-9aa0-ea2b0ae0bd7a') - def test_update_router(self): - """Update Router - - RBAC test for the neutron update_router policy - """ - new_name = data_utils.rand_name( - self.__class__.__name__ + '-new-router-name') - with self.override_role(): - self.routers_client.update_router(self.router['id'], name=new_name) - - @rbac_rule_validation.action(service="neutron", - rules=["get_router", "update_router", - "update_router:external_gateway_info"], - expected_error_codes=[404, 403, 403]) - @decorators.idempotent_id('5a6ae104-a9c3-4b56-8622-e1a0a0194474') - def test_update_router_external_gateway_info(self): - """Update Router External Gateway Info - - RBAC test for the neutron - update_router:external_gateway_info policy - """ - with self.override_role(): - self.routers_client.update_router(self.router['id'], - external_gateway_info={}) - - @rbac_rule_validation.action( - service="neutron", - rules=["get_router", "update_router", - "update_router:external_gateway_info", - "update_router:external_gateway_info:network_id"], - expected_error_codes=[404, 403, 403, 403]) - @decorators.idempotent_id('f1fc5a23-e3d8-44f0-b7bc-47006ad9d3d4') - def test_update_router_external_gateway_info_network_id(self): - """Update Router External Gateway Info Network Id - - RBAC test for the neutron - update_router:external_gateway_info:network_id policy - """ - with self.override_role(): - self.routers_client.update_router( - self.router['id'], - external_gateway_info={'network_id': self.network['id']}) - self.addCleanup( - self.routers_client.update_router, - self.router['id'], - external_gateway_info=None) - - @utils.requires_ext(extension='ext-gw-mode', service='network') - @rbac_rule_validation.action( - service="neutron", - rules=["get_router", "update_router", - "update_router:external_gateway_info", - "update_router:external_gateway_info:enable_snat"], - expected_error_codes=[404, 403, 403, 403]) - @decorators.idempotent_id('515a2954-3d79-4695-aeb9-d1c222765840') - def test_update_router_enable_snat(self): - """Update Router External Gateway Info Enable Snat - - RBAC test for the neutron - update_router:external_gateway_info:enable_snat policy - """ - with self.override_role(): - self.routers_client.update_router( - self.router['id'], - external_gateway_info={'network_id': self.network['id'], - 'enable_snat': True}) - self.addCleanup( - self.routers_client.update_router, - self.router['id'], - external_gateway_info=None) - - @rbac_rule_validation.action( - service="neutron", - rules=["get_router", "update_router", - "update_router:external_gateway_info", - "update_router:external_gateway_info:external_fixed_ips"], - expected_error_codes=[404, 403, 403, 403]) - @decorators.idempotent_id('f429e5ee-8f0a-4667-963e-72dd95d5adee') - def test_update_router_external_fixed_ips(self): - """Update Router External Gateway Info External Fixed Ips - - RBAC test for the neutron - update_router:external_gateway_info:external_fixed_ips policy - """ - unused_ip = self._get_unused_ip_address() - external_fixed_ips = {'subnet_id': self.subnet['id'], - 'ip_address': unused_ip} - external_gateway_info = {'network_id': self.network['id'], - 'external_fixed_ips': [external_fixed_ips]} - - with self.override_role(): - self.routers_client.update_router( - self.router['id'], - external_gateway_info=external_gateway_info) - self.addCleanup( - self.routers_client.update_router, - self.router['id'], - external_gateway_info=None) - - @decorators.idempotent_id('ddc20731-dea1-4321-9abf-8772bf0b5977') - @utils.requires_ext(extension='l3-ha', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_router", "update_router", - "update_router:ha"], - expected_error_codes=[404, 403, 403]) - def test_update_high_availability_router(self): - """Update high-availability router - - RBAC test for the neutron update_router:ha policy - """ - with self.override_role(): - self.routers_client.update_router(self.router['id'], ha=True) - self.addCleanup(self.routers_client.update_router, self.router['id'], - ha=False) - - @decorators.idempotent_id('e1932c19-8f73-41cd-b5d2-84c7ae5d530c') - @utils.requires_ext(extension='dvr', service='network') - @rbac_rule_validation.action(service="neutron", - rules=["get_router", "update_router", - "update_router:distributed"], - expected_error_codes=[404, 403, 403]) - def test_update_distributed_router(self): - """Update distributed router - - RBAC test for the neutron update_router:distributed policy - """ - with self.override_role(): - self.routers_client.update_router(self.router['id'], - distributed=True) - self.addCleanup(self.routers_client.update_router, self.router['id'], - distributed=False) - - @rbac_rule_validation.action(service="neutron", - rules=["get_router", "delete_router"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('c0634dd5-0467-48f7-a4ae-1014d8edb2a7') - def test_delete_router(self): - """Delete Router - - RBAC test for the neutron delete_router policy - """ - router = self.create_router() - with self.override_role(): - self.routers_client.delete_router(router['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_router", "add_router_interface"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('a0627778-d68d-4913-881b-e345360cca19') - def test_add_router_interface(self): - """Add Router Interface - - RBAC test for the neutron add_router_interface policy - """ - network = self.create_network() - subnet = self.create_subnet(network) - router = self.create_router() - - with self.override_role(): - self.routers_client.add_router_interface( - router['id'], subnet_id=subnet['id']) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.routers_client.remove_router_interface, - router['id'], - subnet_id=subnet['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_router", - "remove_router_interface"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('ff2593a4-2bff-4c27-97d3-dd3702b27dfb') - def test_remove_router_interface(self): - """Remove Router Interface - - RBAC test for the neutron remove_router_interface policy - """ - network = self.create_network() - subnet = self.create_subnet(network) - router = self.create_router() - - self.routers_client.add_router_interface( - router['id'], subnet_id=subnet['id']) - - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.routers_client.remove_router_interface, - router['id'], - subnet_id=subnet['id']) - - with self.override_role(): - self.routers_client.remove_router_interface( - router['id'], - subnet_id=subnet['id']) - - @rbac_rule_validation.action(service="neutron", rules=["get_router"]) - @decorators.idempotent_id('86816700-12d1-4173-a50f-34bd137f47e6') - def test_list_routers(self): - """List Routers - - RBAC test for the neutron ``get_router policy`` and - the ``get_router`` policy - """ - - admin_resource_id = self.router['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.routers_client.list_routers( - id=admin_resource_id)["routers"] diff --git a/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py b/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py deleted file mode 100644 index 3460880b..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py +++ /dev/null @@ -1,175 +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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class SecGroupRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def skip_checks(cls): - super(SecGroupRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('security-group', 'network'): - msg = "security-group extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(SecGroupRbacTest, cls).resource_setup() - secgroup_name = data_utils.rand_name(cls.__name__ + '-secgroup') - cls.secgroup = cls.security_groups_client.create_security_group( - name=secgroup_name)['security_group'] - cls.addClassResourceCleanup( - cls.security_groups_client.delete_security_group, - cls.secgroup['id']) - - def _create_security_group(self): - # Create a security group - name = data_utils.rand_name(self.__class__.__name__ + '-secgroup') - security_group =\ - self.security_groups_client.create_security_group( - name=name)['security_group'] - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.security_groups_client.delete_security_group, - security_group['id']) - return security_group - - def _create_security_group_rule(self): - # Create a security group rule - sec_group_rule = \ - self.security_group_rules_client.create_security_group_rule( - security_group_id=self.secgroup['id'], - direction='ingress', - protocol='tcp', - port_range_min=99, - port_range_max=99)['security_group_rule'] - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.security_group_rules_client.delete_security_group_rule, - sec_group_rule['id']) - return sec_group_rule - - @rbac_rule_validation.action(service="neutron", - rules=["create_security_group"]) - @decorators.idempotent_id('db7003ce-5717-4e5b-afc7-befa35e8c67f') - def test_create_security_group(self): - - with self.override_role(): - self._create_security_group() - - @rbac_rule_validation.action(service="neutron", - rules=["get_security_group"], - expected_error_codes=[404]) - @decorators.idempotent_id('56335e77-aef2-4b54-86c7-7f772034b585') - def test_show_security_group(self): - - with self.override_role(): - self.security_groups_client.show_security_group( - self.secgroup['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_security_group", - "delete_security_group"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('0b1330fd-dd28-40f3-ad73-966052e4b3de') - def test_delete_security_group(self): - - # Create a security group - secgroup_id = self._create_security_group()['id'] - - with self.override_role(): - self.security_groups_client.delete_security_group(secgroup_id) - - @rbac_rule_validation.action(service="neutron", - rules=["get_security_group", - "update_security_group"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('56c5e4dc-f8aa-11e6-bc64-92361f002671') - def test_update_security_group(self): - - # Create a security group - secgroup_id = self._create_security_group()['id'] - - with self.override_role(): - self.security_groups_client.update_security_group( - secgroup_id, - description="test description") - - @rbac_rule_validation.action(service="neutron", - rules=["get_security_group"]) - @decorators.idempotent_id('fbaf8d96-ed3e-49af-b24c-5fb44f05bbb7') - def test_list_security_groups(self): - """List Security Groups - - RBAC test for the neutron ``list_security_groups`` function and - the ``get_security_group`` policy - """ - admin_resource_id = self.secgroup['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.security_groups_client.list_security_groups( - id=admin_resource_id)["security_groups"] - - @rbac_rule_validation.action(service="neutron", - rules=["create_security_group_rule"]) - @decorators.idempotent_id('953d78df-00cd-416f-9cbd-b7cb4ea65772') - def test_create_security_group_rule(self): - - with self.override_role(): - self._create_security_group_rule() - - @rbac_rule_validation.action(service="neutron", - rules=["get_security_group_rule", - "delete_security_group_rule"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('2262539e-b7d9-438c-acf9-a5ce0613be28') - def test_delete_security_group_rule(self): - - sec_group_rule = self._create_security_group_rule() - with self.override_role(): - self.security_group_rules_client.delete_security_group_rule( - sec_group_rule['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_security_group_rule"], - expected_error_codes=[404]) - @decorators.idempotent_id('84b4038c-261e-4a94-90d5-c885739ab0d5') - def test_show_security_group_rule(self): - - sec_group_rule = self._create_security_group_rule() - with self.override_role(): - self.security_group_rules_client.show_security_group_rule( - sec_group_rule['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_security_group_rule"]) - @decorators.idempotent_id('05739ab6-fa35-11e6-bc64-92361f002671') - def test_list_security_group_rules(self): - - with self.override_role(): - security_rules = self.security_group_rules_client.\ - list_security_group_rules() - - # Neutron may return an empty list if access is denied. - if not security_rules['security_group_rules']: - raise rbac_exceptions.RbacEmptyResponseBody() diff --git a/patrole_tempest_plugin/tests/api/network/test_segments_rbac.py b/patrole_tempest_plugin/tests/api/network/test_segments_rbac.py deleted file mode 100644 index 1e6d7f11..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_segments_rbac.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright 2018 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 random - -from tempest.common import utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class SegmentsExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(SegmentsExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('segment', 'network'): - msg = "segment extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(SegmentsExtRbacTest, cls).resource_setup() - cls.network = cls.create_network() - - @classmethod - def get_free_segmentation_id(cls): - # Select unused segmentation_id to prevent usage conflict - segments = cls.ntp_client.list_segments()["segments"] - segmentation_ids = [s["segmentation_id"] for s in segments] - - # With 2+ concurrency, tests that ran in the same moment may fail due - # to usage conflict. To prevent it we select segmentation to start - # randomly. - segmentation_id = random.randint(1000, 5000) # nosec - while segmentation_id in segmentation_ids: - segmentation_id += 1 - - return segmentation_id - - @classmethod - def create_segment(cls, network): - segmentation_id = cls.get_free_segmentation_id() - - seg = cls.ntp_client.create_segment( - network_id=network['id'], network_type="gre", - segmentation_id=segmentation_id) - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.ntp_client.delete_segment, seg['segment']['id']) - - return seg - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08126') - @rbac_rule_validation.action(service="neutron", - rules=["create_segment"]) - def test_create_segment(self): - """Create segment. - - RBAC test for the neutron "create_segment" policy - """ - with self.override_role(): - self.create_segment(self.network) - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08127') - @rbac_rule_validation.action(service="neutron", - rules=["get_segment"], - expected_error_codes=[404]) - def test_show_segment(self): - """Show segment. - - RBAC test for the neutron "get_segment" policy - """ - segment = self.create_segment(self.network) - - with self.override_role(): - self.ntp_client.show_segment(segment['segment']['id']) - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08128') - @rbac_rule_validation.action(service="neutron", - rules=["get_segment", - "update_segment"], - expected_error_codes=[404, 403]) - def test_update_segment(self): - """Update segment. - - RBAC test for the neutron "update_segment" policy - """ - segment = self.create_segment(self.network) - - with self.override_role(): - self.ntp_client.update_segment(segment['segment']['id'], - name="NewName") - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08129') - @rbac_rule_validation.action(service="neutron", - rules=["get_segment", - "delete_segment"], - expected_error_codes=[404, 403]) - def test_delete_segment(self): - """Delete segment. - - RBAC test for the neutron "delete_segment" policy - """ - segment = self.create_segment(self.network) - - with self.override_role(): - self.ntp_client.delete_segment(segment['segment']['id']) - - @decorators.idempotent_id('d68a0578-36ae-435e-8aaa-508ee96bdfae') - @rbac_rule_validation.action(service="neutron", rules=["get_segment"]) - def test_list_segments(self): - """List segments. - - RBAC test for the neutron ``list_segments`` function and - the``get_segment`` policy - """ - admin_resource_id = self.create_segment(self.network)['segment']['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.ntp_client.list_segments( - id=admin_resource_id)["segments"] diff --git a/patrole_tempest_plugin/tests/api/network/test_service_profile_rbac.py b/patrole_tempest_plugin/tests/api/network/test_service_profile_rbac.py deleted file mode 100644 index fbb42304..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_service_profile_rbac.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2018 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 patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class ServiceProfileExtRbacTest(base.BaseNetworkExtRbacTest): - @decorators.idempotent_id('6ce76efa-7400-44c1-80ec-58f79b1d89ca') - @rbac_rule_validation.action(service="neutron", - rules=["create_service_profile"]) - def test_create_service_profile(self): - """Create service profile - - RBAC test for the neutron "create_service_profile" policy - """ - with self.override_role(): - self.create_service_profile() - - @decorators.idempotent_id('e4c473b7-3ae9-4a2e-8cac-848f7b01187d') - @rbac_rule_validation.action(service="neutron", - rules=["get_service_profile"], - expected_error_codes=[404]) - def test_show_service_profile(self): - """Show service profile - - RBAC test for the neutron "get_service_profile" policy - """ - profile_id = self.create_service_profile() - with self.override_role(): - self.ntp_client.show_service_profile(profile_id) - - @decorators.idempotent_id('a3dd719d-4cd3-40cc-b4f1-5642e2717adf') - @rbac_rule_validation.action(service="neutron", - rules=["get_service_profile", - "update_service_profile"], - expected_error_codes=[404, 403]) - def test_update_service_profile(self): - """Update service profile - - RBAC test for the neutron "update_service_profile" policy - """ - profile_id = self.create_service_profile() - with self.override_role(): - self.ntp_client.update_service_profile(profile_id, enabled=False) - - @decorators.idempotent_id('926b60c2-04fe-4339-aa44-bf27121392e8') - @rbac_rule_validation.action(service="neutron", - rules=["get_service_profile", - "delete_service_profile"], - expected_error_codes=[404, 403]) - def test_delete_service_profile(self): - """Delete service profile - - RBAC test for the neutron "delete_service_profile" policy - """ - profile_id = self.create_service_profile() - with self.override_role(): - self.ntp_client.delete_service_profile(profile_id) diff --git a/patrole_tempest_plugin/tests/api/network/test_service_providers_rbac.py b/patrole_tempest_plugin/tests/api/network/test_service_providers_rbac.py deleted file mode 100644 index 41725d57..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_service_providers_rbac.py +++ /dev/null @@ -1,29 +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 patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class ServiceProvidersRbacTest(base.BaseNetworkRbacTest): - - @rbac_rule_validation.action(service="neutron", - rules=["get_service_provider"]) - @decorators.idempotent_id('15f573b7-474a-4b37-8629-7fac86553ce5') - def test_list_service_providers(self): - with self.override_role(): - self.service_providers_client.list_service_providers() diff --git a/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py b/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py deleted file mode 100644 index af65f2fd..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py +++ /dev/null @@ -1,180 +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.common import utils -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - -CONF = config.CONF - - -class SubnetPoolsRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def skip_checks(cls): - super(SubnetPoolsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('subnet_allocation', 'network'): - msg = "subnet_allocation extension not enabled." - raise cls.skipException(msg) - - def _create_subnetpool(self, **kwargs): - post_body = {'name': data_utils.rand_name(self.__class__.__name__), - 'min_prefixlen': 24, - 'max_prefixlen': 32, - 'prefixes': [CONF.network.project_network_cidr]} - - if kwargs: - post_body.update(kwargs) - - body = self.subnetpools_client.create_subnetpool(**post_body) - subnetpool = body['subnetpool'] - - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.subnetpools_client.delete_subnetpool, - subnetpool['id']) - - return subnetpool - - @rbac_rule_validation.action(service="neutron", - rules=["create_subnetpool"]) - @decorators.idempotent_id('1b5509fd-2c32-44a8-a786-1b6ca162dbd1') - def test_create_subnetpool(self): - """Create subnetpool. - - RBAC test for the neutron create_subnetpool policy - """ - with self.override_role(): - self._create_subnetpool() - - @rbac_rule_validation.action(service="neutron", - rules=["create_subnetpool", - "create_subnetpool:is_default"], - expected_error_codes=[403, 403]) - @decorators.idempotent_id('1b5509fd-2c32-44a8-a786-1b6ca162dbd2') - def test_create_subnetpool_default(self): - """Create default subnetpool. - - RBAC test for the neutron create_subnetpool:is_default policy - """ - # Most likely we already have default subnetpools for ipv4 and ipv6, - # so we temporary mark them as is_default=False, to let this test pass. - def_pools = self.subnetpools_client.list_subnetpools(is_default=True) - for default_pool in def_pools["subnetpools"]: - self.subnetpools_client.update_subnetpool(default_pool["id"], - is_default=False) - - self.addCleanup(self.subnetpools_client.update_subnetpool, - default_pool["id"], is_default=True) - - with self.override_role(): - # It apparently only enforces the policy for is_default=True. - # It does nothing for is_default=False - self._create_subnetpool(is_default=True) - - @rbac_rule_validation.action(service="neutron", - rules=["create_subnetpool", - "create_subnetpool:shared"], - expected_error_codes=[403, 403]) - @decorators.idempotent_id('cf730989-0d47-40bc-b39a-99e7de484723') - def test_create_subnetpool_shared(self): - """Create subnetpool shared. - - RBAC test for the neutron create_subnetpool:shared policy - """ - with self.override_role(): - self._create_subnetpool(shared=True) - - @rbac_rule_validation.action(service="neutron", - rules=["get_subnetpool"], - expected_error_codes=[404]) - @decorators.idempotent_id('4f5aee26-0507-4b6d-b44c-3128a25094d2') - def test_show_subnetpool(self): - """Show subnetpool. - - RBAC test for the neutron get_subnetpool policy - """ - subnetpool = self._create_subnetpool() - with self.override_role(): - self.subnetpools_client.show_subnetpool(subnetpool['id']) - - @rbac_rule_validation.action(service="neutron", - rules=["get_subnetpool", - "update_subnetpool"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('1e79cead-5081-4be2-a4f7-484c0f443b9b') - def test_update_subnetpool(self): - """Update subnetpool. - - RBAC test for the neutron update_subnetpool policy - """ - subnetpool = self._create_subnetpool() - with self.override_role(): - self.subnetpools_client.update_subnetpool(subnetpool['id'], - min_prefixlen=24) - - @decorators.idempotent_id('a16f4e5c-0675-415f-b636-00af00638693') - @rbac_rule_validation.action(service="neutron", - rules=["update_subnetpool", - "update_subnetpool:is_default"]) - def test_update_subnetpool_is_default(self): - """Update default subnetpool. - - RBAC test for the neutron update_subnetpool:is_default policy - """ - subnetpools = self.subnetpools_client.list_subnetpools()['subnetpools'] - default_pool = list( - filter(lambda p: p['is_default'] is True, subnetpools)) - if default_pool: - default_pool = default_pool[0] - else: - default_pool = self._create_subnetpool(is_default=True) - original_desc = default_pool['description'] - - with self.override_role(): - self.subnetpools_client.update_subnetpool( - default_pool['id'], description=original_desc, is_default=True) - - @rbac_rule_validation.action(service="neutron", - rules=["get_subnetpool", - "delete_subnetpool"], - expected_error_codes=[404, 403]) - @decorators.idempotent_id('50f5944e-43e5-457b-ab50-fb48a73f0d3e') - def test_delete_subnetpool(self): - """Delete subnetpool. - - RBAC test for the neutron delete_subnetpool policy - """ - subnetpool = self._create_subnetpool() - with self.override_role(): - self.subnetpools_client.delete_subnetpool(subnetpool['id']) - - @rbac_rule_validation.action(service="neutron", rules=["get_subnetpool"]) - @decorators.idempotent_id('f1caf0f6-bde5-11e8-a355-529269fb1459') - def test_list_subnetpools(self): - """List subnetpools. - - RBAC test for the neutron ``list_subnetpools`` function and - the ``get_subnetpool`` policy - """ - admin_resource_id = self._create_subnetpool()['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.subnetpools_client.list_subnetpools( - id=admin_resource_id)["subnetpools"] diff --git a/patrole_tempest_plugin/tests/api/network/test_subnets_rbac.py b/patrole_tempest_plugin/tests/api/network/test_subnets_rbac.py deleted file mode 100644 index 2b03ece7..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_subnets_rbac.py +++ /dev/null @@ -1,103 +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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class SubnetsRbacTest(base.BaseNetworkRbacTest): - - @classmethod - def skip_checks(cls): - super(SubnetsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('subnet_allocation', 'network'): - msg = "subnet_allocation extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(SubnetsRbacTest, cls).resource_setup() - cls.network = cls.create_network() - cls.subnet = cls.create_subnet(cls.network) - - @decorators.idempotent_id('0481adeb-4301-44d5-851c-35910cc18a6b') - @rbac_rule_validation.action(service="neutron", - rules=["create_subnet"]) - def test_create_subnet(self): - """Create subnet. - - RBAC test for the neutron "create_subnet" policy - """ - with self.override_role(): - self.create_subnet(self.network) - - @decorators.idempotent_id('c02618e7-bb20-4abd-83c8-6eec2af08752') - @rbac_rule_validation.action(service="neutron", - rules=["get_subnet"], - expected_error_codes=[404]) - def test_show_subnet(self): - """Show subnet. - - RBAC test for the neutron "get_subnet" policy - """ - with self.override_role(): - self.subnets_client.show_subnet(self.subnet['id']) - - @decorators.idempotent_id('e2ddc415-5cab-43f4-9b61-166aed65d637') - @rbac_rule_validation.action(service="neutron", rules=["get_subnet"]) - def test_list_subnets(self): - """List subnets. - - RBAC test for the neutron ``list_subnets`` function and - the ``get_subnet`` policy - """ - admin_resource_id = self.subnet['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.subnets_client.list_subnets( - id=admin_resource_id)["subnets"] - - @decorators.idempotent_id('f36cd821-dd22-4bd0-b43d-110fc4b553eb') - @rbac_rule_validation.action(service="neutron", - rules=["get_subnet", "update_subnet"], - expected_error_codes=[404, 403]) - def test_update_subnet(self): - """Update subnet. - - RBAC test for the neutron "update_subnet" policy - """ - update_name = data_utils.rand_name(self.__class__.__name__ + '-Subnet') - - with self.override_role(): - self.subnets_client.update_subnet(self.subnet['id'], - name=update_name) - - @decorators.idempotent_id('bcfc7153-bbd1-43a4-a908-b3e1b0cde0dc') - @rbac_rule_validation.action(service="neutron", - rules=["get_subnet", "delete_subnet"], - expected_error_codes=[404, 403]) - def test_delete_subnet(self): - """Delete subnet. - - RBAC test for the neutron "delete_subnet" policy - """ - subnet = self.create_subnet(self.network) - - with self.override_role(): - self.subnets_client.delete_subnet(subnet['id']) diff --git a/patrole_tempest_plugin/tests/api/network/test_trunks_rbac.py b/patrole_tempest_plugin/tests/api/network/test_trunks_rbac.py deleted file mode 100644 index 0e8719ee..00000000 --- a/patrole_tempest_plugin/tests/api/network/test_trunks_rbac.py +++ /dev/null @@ -1,201 +0,0 @@ -# Copyright 2018 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.common import utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.network import rbac_base as base - - -class TrunksExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(TrunksExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('trunk', 'network'): - msg = "trunk extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(TrunksExtRbacTest, cls).resource_setup() - cls.network = cls.create_network() - cls.port_id = cls.create_port(cls.network)["id"] - - def create_trunk(self, port_id): - trunk = self.ntp_client.create_trunk(port_id, []) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.delete_trunk, trunk["trunk"]['id']) - - return trunk - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08130') - @rbac_rule_validation.action(service="neutron", - rules=["create_trunk"]) - def test_create_trunk(self): - """Create trunk. - - RBAC test for the neutron "create_trunk" policy - """ - with self.override_role(): - self.create_trunk(self.port_id) - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08131') - @rbac_rule_validation.action(service="neutron", - rules=["get_trunk"], - expected_error_codes=[404]) - def test_show_trunk(self): - """Show trunk. - - RBAC test for the neutron "get_trunk" policy - """ - trunk = self.create_trunk(self.port_id) - - with self.override_role(): - self.ntp_client.show_trunk(trunk['trunk']['id']) - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08132') - @rbac_rule_validation.action(service="neutron", - rules=["get_trunk", - "delete_trunk"], - expected_error_codes=[404, 403]) - def test_delete_trunk(self): - """Delete trunk. - - RBAC test for the neutron "delete_trunk" policy - """ - trunk = self.create_trunk(self.port_id) - - with self.override_role(): - self.ntp_client.delete_trunk(trunk['trunk']['id']) - - @decorators.idempotent_id('047badd1-e4ff-40c5-9929-99ffcb8750a7') - @rbac_rule_validation.action(service="neutron", rules=["get_trunk"]) - def test_list_trunks(self): - """Show trunk. - - RBAC test for the neutron ``list_trunks``` function and - the ``get_trunk`` policy - """ - admin_resource_id = self.create_trunk(self.port_id)["trunk"]['id'] - with (self.override_role_and_validate_list( - admin_resource_id=admin_resource_id)) as ctx: - ctx.resources = self.ntp_client.list_trunks( - id=admin_resource_id)["trunks"] - - -class TrunksSubportsExtRbacTest(base.BaseNetworkExtRbacTest): - - @classmethod - def skip_checks(cls): - super(TrunksSubportsExtRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('trunk', 'network'): - msg = "trunk extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(TrunksSubportsExtRbacTest, cls).resource_setup() - cls.network = cls.create_network() - cls.port_id = cls.create_port(cls.network)["id"] - cls.trunk_id = cls.ntp_client.create_trunk( - cls.port_id, [])['trunk']['id'] - - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.ntp_client.delete_trunk, cls.trunk_id) - - def create_subports(self, trunk_id, port_id): - subports = [{'port_id': port_id, - 'segmentation_type': 'vlan', - 'segmentation_id': 4000}] - sub = self.ntp_client.add_subports(trunk_id, subports) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.remove_subports, - trunk_id, subports) - return sub["sub_ports"] - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08133') - @rbac_rule_validation.action(service="neutron", - rules=["get_trunk", - "get_subports"], - expected_error_codes=[404, 403]) - def test_get_subports(self): - """Get subports. - - RBAC test for the neutron "get_subports" policy. - - Error 403 expected due to implementation of subports as a part of - trunk object. - """ - network = self.create_network() - port = self.create_port(network) - - self.create_subports(self.trunk_id, port["id"]) - - with self.override_role(): - self.ntp_client.get_subports(self.trunk_id) - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08134') - @rbac_rule_validation.action(service="neutron", - rules=["get_trunk", - "add_subports"], - expected_error_codes=[404, 403]) - def test_add_subports(self): - """Add subports. - - RBAC test for the neutron "add_subports" policy - - Error 403 expected due to implementation of subports as a part of - trunk object. - """ - network = self.create_network() - port = self.create_port(network) - - subports = [{'port_id': port["id"], - 'segmentation_type': 'vlan', - 'segmentation_id': 4000}] - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.ntp_client.remove_subports, - self.trunk_id, subports) - - with self.override_role(): - self.ntp_client.add_subports(self.trunk_id, subports) - - @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08135') - @rbac_rule_validation.action(service="neutron", - rules=["get_trunk", - "remove_subports"], - expected_error_codes=[404, 403]) - def test_remove_subports(self): - """Remove subports. - - RBAC test for the neutron "remove_subports" policy - - Error 403 expected due to implementation of subports as a part of - trunk object. - """ - network = self.create_network() - port = self.create_port(network) - - subports = self.create_subports(self.trunk_id, port["id"]) - - with self.override_role(): - self.ntp_client.remove_subports(self.trunk_id, subports) diff --git a/patrole_tempest_plugin/tests/api/volume/__init__.py b/patrole_tempest_plugin/tests/api/volume/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/api/volume/rbac_base.py b/patrole_tempest_plugin/tests/api/volume/rbac_base.py deleted file mode 100644 index e517b67c..00000000 --- a/patrole_tempest_plugin/tests/api/volume/rbac_base.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2017 AT&T Corporation. -# 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.volume import base as vol_base -from tempest.common import waiters -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils - -from patrole_tempest_plugin import rbac_utils - - -class BaseVolumeRbacTest(rbac_utils.RbacUtilsMixin, - vol_base.BaseVolumeTest): - # NOTE(felipemonteiro): Patrole currently only tests the v3 Cinder API - # because it is the current API and because policy enforcement does not - # change between API major versions. So, it is not necessary to specify - # the `_api_version` in any test class. However, specify microversions in - # subclasses if necessary. - _api_version = 3 - - @classmethod - def setup_clients(cls): - super(BaseVolumeRbacTest, cls).setup_clients() - cls.volume_hosts_client = cls.os_primary.volume_hosts_client_latest - cls.volume_types_client = cls.os_primary.volume_types_client_latest - cls.groups_client = cls.os_primary.groups_client_latest - cls.group_types_client = cls.os_primary.group_types_client_latest - - @classmethod - def create_volume_type(cls, name=None, **kwargs): - """Create a test volume-type""" - name = name or data_utils.rand_name(cls.__name__ + '-volume-type') - volume_type = cls.volume_types_client.create_volume_type( - name=name, **kwargs)['volume_type'] - cls.addClassResourceCleanup( - cls.volume_types_client.wait_for_resource_deletion, - volume_type['id']) - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - cls.volume_types_client.delete_volume_type, volume_type['id']) - return volume_type - - @classmethod - def _create_backup(cls, volume_id, backup_client=None, **kwargs): - """Wrapper utility that returns a test backup. - - Tempest has an instance-level version. This is a class-level version. - """ - if backup_client is None: - backup_client = cls.backups_client - if 'name' not in kwargs: - name = data_utils.rand_name(cls.__name__ + '-Backup') - kwargs['name'] = name - - backup = backup_client.create_backup( - volume_id=volume_id, **kwargs)['backup'] - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - backup_client.wait_for_resource_deletion, backup['id']) - cls.addClassResourceCleanup( - test_utils.call_and_ignore_notfound_exc, - backup_client.delete_backup, backup['id']) - waiters.wait_for_volume_resource_status(backup_client, backup['id'], - 'available') - waiters.wait_for_volume_resource_status(cls.volumes_client, volume_id, - 'available') - return backup - - def create_group_type(self, name=None, ignore_notfound=False, **kwargs): - """Create a test group-type""" - name = name or data_utils.rand_name( - self.__class__.__name__ + '-group-type') - group_type = self.group_types_client.create_group_type( - name=name, **kwargs)['group_type'] - - if ignore_notfound: - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.group_types_client.delete_group_type, - group_type['id']) - else: - self.addCleanup(self.group_types_client.delete_group_type, - group_type['id']) - - return group_type diff --git a/patrole_tempest_plugin/tests/api/volume/test_capabilities_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_capabilities_rbac.py deleted file mode 100644 index 2860c2f0..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_capabilities_rbac.py +++ /dev/null @@ -1,45 +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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - - -class CapabilitiesV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(CapabilitiesV3RbacTest, cls).skip_checks() - if not utils.is_extension_enabled('capabilities', 'volume'): - msg = "%s skipped as capabilities not enabled." % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(CapabilitiesV3RbacTest, cls).setup_clients() - cls.capabilities_client = \ - cls.os_primary.volume_capabilities_client_latest - cls.hosts_client = cls.os_primary.volume_hosts_client_latest - - @rbac_rule_validation.action(service="cinder", - rules=["volume_extension:capabilities"]) - @decorators.idempotent_id('40928b74-2141-11e7-93ae-92361f002671') - def test_show_back_end_capabilities(self): - host = self.hosts_client.list_hosts()['hosts'][0]['host_name'] - with self.override_role(): - self.capabilities_client.show_backend_capabilities(host) diff --git a/patrole_tempest_plugin/tests/api/volume/test_encryption_types_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_encryption_types_rbac.py deleted file mode 100644 index 07bbd6b4..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_encryption_types_rbac.py +++ /dev/null @@ -1,119 +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. - -import functools - -from tempest.common import utils -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -def _get_volume_type_encryption_policy(action): - feature_flag = CONF.policy_feature_enabled.added_cinder_policies_stein - - if feature_flag: - return "volume_extension:volume_type_encryption:%s" % action - - return "volume_extension:volume_type_encryption" - - -_CREATE_VOLUME_TYPE_ENCRYPTION = functools.partial( - _get_volume_type_encryption_policy, "create") -_SHOW_VOLUME_TYPE_ENCRYPTION = functools.partial( - _get_volume_type_encryption_policy, "get") -_UPDATE_VOLUME_TYPE_ENCRYPTION = functools.partial( - _get_volume_type_encryption_policy, "update") -_DELETE_VOLUME_TYPE_ENCRYPTION = functools.partial( - _get_volume_type_encryption_policy, "delete") - - -class EncryptionTypesV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(EncryptionTypesV3RbacTest, cls).skip_checks() - if not utils.is_extension_enabled('encryption', 'volume'): - msg = "%s skipped as encryption not enabled." % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(EncryptionTypesV3RbacTest, cls).setup_clients() - cls.encryption_types_client = \ - cls.os_primary.encryption_types_client_latest - - def _create_volume_type_encryption(self): - vol_type_id = self.create_volume_type()['id'] - self.encryption_types_client.create_encryption_type( - vol_type_id, - provider="nova.volume.encryptors.luks.LuksEncryptor", - control_location="front-end")['encryption'] - return vol_type_id - - @decorators.idempotent_id('ffd94ce5-c24b-4b6c-84c9-c5aad8c3010c') - @rbac_rule_validation.action( - service="cinder", - rules=[_CREATE_VOLUME_TYPE_ENCRYPTION]) - def test_create_volume_type_encryption(self): - vol_type_id = self.create_volume_type()['id'] - with self.override_role(): - self.encryption_types_client.create_encryption_type( - vol_type_id, - provider="nova.volume.encryptors.luks.LuksEncryptor", - control_location="front-end")['encryption'] - - @decorators.idempotent_id('6599e72e-acef-4c0d-a9b2-463fca30d1da') - @rbac_rule_validation.action( - service="cinder", - rules=[_DELETE_VOLUME_TYPE_ENCRYPTION]) - def test_delete_volume_type_encryption(self): - vol_type_id = self._create_volume_type_encryption() - with self.override_role(): - self.encryption_types_client.delete_encryption_type(vol_type_id) - - @decorators.idempotent_id('42da9fec-32fd-4dca-9242-8a53b2fed25a') - @rbac_rule_validation.action( - service="cinder", - rules=[_UPDATE_VOLUME_TYPE_ENCRYPTION]) - def test_update_volume_type_encryption(self): - vol_type_id = self._create_volume_type_encryption() - with self.override_role(): - self.encryption_types_client.update_encryption_type( - vol_type_id, - control_location="front-end") - - @decorators.idempotent_id('1381a3dc-248f-4282-b231-c9399018c804') - @rbac_rule_validation.action( - service="cinder", - rules=[_SHOW_VOLUME_TYPE_ENCRYPTION]) - def test_show_volume_type_encryption(self): - vol_type_id = self._create_volume_type_encryption() - with self.override_role(): - self.encryption_types_client.show_encryption_type(vol_type_id) - - @decorators.idempotent_id('d4ed3cf8-52b2-4fa2-910d-e405361f0881') - @rbac_rule_validation.action( - service="cinder", - rules=[_SHOW_VOLUME_TYPE_ENCRYPTION]) - def test_show_encryption_specs_item(self): - vol_type_id = self._create_volume_type_encryption() - with self.override_role(): - self.encryption_types_client.show_encryption_specs_item( - vol_type_id, 'provider') diff --git a/patrole_tempest_plugin/tests/api/volume/test_group_snapshots_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_group_snapshots_rbac.py deleted file mode 100644 index 0b265e8a..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_group_snapshots_rbac.py +++ /dev/null @@ -1,200 +0,0 @@ -# Copyright 2017 NEC 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.common import utils -from tempest.common import waiters -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - - -class BaseGroupSnapshotsRbacTest(rbac_base.BaseVolumeRbacTest): - - def _create_group_snapshot(self, **kwargs): - if 'name' not in kwargs: - kwargs['name'] = data_utils.rand_name( - self.__class__.__name__ + '-Group_Snapshot') - group_snapshot = self.group_snapshots_client.create_group_snapshot( - **kwargs)['group_snapshot'] - group_snapshot['group_id'] = kwargs['group_id'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self._delete_group_snapshot, group_snapshot) - waiters.wait_for_volume_resource_status( - self.group_snapshots_client, group_snapshot['id'], 'available') - snapshots = self.snapshots_client.list_snapshots( - detail=True)['snapshots'] - for snap in snapshots: - if self.vol['id'] == snap['volume_id']: - waiters.wait_for_volume_resource_status( - self.snapshots_client, snap['id'], 'available') - return group_snapshot - - def _delete_group_snapshot(self, group_snapshot): - self.group_snapshots_client.delete_group_snapshot(group_snapshot['id']) - vols = self.volumes_client.list_volumes(detail=True)['volumes'] - snapshots = self.snapshots_client.list_snapshots( - detail=True)['snapshots'] - for vol in vols: - for snap in snapshots: - if (vol['group_id'] == group_snapshot['group_id'] and - vol['id'] == snap['volume_id']): - self.snapshots_client.wait_for_resource_deletion( - snap['id']) - self.group_snapshots_client.wait_for_resource_deletion( - group_snapshot['id']) - - -class GroupSnaphotsV314RbacTest(BaseGroupSnapshotsRbacTest): - _api_version = 3 - volume_min_microversion = '3.14' - volume_max_microversion = 'latest' - - @classmethod - def skip_checks(cls): - super(GroupSnaphotsV314RbacTest, cls).skip_checks() - if not utils.is_extension_enabled('groupsnapshot', 'volume'): - msg = "%s skipped as group snapshots not enabled." % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(GroupSnaphotsV314RbacTest, cls).setup_clients() - cls.group_snapshot_client = \ - cls.os_primary.group_snapshots_client_latest - - def setUp(self): - super(GroupSnaphotsV314RbacTest, self).setUp() - self.volume_type = self.create_volume_type() - self.group_type = self.create_group_type() - self.grp = self.create_group(group_type=self.group_type['id'], - volume_types=[self.volume_type['id']]) - self.vol = self.create_volume(volume_type=self.volume_type['id'], - group_id=self.grp['id']) - - @decorators.idempotent_id('653df0e8-d90a-474a-a5ce-3c2339aff7ba') - @rbac_rule_validation.action( - service="cinder", - rules=["group:create_group_snapshot"] - ) - def test_create_group_snapshot(self): - with self.override_role(): - name = data_utils.rand_name( - self.__class__.__name__ + '-Group_Snapshot') - group_snapshot = self.group_snapshots_client.create_group_snapshot( - name=name, group_id=self.grp['id'])['group_snapshot'] - group_snapshot['group_id'] = self.grp['id'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self._delete_group_snapshot, group_snapshot) - waiters.wait_for_volume_resource_status( - self.group_snapshots_client, group_snapshot['id'], 'available') - snapshots = self.snapshots_client.list_snapshots( - detail=True)['snapshots'] - for snap in snapshots: - if self.vol['id'] == snap['volume_id']: - waiters.wait_for_volume_resource_status( - self.snapshots_client, snap['id'], 'available') - - @decorators.idempotent_id('8b966844-4421-4f73-940b-9157cb878331') - @rbac_rule_validation.action( - service="cinder", - rules=["group:get_group_snapshot"] - ) - def test_show_group_snapshot_rbac(self): - group_snapshot_name = data_utils.rand_name('group_snapshot') - group_snapshot = self._create_group_snapshot(group_id=self.grp['id'], - name=group_snapshot_name) - with self.override_role(): - self.group_snapshots_client.show_group_snapshot( - group_snapshot['id']) - - @decorators.idempotent_id('e9de6dae-1efb-47cd-a3a8-d1f4b8f9f3ff') - @rbac_rule_validation.action( - service="cinder", - rules=["group:get_all_group_snapshots"] - ) - def test_list_group_snapshot_rbac(self): - with self.override_role(): - self.group_snapshots_client.list_group_snapshots() - - @decorators.idempotent_id('cf2e25ee-ca58-4ad6-b98d-33235c77db7b') - @rbac_rule_validation.action( - service="cinder", - rules=["group:delete_group_snapshot"] - ) - def test_delete_group_snapshot_rbac(self): - group_snapshot_name = data_utils.rand_name('group_snapshot') - group_snapshot = self._create_group_snapshot(group_id=self.grp['id'], - name=group_snapshot_name) - with self.override_role(): - self.group_snapshots_client.delete_group_snapshot( - group_snapshot['id']) - vols = self.volumes_client.list_volumes(detail=True)['volumes'] - snapshots = self.snapshots_client.list_snapshots( - detail=True)['snapshots'] - for vol in vols: - for snap in snapshots: - if (vol['group_id'] == group_snapshot['group_id'] and - vol['id'] == snap['volume_id']): - self.snapshots_client.wait_for_resource_deletion( - snap['id']) - self.group_snapshots_client.wait_for_resource_deletion( - group_snapshot['id']) - - -class GroupSnaphotsV319RbacTest(BaseGroupSnapshotsRbacTest): - _api_version = 3 - volume_min_microversion = '3.19' - volume_max_microversion = 'latest' - - @classmethod - def skip_checks(cls): - super(GroupSnaphotsV319RbacTest, cls).skip_checks() - if not utils.is_extension_enabled('groupsnapshot', 'volume'): - msg = "%s skipped as group snapshots not enabled." % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(GroupSnaphotsV319RbacTest, cls).setup_clients() - cls.group_snapshot_client = \ - cls.os_primary.group_snapshots_client_latest - - def setUp(self): - super(GroupSnaphotsV319RbacTest, self).setUp() - self.volume_type = self.create_volume_type() - self.group_type = self.create_group_type() - self.grp = self.create_group(group_type=self.group_type['id'], - volume_types=[self.volume_type['id']]) - self.vol = self.create_volume(volume_type=self.volume_type['id'], - group_id=self.grp['id']) - - @decorators.idempotent_id('3f0c842e-0c72-4f5e-a9c2-281070be3e2c') - @rbac_rule_validation.action( - service="cinder", - rules=["group:reset_group_snapshot_status"] - ) - def test_reset_group_snapshot_rbac(self): - group_snapshot_name = data_utils.rand_name('group_snapshot') - group_snapshot = self._create_group_snapshot(group_id=self.grp['id'], - name=group_snapshot_name) - with self.override_role(): - self.group_snapshots_client.reset_group_snapshot_status( - group_snapshot['id'], 'error') - - waiters.wait_for_volume_resource_status( - self.group_snapshots_client, group_snapshot['id'], 'error') diff --git a/patrole_tempest_plugin/tests/api/volume/test_group_type_specs.py b/patrole_tempest_plugin/tests/api/volume/test_group_type_specs.py deleted file mode 100644 index 3b93d093..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_group_type_specs.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright 2018 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 import config -from tempest.lib import decorators - -from patrole_tempest_plugin.tests.api.volume import rbac_base - -from patrole_tempest_plugin import rbac_rule_validation - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_cinder_policies_xena: - _GROUP_SPEC_SHOW = "group:group_types_specs:get" - _GROUP_SPEC_LIST = "group:group_types_specs:get_all" - _GROUP_SPEC_CREATE = "group:group_types_specs:create" - _GROUP_SPEC_UPDATE = "group:group_types_specs:update" - _GROUP_SPEC_DELETE = "group:group_types_specs:delete" -else: - _GROUP_SPEC_SHOW = "group:group_types_specs" - _GROUP_SPEC_LIST = "group:group_types_specs" - _GROUP_SPEC_CREATE = "group:group_types_specs" - _GROUP_SPEC_UPDATE = "group:group_types_specs" - _GROUP_SPEC_DELETE = "group:group_types_specs" - - -class GroupTypeSpecsRbacTest(rbac_base.BaseVolumeRbacTest): - _api_version = 3 - volume_min_microversion = '3.11' - volume_max_microversion = 'latest' - - @decorators.idempotent_id('b2859734-00ad-4a22-88ee-541698e90d12') - @rbac_rule_validation.action( - service="cinder", - rules=[_GROUP_SPEC_CREATE] - ) - def test_group_type_specs_create(self): - # Create new group type - group_type = self.create_group_type() - - # Create new group type specs - create_specs = { - "key1": "value1", - "key2": "value2" - } - - with self.override_role(): - self.group_types_client. \ - create_or_update_group_type_specs( - group_type['id'], create_specs)['group_specs'] - - @decorators.idempotent_id('469d0253-aa13-423f-8264-231ac17effbf') - @rbac_rule_validation.action( - service="cinder", - rules=[_GROUP_SPEC_SHOW] - ) - def test_group_type_specs_show(self): - group_type = self.create_group_type() - specs = { - "key1": "value1", - "key2": "value2" - } - self.group_types_client.create_or_update_group_type_specs( - group_type['id'], specs)['group_specs'] - # Show specified item of group type specs - with self.override_role(): - self.group_types_client.show_group_type_specs_item( - group_type['id'], 'key2') - - @decorators.idempotent_id('2e706a4e-dec9-46bf-9426-1c5b6f3ce102') - @rbac_rule_validation.action( - service="cinder", - rules=[_GROUP_SPEC_UPDATE] - ) - def test_group_type_specs_update(self): - group_type = self.create_group_type() - # Update specified item of group type specs - update_key = 'key3' - update_spec = {update_key: "value3-updated"} - self.group_types_client.create_or_update_group_type_specs( - group_type['id'], update_spec)['group_specs'] - with self.override_role(): - self.group_types_client.update_group_type_specs_item( - group_type['id'], update_key, update_spec) - - @decorators.idempotent_id('fd5e332b-fb2c-4957-ace9-11d60ddd5472') - @rbac_rule_validation.action( - service="cinder", - rules=[_GROUP_SPEC_LIST] - ) - def test_group_type_specs_list(self): - group_type = self.create_group_type() - with self.override_role(): - self.group_types_client.list_group_type_specs( - group_type['id'])['group_specs'] - - @decorators.idempotent_id('d9639a07-e441-4576-baf6-7ec732b16572') - @rbac_rule_validation.action( - service="cinder", - rules=[_GROUP_SPEC_DELETE] - ) - def test_group_type_specs_delete(self): - group_type = self.create_group_type() - # Delete specified item of group type specs - delete_key = 'key1' - specs = {'key1': 'value1'} - self.group_types_client.create_or_update_group_type_specs( - group_type['id'], specs)['group_specs'] - with self.override_role(): - self.group_types_client.delete_group_type_specs_item( - group_type['id'], delete_key) diff --git a/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py deleted file mode 100644 index f0123844..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py +++ /dev/null @@ -1,237 +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.common import waiters -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_cinder_policies_xena: - _GROUP_CREATE = "group:group_types:create" - _GROUP_UPDATE = "group:group_types:update" - _GROUP_DELETE = "group:group_types:delete" -else: - _GROUP_CREATE = "group:group_types_manage" - _GROUP_UPDATE = "group:group_types_manage" - _GROUP_DELETE = "group:group_types_manage" - - -class BaseGroupRbacTest(rbac_base.BaseVolumeRbacTest): - - def setUp(self): - super(BaseGroupRbacTest, self).setUp() - self.volume_type_id = self.create_volume_type()['id'] - self.group_type_id = self.create_group_type()['id'] - - def _create_group(self, name=None, ignore_notfound=False, **kwargs): - group_name = name or data_utils.rand_name( - self.__class__.__name__ + '-Group') - group = self.groups_client.create_group(name=group_name, **kwargs)[ - 'group'] - if ignore_notfound: - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self._delete_group, group['id']) - else: - self.addCleanup(self._delete_group, group['id']) - waiters.wait_for_volume_resource_status( - self.groups_client, group['id'], 'available') - return group - - def _delete_group(self, group_id): - self.groups_client.delete_group(group_id, delete_volumes=True) - self.groups_client.wait_for_resource_deletion(group_id) - - vols = self.volumes_client.list_volumes( - detail=True, params={'all_tenants': True})['volumes'] - for vol in vols: - if vol['group_id'] == group_id: - self.volumes_client.wait_for_resource_deletion( - vol['id']) - - -class GroupsV3RbacTest(BaseGroupRbacTest): - volume_min_microversion = '3.13' - volume_max_microversion = 'latest' - - @decorators.idempotent_id('43235328-66ae-424f-bc7f-f709c0ca268c') - @rbac_rule_validation.action( - service="cinder", - rules=["group:create"]) - def test_create_group(self, name=None): - - group_name = name or data_utils.rand_name( - self.__class__.__name__ + '-Group') - with self.override_role(): - group = self.groups_client.create_group( - name=group_name, group_type=self.group_type_id, - volume_types=[self.volume_type_id])['group'] - self.addCleanup(self._delete_group, group['id']) - - waiters.wait_for_volume_resource_status( - self.groups_client, group['id'], 'available') - - @decorators.idempotent_id('9dc34a62-ae3e-439e-92b6-9389ea4c2863') - @rbac_rule_validation.action( - service="cinder", - rules=["group:get"]) - def test_show_group(self): - group = self._create_group(group_type=self.group_type_id, - volume_types=[self.volume_type_id]) - - with self.override_role(): - self.groups_client.show_group(group['id']) - - @decorators.idempotent_id('db43841b-a173-4317-acfc-f83e4e48e4ee') - @rbac_rule_validation.action( - service="cinder", - rules=["group:get_all"]) - def test_list_groups(self): - with self.override_role(): - self.groups_client.list_groups()['groups'] - - @decorators.idempotent_id('5378da93-9c26-4ad4-b039-0555e2b8f668') - @rbac_rule_validation.action( - service="cinder", - rules=["group:get_all"]) - def test_list_groups_with_details(self): - with self.override_role(): - self.groups_client.list_groups(detail=True)['groups'] - - @decorators.idempotent_id('f499fc48-df83-4917-bf8d-783ebf6f080b') - @rbac_rule_validation.action( - service="cinder", - rules=["group:update"]) - def test_update_group(self): - group = self._create_group(group_type=self.group_type_id, - volume_types=[self.volume_type_id]) - updated_name = data_utils.rand_name(self.__class__.__name__ + '-Group') - - with self.override_role(): - self.groups_client.update_group(group['id'], name=updated_name) - - @decorators.idempotent_id('66fda391-5774-42a9-a018-80b34e57ab76') - @rbac_rule_validation.action( - service="cinder", - rules=["group:delete"]) - def test_delete_group(self): - - group = self._create_group(ignore_notfound=True, - group_type=self.group_type_id, - volume_types=[self.volume_type_id]) - group_id = group['id'] - with self.override_role(): - self.groups_client.delete_group(group_id, delete_volumes=True) - - self.groups_client.wait_for_resource_deletion(group_id) - vols = self.volumes_client.list_volumes( - detail=True, params={'all_tenants': True})['volumes'] - for vol in vols: - if vol['group_id'] == group_id: - self.volumes_client.wait_for_resource_deletion( - vol['id']) - - -class GroupV320RbacTest(BaseGroupRbacTest): - _api_version = 3 - volume_min_microversion = '3.20' - volume_max_microversion = 'latest' - - @decorators.idempotent_id('b849c1d4-3215-4f9d-b1e6-0aeb4b2b65ac') - @rbac_rule_validation.action( - service="cinder", - rules=["group:reset_status"]) - def test_reset_group_status(self): - group = self._create_group(ignore_notfound=False, - group_type=self.group_type_id, - volume_types=[self.volume_type_id]) - status = 'available' - with self.override_role(): - self.groups_client.reset_group_status(group['id'], - status) - waiters.wait_for_volume_resource_status( - self.groups_client, group['id'], status) - - -class GroupTypesV3RbacTest(rbac_base.BaseVolumeRbacTest): - volume_min_microversion = '3.11' - volume_max_microversion = 'latest' - - @decorators.idempotent_id('2820f12c-4681-4c7f-b28d-e6925637dff6') - @rbac_rule_validation.action( - service="cinder", - rules=[_GROUP_CREATE]) - def test_create_group_type(self): - with self.override_role(): - self.create_group_type(ignore_notfound=True) - - @decorators.idempotent_id('f77f8156-4fc9-4f02-be15-8930f748e10c') - @rbac_rule_validation.action( - service="cinder", - rules=[_GROUP_DELETE]) - def test_delete_group_type(self): - group_type = self.create_group_type(ignore_notfound=True) - - with self.override_role(): - self.group_types_client.delete_group_type(group_type['id']) - - @decorators.idempotent_id('67929954-4551-4d22-b15a-27fb6e56b711') - @rbac_rule_validation.action( - service="cinder", - rules=[_GROUP_DELETE]) - def test_update_group_type(self): - group_type = self.create_group_type() - update_params = { - 'name': data_utils.rand_name( - self.__class__.__name__ + '-updated-group-type'), - 'description': 'updated-group-type-desc' - } - with self.override_role(): - self.group_types_client.update_group_type( - group_type['id'], **update_params) - - @decorators.idempotent_id('a5f88c26-df7c-4f21-a3ae-7a4c2d6212b4') - @rbac_rule_validation.action( - service="cinder", - rules=["group:access_group_types_specs"]) - def test_create_group_type_group_specs(self): - # TODO(felipemonteiro): Combine with ``test_create_group_type`` - # once multiple policy testing is supported. This policy is - # only enforced after "group:group_types_manage". - with self.override_role(): - group_type = self.create_group_type(ignore_notfound=True) - - if 'group_specs' not in group_type: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='group_specs') - - @decorators.idempotent_id('8d9e2831-24c3-47b7-a76a-2e563287f12f') - @rbac_rule_validation.action( - service="cinder", - rules=["group:access_group_types_specs"]) - def test_show_group_type(self): - group_type = self.create_group_type() - with self.override_role(): - resp_body = self.group_types_client.show_group_type( - group_type['id'])['group_type'] - if 'group_specs' not in resp_body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute='group_specs') diff --git a/patrole_tempest_plugin/tests/api/volume/test_limits_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_limits_rbac.py deleted file mode 100644 index 32baf561..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_limits_rbac.py +++ /dev/null @@ -1,55 +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. - -import testtools - -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class LimitsV3RbacTest(rbac_base.BaseVolumeRbacTest): - _api_version = 3 - - @testtools.skipUnless( - CONF.policy_feature_enabled.limits_extension_used_limits_policy, - '"limits_extension:used_limits" must be available in the cloud.') - @decorators.idempotent_id('dab04510-5b86-4479-a633-6e496ff405af') - @rbac_rule_validation.action(service="cinder", - rules=["limits_extension:used_limits"]) - def test_show_limits(self): - # It is enough to check whether any of the following keys below - # are in the response body under ['limits']['absolute'], but no harm - # in checking for them all. - expected_keys = { - 'totalVolumesUsed', - 'totalGigabytesUsed', - 'totalSnapshotsUsed', - 'totalBackupsUsed', - 'totalBackupGigabytesUsed' - } - - with self.override_role(): - absolute_limits = self.volume_limits_client.show_limits()[ - 'limits']['absolute'] - for key in expected_keys: - if key not in absolute_limits: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=key) diff --git a/patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py deleted file mode 100644 index be8424e6..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py +++ /dev/null @@ -1,148 +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.common import waiters -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - - -class VolumeQOSV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def setup_clients(cls): - super(VolumeQOSV3RbacTest, cls).setup_clients() - cls.qos_client = cls.os_primary.volume_qos_client_latest - - def _create_test_qos_specs(self, name=None, consumer=None, **kwargs): - name = name or data_utils.rand_name(self.__class__.__name__ + '-QoS') - consumer = consumer or 'front-end' - qos_specs = self.qos_client.create_qos( - name=name, consumer=consumer, **kwargs)['qos_specs'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.qos_client.delete_qos, qos_specs['id']) - return qos_specs - - @rbac_rule_validation.action( - service="cinder", rules=["volume_extension:qos_specs_manage:create"]) - @decorators.idempotent_id('4f9f45f0-b379-4577-a279-cec3e917cbec') - def test_create_qos_with_consumer(self): - with self.override_role(): - self._create_test_qos_specs() - - @rbac_rule_validation.action( - service="cinder", rules=["volume_extension:qos_specs_manage:delete"]) - @decorators.idempotent_id('fbc8a77e-6b6d-45ae-bebe-c496eb8f06f7') - def test_delete_qos_with_consumer(self): - qos = self._create_test_qos_specs() - with self.override_role(): - self.qos_client.delete_qos(qos['id']) - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:qos_specs_manage:get"]) - @decorators.idempotent_id('22aff0dd-0343-408d-ae80-e77551956e14') - def test_show_qos(self): - qos = self._create_test_qos_specs() - with self.override_role(): - self.qos_client.show_qos(qos['id'])['qos_specs'] - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:qos_specs_manage:get_all"]) - @decorators.idempotent_id('ff1e98f3-d456-40a9-96d4-c7e4a55dcffa') - def test_get_association_qos(self): - qos = self._create_test_qos_specs() - vol_type = self.create_volume_type()['id'] - self.qos_client.associate_qos(qos['id'], vol_type) - self.addCleanup(self.qos_client.disassociate_qos, qos['id'], vol_type) - - with self.override_role(): - self.qos_client.show_association_qos(qos['id']) - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:qos_specs_manage:get_all"]) - @decorators.idempotent_id('546b8bb1-04a4-4387-9506-a538a7f3cd6a') - def test_list_qos(self): - with self.override_role(): - self.qos_client.list_qos()['qos_specs'] - - @rbac_rule_validation.action( - service="cinder", rules=["volume_extension:qos_specs_manage:update"]) - @decorators.idempotent_id('89b630b7-c170-47c3-ac80-50ed425c2d98') - def test_set_qos_key(self): - qos = self._create_test_qos_specs() - with self.override_role(): - self.qos_client.set_qos_key( - qos['id'], iops_bytes='500')['qos_specs'] - - @rbac_rule_validation.action( - service="cinder", rules=["volume_extension:qos_specs_manage:update"]) - @decorators.idempotent_id('6c50c837-de77-4dae-a2ec-30e05c62969c') - def test_unset_qos_key(self): - qos = self._create_test_qos_specs() - self.qos_client.set_qos_key(qos['id'], iops_bytes='500')['qos_specs'] - - with self.override_role(): - self.qos_client.unset_qos_key(qos['id'], ['iops_bytes']) - waiters.wait_for_qos_operations(self.qos_client, qos['id'], - 'qos-key-unset', args=['iops_bytes']) - - @rbac_rule_validation.action( - service="cinder", rules=["volume_extension:qos_specs_manage:update"]) - @decorators.idempotent_id('2047b347-8bbe-405e-bf5a-c75a0d7e3930') - def test_associate_qos(self): - qos = self._create_test_qos_specs() - vol_type = self.create_volume_type()['id'] - - with self.override_role(): - self.qos_client.associate_qos(qos['id'], vol_type) - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.qos_client.disassociate_qos, qos['id'], vol_type) - - @rbac_rule_validation.action( - service="cinder", rules=["volume_extension:qos_specs_manage:update"]) - @decorators.idempotent_id('f12aeca1-0c02-4f33-b805-014171e5b2d4') - def test_disassociate_qos(self): - qos = self._create_test_qos_specs() - vol_type = self.create_volume_type()['id'] - self.qos_client.associate_qos(qos['id'], vol_type) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.qos_client.disassociate_qos, qos['id'], vol_type) - - with self.override_role(): - self.qos_client.disassociate_qos(qos['id'], vol_type) - waiters.wait_for_qos_operations(self.qos_client, qos['id'], - 'disassociate', args=vol_type) - - @rbac_rule_validation.action( - service="cinder", rules=["volume_extension:qos_specs_manage:update"]) - @decorators.idempotent_id('9f6e664d-a5d9-4e71-b122-73a3086be1b9') - def test_disassociate_all_qos(self): - qos = self._create_test_qos_specs() - vol_type = self.create_volume_type()['id'] - self.qos_client.associate_qos(qos['id'], vol_type) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.qos_client.disassociate_qos, qos['id'], vol_type) - - with self.override_role(): - self.qos_client.disassociate_all_qos(qos['id']) - waiters.wait_for_qos_operations(self.qos_client, qos['id'], - 'disassociate-all') diff --git a/patrole_tempest_plugin/tests/api/volume/test_quota_classes_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_quota_classes_rbac.py deleted file mode 100644 index f29fff1f..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_quota_classes_rbac.py +++ /dev/null @@ -1,68 +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.common import utils -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_cinder_policies_xena: - _QUOTA_SET_SHOW = "volume_extension:quota_classes:get" - _QUOTA_SET_UPDATE = "volume_extension:quota_classes:update" -else: - _QUOTA_SET_SHOW = "volume_extension:quota_classes" - _QUOTA_SET_UPDATE = "volume_extension:quota_classes" - - -class QuotaClassesV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(QuotaClassesV3RbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-quota-class-sets', 'volume'): - msg = ("%s skipped as os-quota-class-sets not enabled." - % cls.__name__) - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(QuotaClassesV3RbacTest, cls).setup_clients() - cls.quota_classes_client = cls.os_primary.quota_classes_client - cls.quota_name = data_utils.rand_name(cls.__name__ + '-QuotaClass') - - @decorators.idempotent_id('1a060def-2b43-4534-97f5-5eadbbe8c726') - @rbac_rule_validation.action(service="cinder", - rules=[_QUOTA_SET_SHOW]) - def test_show_quota_class_set(self): - with self.override_role(): - self.quota_classes_client.show_quota_class_set( - self.quota_name)['quota_class_set'] - - @decorators.idempotent_id('72159478-23a7-4c75-989f-6bac609eca62') - @rbac_rule_validation.action(service="cinder", - rules=[_QUOTA_SET_UPDATE]) - def test_update_quota_class_set(self): - quota_class_set = self.quota_classes_client.show_quota_class_set( - self.quota_name)['quota_class_set'] - quota_class_set.pop('id') - - with self.override_role(): - self.quota_classes_client.update_quota_class_set(self.quota_name, - **quota_class_set) diff --git a/patrole_tempest_plugin/tests/api/volume/test_scheduler_stats_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_scheduler_stats_rbac.py deleted file mode 100644 index 5bb57e77..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_scheduler_stats_rbac.py +++ /dev/null @@ -1,44 +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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - - -class SchedulerStatsV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(SchedulerStatsV3RbacTest, cls).skip_checks() - if not utils.is_extension_enabled('scheduler-stats', 'volume'): - msg = "%s skipped as scheduler-stats not enabled." % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(SchedulerStatsV3RbacTest, cls).setup_clients() - cls.scheduler_stats_client =\ - cls.os_primary.volume_scheduler_stats_client_latest - - @rbac_rule_validation.action( - service="cinder", - rules=["scheduler_extension:scheduler_stats:get_pools"]) - @decorators.idempotent_id('5f800441-4d30-48ec-9e5b-0d55bc86acbb') - def test_list_back_end_storage_pools(self): - with self.override_role(): - self.scheduler_stats_client.list_pools() diff --git a/patrole_tempest_plugin/tests/api/volume/test_snapshot_manage_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_snapshot_manage_rbac.py deleted file mode 100644 index f083924a..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_snapshot_manage_rbac.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2017 NEC 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.common import waiters -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 - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class SnapshotManageRbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(SnapshotManageRbacTest, cls).skip_checks() - if not CONF.volume_feature_enabled.manage_snapshot: - raise cls.skipException("Manage snapshot tests are disabled") - if len(CONF.volume.manage_snapshot_ref) != 2: - msg = ("Manage snapshot ref is not correctly configured, " - "it should be a list of two elements") - raise lib_exc.InvalidConfiguration(msg) - - @classmethod - def setup_clients(cls): - super(SnapshotManageRbacTest, cls).setup_clients() - cls.snapshot_manage_client = \ - cls.os_primary.snapshot_manage_client_latest - - @classmethod - def resource_setup(cls): - super(SnapshotManageRbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id']) - - @decorators.idempotent_id('bd7d62f2-e485-4626-87ef-03b7f19ee1d0') - @rbac_rule_validation.action( - service="cinder", - rules=["snapshot_extension:snapshot_manage"]) - def test_manage_snapshot_rbac(self): - name = data_utils.rand_name(self.__class__.__name__ + - '-Managed-Snapshot') - snapshot_ref = { - 'volume_id': self.volume['id'], - 'ref': {CONF.volume.manage_snapshot_ref[0]: - CONF.volume.manage_snapshot_ref[1] % self.snapshot['id']}, - 'name': name - } - with self.override_role(): - snapshot = self.snapshot_manage_client.manage_snapshot( - **snapshot_ref)['snapshot'] - self.addCleanup(self.delete_snapshot, snapshot['id'], - self.snapshots_client) - waiters.wait_for_volume_resource_status(self.snapshots_client, - snapshot['id'], - 'available') - - @decorators.idempotent_id('4a2e8934-9c0b-434e-8f0b-e18b9aff126f') - @rbac_rule_validation.action( - service="cinder", - rules=["snapshot_extension:snapshot_unmanage"]) - def test_unmanage_snapshot_rbac(self): - with self.override_role(): - self.snapshots_client.unmanage_snapshot(self.snapshot['id']) - self.snapshots_client.wait_for_resource_deletion( - self.snapshot['id']) diff --git a/patrole_tempest_plugin/tests/api/volume/test_snapshots_actions_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_snapshots_actions_rbac.py deleted file mode 100644 index b3714ba5..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_snapshots_actions_rbac.py +++ /dev/null @@ -1,87 +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.common import waiters -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class SnapshotsActionsV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(SnapshotsActionsV3RbacTest, cls).skip_checks() - if not CONF.volume_feature_enabled.snapshot: - raise cls.skipException("Cinder snapshot feature disabled") - - @classmethod - def resource_setup(cls): - super(SnapshotsActionsV3RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id']) - cls.snapshot_id = cls.snapshot['id'] - - def tearDown(self): - # Set snapshot's status to available after test - status = 'available' - self.snapshots_client.reset_snapshot_status(self.snapshot_id, - status) - waiters.wait_for_volume_resource_status(self.snapshots_client, - self.snapshot_id, status) - super(SnapshotsActionsV3RbacTest, self).tearDown() - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:snapshot_admin_actions:reset_status"]) - @decorators.idempotent_id('ea430145-34ef-408d-b678-95d5ae5f46eb') - def test_reset_snapshot_status(self): - status = 'error' - with self.override_role(): - self.snapshots_client.reset_snapshot_status( - self.snapshot['id'], status) - waiters.wait_for_volume_resource_status( - self.snapshots_client, self.snapshot['id'], status) - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:snapshot_admin_actions:force_delete"]) - @decorators.idempotent_id('a8b0f7d8-4c00-4645-b8d5-33ab4eecc6cb') - def test_snapshot_force_delete(self): - temp_snapshot = self.create_snapshot(self.volume['id']) - - with self.override_role(): - self.snapshots_client.force_delete_snapshot(temp_snapshot['id']) - self.snapshots_client.wait_for_resource_deletion(temp_snapshot['id']) - - @decorators.idempotent_id('a95eab2a-c441-4609-9235-f7478627da88') - @rbac_rule_validation.action( - service="cinder", - rules=["snapshot_extension:snapshot_actions:update_snapshot_status"]) - def test_update_snapshot_status(self): - status = 'creating' - self.snapshots_client.reset_snapshot_status( - self.snapshot['id'], status) - waiters.wait_for_volume_resource_status(self.snapshots_client, - self.snapshot['id'], status) - with self.override_role(): - self.snapshots_client.update_snapshot_status(self.snapshot['id'], - status="creating") - waiters.wait_for_volume_resource_status( - self.snapshots_client, self.snapshot['id'], status) diff --git a/patrole_tempest_plugin/tests/api/volume/test_snapshots_metadata_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_snapshots_metadata_rbac.py deleted file mode 100644 index bf452ce7..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_snapshots_metadata_rbac.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright 2016 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 tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class SnapshotMetadataV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(SnapshotMetadataV3RbacTest, cls).skip_checks() - if not CONF.volume_feature_enabled.snapshot: - raise cls.skipException("Cinder snapshot feature disabled") - - @classmethod - def resource_setup(cls): - super(SnapshotMetadataV3RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - # Create a snapshot - cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id']) - cls.snapshot_id = cls.snapshot['id'] - - @classmethod - def _create_test_snapshot_metadata(cls): - # Create test snapshot metadata - metadata = {"key1": "value1", - "key2": "value2", - "key3": "value3"} - cls.snapshots_client.create_snapshot_metadata( - cls.snapshot_id, metadata)['metadata'] - - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_snapshot_metadata"]) - @decorators.idempotent_id('f6912bb1-62e6-483d-bcd0-e98c1641f4c3') - def test_get_snapshot_metadata(self): - # Create volume and snapshot metadata - self._create_test_snapshot_metadata() - # Get metadata for the snapshot - with self.override_role(): - self.snapshots_client.show_snapshot_metadata( - self.snapshot_id) - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_tenant_attribute"]) - @decorators.idempotent_id('e2c73b00-0c19-4bb7-8c61-d84b1a223ed1') - def test_get_snapshot_metadata_for_volume_tenant(self): - # Create volume and snapshot metadata - self._create_test_snapshot_metadata() - # Get the metadata of the snapshot - with self.override_role(): - self.snapshots_client.show_snapshot_metadata( - self.snapshot_id)['metadata'] - - @decorators.idempotent_id('7ea597f6-c544-4b10-aab0-ff68f595fb06') - @rbac_rule_validation.action(service="cinder", - rules=["volume:update_snapshot_metadata"]) - def test_update_snapshot_metadata(self): - self._create_test_snapshot_metadata() - with self.override_role(): - update = {"key3": "value3_update", - "key4": "value4"} - self.snapshots_client.update_snapshot_metadata( - self.snapshot['id'], metadata=update) - - @decorators.idempotent_id('93068d02-0131-4dd3-af16-fc40d7128d93') - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_snapshot_metadata"]) - def test_show_snapshot_metadata_item(self): - self._create_test_snapshot_metadata() - with self.override_role(): - self.snapshots_client.show_snapshot_metadata_item( - self.snapshot['id'], "key3")['meta'] - - @decorators.idempotent_id('1f8f43e7-da31-4128-bb3c-73fc548650e3') - @rbac_rule_validation.action(service="cinder", - rules=["volume:update_snapshot_metadata"]) - def test_update_snapshot_metadata_item(self): - update_item = {"key3": "value3_update"} - self._create_test_snapshot_metadata() - with self.override_role(): - self.snapshots_client.update_snapshot_metadata_item( - self.snapshot['id'], "key3", meta=update_item)['meta'] - - @decorators.idempotent_id('3ec32516-f7cd-4f88-b78a-ddee67492071') - @rbac_rule_validation.action(service="cinder", - rules=["volume:delete_snapshot_metadata"]) - def test_delete_snapshot_metadata_item(self): - self._create_test_snapshot_metadata() - with self.override_role(): - self.snapshots_client.delete_snapshot_metadata_item( - self.snapshot['id'], "key1") diff --git a/patrole_tempest_plugin/tests/api/volume/test_user_messages_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_user_messages_rbac.py deleted file mode 100644 index 3feb2dfc..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_user_messages_rbac.py +++ /dev/null @@ -1,92 +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 import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class MessagesV3RbacTest(rbac_base.BaseVolumeRbacTest): - volume_min_microversion = '3.3' - volume_max_microversion = 'latest' - - @classmethod - def setup_clients(cls): - super(MessagesV3RbacTest, cls).setup_clients() - cls.messages_client = cls.os_primary.volume_messages_client_latest - - def _create_user_message(self): - """Trigger a 'no valid host' situation to generate a message.""" - bad_protocol = data_utils.rand_name( - self.__class__.__name__ + '-storage_protocol') - bad_vendor = data_utils.rand_name( - self.__class__.__name__ + '-vendor_name') - extra_specs = {'storage_protocol': bad_protocol, - 'vendor_name': bad_vendor} - vol_type_name = data_utils.rand_name( - self.__class__.__name__ + '-volume-type') - bogus_type = self.create_volume_type( - name=vol_type_name, extra_specs=extra_specs) - params = {'volume_type': bogus_type['id'], - 'size': CONF.volume.volume_size} - volume = self.create_volume(wait_until="error", **params) - messages = self.messages_client.list_messages()['messages'] - message_id = None - for message in messages: - if message['resource_uuid'] == volume['id']: - message_id = message['id'] - break - self.assertIsNotNone(message_id, 'No user message generated for ' - 'volume %s' % volume['id']) - - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.messages_client.delete_message, message_id) - - return message_id - - @decorators.idempotent_id('bf7f31a1-509b-4a7d-a8a8-ad6ce68229c7') - @rbac_rule_validation.action( - service="cinder", - rules=["message:get_all"]) - def test_list_messages(self): - with self.override_role(): - self.messages_client.list_messages()['messages'] - - @decorators.idempotent_id('9cc1ad1e-68a2-4407-8b60-ea77909bce08') - @rbac_rule_validation.action( - service="cinder", - rules=["message:get"]) - def test_show_message(self): - message_id = self._create_user_message() - - with self.override_role(): - self.messages_client.show_message(message_id)['message'] - - @decorators.idempotent_id('65ca7fb7-7f2c-443e-b144-ac86973a97be') - @rbac_rule_validation.action( - service="cinder", - rules=["message:delete"]) - def test_delete_message(self): - message_id = self._create_user_message() - - with self.override_role(): - self.messages_client.delete_message(message_id) - self.messages_client.wait_for_resource_deletion(message_id) diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py deleted file mode 100644 index e3311eae..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py +++ /dev/null @@ -1,293 +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. - -import testtools - -from tempest.common import compute -from tempest.common import utils -from tempest.common import waiters -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class VolumesActionsV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def setup_clients(cls): - super(VolumesActionsV3RbacTest, cls).setup_clients() - cls.image_client = cls.os_primary.image_client_v2 - - @classmethod - def setup_credentials(cls): - cls.set_network_resources(network=True, subnet=True, router=True) - super(VolumesActionsV3RbacTest, cls).setup_credentials() - - @classmethod - def resource_setup(cls): - super(VolumesActionsV3RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - - def _create_server(self): - tenant_network = self.get_tenant_network() - server, _ = compute.create_test_server( - self.os_primary, tenant_network=tenant_network, - wait_until='ACTIVE') - self.addCleanup(waiters.wait_for_server_termination, - self.servers_client, server['id']) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.servers_client.delete_server, server['id']) - return server - - def _attach_volume(self, server, volume_id=None): - if volume_id is None: - volume_id = self.volume['id'] - - self.servers_client.attach_volume( - server['id'], volumeId=volume_id, - device='/dev/%s' % CONF.compute.volume_device_name) - waiters.wait_for_volume_resource_status( - self.volumes_client, volume_id, 'in-use') - self.addCleanup(self._detach_volume, volume_id) - - def _detach_volume(self, volume_id=None): - if volume_id is None: - volume_id = self.volume['id'] - - self.volumes_client.detach_volume(volume_id) - waiters.wait_for_volume_resource_status( - self.volumes_client, volume_id, 'available') - - @testtools.skipUnless( - CONF.policy_feature_enabled - .volume_extension_volume_actions_attach_policy, - '"volume_extension:volume_actions:attach" must be available in the ' - 'cloud.') - @utils.services('compute') - @decorators.attr(type='slow') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_actions:attach"]) - @decorators.idempotent_id('f97b10e4-2eed-4f8b-8632-71c02cb9fe42') - def test_attach_volume_to_instance(self): - server = self._create_server() - volume_id = self.volume['id'] - - with self.override_role(): - self.servers_client.attach_volume( - server['id'], volumeId=volume_id, - device='/dev/%s' % CONF.compute.volume_device_name) - waiters.wait_for_volume_resource_status( - self.volumes_client, volume_id, 'in-use') - self.addCleanup(self._detach_volume, volume_id) - - @utils.services('compute') - @decorators.attr(type='slow') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_actions:detach"]) - @decorators.idempotent_id('5a042f6a-688b-42e6-a02e-fe5c47b89b07') - def test_detach_volume_from_instance(self): - server = self._create_server() - self._attach_volume(server) - volume_id = self.volume['id'] - - with self.override_role(): - self.volumes_client.detach_volume(volume_id) - waiters.wait_for_volume_resource_status( - self.volumes_client, volume_id, 'available') - - @rbac_rule_validation.action(service="cinder", - rules=["volume:update_readonly_flag"]) - @decorators.idempotent_id('2750717a-f250-4e41-9e09-02624aad6ff8') - def test_volume_readonly_update(self): - with self.override_role(): - self.volumes_client.update_volume_readonly(self.volume['id'], - readonly=True) - self.addCleanup(self.volumes_client.update_volume_readonly, - self.volume['id'], readonly=False) - - @decorators.idempotent_id('59b783c0-f4ef-430c-8a90-1bad97d4ec5c') - @rbac_rule_validation.action(service="cinder", - rules=["volume:update"]) - def test_volume_set_bootable(self): - with self.override_role(): - self.volumes_client.set_bootable_volume(self.volume['id'], - bootable=True) - - @testtools.skipUnless( - CONF.policy_feature_enabled - .volume_extension_volume_actions_reserve_policy, - '"volume_extension:volume_actions:reserve" must be available in the ' - 'cloud.') - @decorators.idempotent_id('41566922-75a1-4484-99c7-9c8782ee99ac') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_actions:reserve"]) - def test_volume_reserve(self): - with self.override_role(): - self.volumes_client.reserve_volume(self.volume['id']) - - @testtools.skipUnless( - CONF.policy_feature_enabled - .volume_extension_volume_actions_unreserve_policy, - '"volume_extension:volume_actions:unreserve" must be available in the ' - 'cloud.') - @decorators.idempotent_id('e5fa9564-77d9-4e57-b0c0-3e0ae4d08535') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_actions:unreserve"]) - def test_volume_unreserve(self): - with self.override_role(): - self.volumes_client.unreserve_volume(self.volume['id']) - - @decorators.idempotent_id('c015c82f-7010-48cc-bd71-4ef542046f20') - @rbac_rule_validation.action(service="cinder", - rules=["volume:retype"]) - def test_volume_retype(self): - vol_type = self.create_volume_type()['name'] - volume = self.create_volume() - - with self.override_role(): - self.volumes_client.retype_volume(volume['id'], new_type=vol_type) - waiters.wait_for_volume_retype( - self.volumes_client, volume['id'], vol_type) - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_admin_actions:reset_status"]) - @decorators.idempotent_id('4b3dad7d-0e73-4839-8781-796dd3d7af1d') - def test_volume_reset_status(self): - volume = self.create_volume() - - with self.override_role(): - self.volumes_client.reset_volume_status( - volume['id'], status='error') - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_admin_actions:force_delete"]) - @decorators.idempotent_id('a312a937-6abf-4b91-a950-747086cbce48') - def test_volume_force_delete(self): - volume = self.create_volume() - self.volumes_client.reset_volume_status(volume['id'], status='error') - - with self.override_role(): - self.volumes_client.force_delete_volume(volume['id']) - self.volumes_client.wait_for_resource_deletion(volume['id']) - - @decorators.idempotent_id('48bd302b-950a-4830-840c-3158246ecdcc') - @utils.services('compute') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_admin_actions:force_detach"]) - def test_force_detach_volume_from_instance(self): - volume = self.create_volume() - server = self._create_server() - self._attach_volume(server, volume['id']) - attachment = self.volumes_client.show_volume( - volume['id'])['volume']['attachments'][0] - - # Reset volume's status to error. - self.volumes_client.reset_volume_status(volume['id'], status='error') - waiters.wait_for_volume_resource_status(self.volumes_client, - volume['id'], 'error') - with self.override_role(): - self.volumes_client.force_detach_volume( - volume['id'], connector=None, - attachment_id=attachment['attachment_id']) - waiters.wait_for_volume_resource_status(self.volumes_client, - volume['id'], 'available') - - -class VolumesActionsV310RbacTest(rbac_base.BaseVolumeRbacTest): - _api_version = 3 - volume_min_microversion = '3.10' - volume_max_microversion = 'latest' - - @classmethod - def setup_clients(cls): - super(VolumesActionsV310RbacTest, cls).setup_clients() - cls.image_client = cls.os_primary.image_client_v2 - - @classmethod - def resource_setup(cls): - super(VolumesActionsV310RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - - @decorators.attr(type=["slow"]) - @utils.services('image') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_actions:upload_image"]) - @decorators.idempotent_id('b0d0da46-903c-4445-893e-20e680d68b50') - def test_volume_upload_image(self): - # TODO(felipemonteiro): The ``upload_volume`` endpoint also enforces - # "volume:copy_volume_to_image". - image_name = data_utils.rand_name(self.__class__.__name__ + '-Image') - - with self.override_role(): - body = self.volumes_client.upload_volume( - self.volume['id'], image_name=image_name, visibility="private", - disk_format=CONF.volume.disk_format)['os-volume_upload_image'] - image_id = body["image_id"] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.image_client.delete_image, - image_id) - waiters.wait_for_image_status(self.image_client, image_id, - 'active') - waiters.wait_for_volume_resource_status(self.volumes_client, - self.volume['id'], 'available') - - @decorators.attr(type=["slow"]) - @utils.services('image') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_actions:upload_public"]) - @decorators.idempotent_id('578a84dd-a6bd-4f97-a418-4a0c3c272c08') - def test_volume_upload_public(self): - # This also enforces "volume_extension:volume_actions:upload_image". - image_name = data_utils.rand_name(self.__class__.__name__ + '-Image') - - with self.override_role(): - body = self.volumes_client.upload_volume( - self.volume['id'], image_name=image_name, visibility="public", - disk_format=CONF.volume.disk_format)['os-volume_upload_image'] - image_id = body["image_id"] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.image_client.delete_image, - image_id) - waiters.wait_for_image_status(self.image_client, image_id, - 'active') - waiters.wait_for_volume_resource_status(self.volumes_client, - self.volume['id'], 'available') - - -class VolumesActionsV312RbacTest(rbac_base.BaseVolumeRbacTest): - _api_version = 3 - volume_min_microversion = '3.12' - volume_max_microversion = 'latest' - - @decorators.idempotent_id('a654833d-4811-4acd-93ef-5ac4a34c75bc') - @rbac_rule_validation.action(service="cinder", rules=["volume:get_all"]) - def test_show_volume_summary(self): - with self.override_role(): - self.volumes_client.show_volume_summary() diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py deleted file mode 100644 index e4958f5a..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py +++ /dev/null @@ -1,100 +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.common import waiters -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class VolumesBasicCrudV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def resource_setup(cls): - super(VolumesBasicCrudV3RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - - @rbac_rule_validation.action(service="cinder", - rules=["volume:create"]) - @decorators.idempotent_id('426b08ef-6394-4d06-9128-965d5a6c38ef') - def test_create_volume(self): - name = data_utils.rand_name(self.__class__.__name__ + '-Volume') - size = CONF.volume.volume_size - - with self.override_role(): - volume = self.volumes_client.create_volume(name=name, size=size)[ - 'volume'] - # Use helper in base Tempest volume class which waits for deletion. - self.addCleanup(self.delete_volume, self.volumes_client, volume['id']) - waiters.wait_for_volume_resource_status(self.volumes_client, - volume['id'], 'available') - - @decorators.idempotent_id('a009e6dc-e8bf-4412-99f5-8e45cffcffec') - @rbac_rule_validation.action(service="cinder", - rules=["volume:create_from_image"]) - def test_create_volume_from_image(self): - name = data_utils.rand_name(self.__class__.__name__ + '-Volume') - size = CONF.volume.volume_size - img_uuid = CONF.compute.image_ref - - with self.override_role(): - volume = self.volumes_client.create_volume( - name=name, size=size, imageRef=img_uuid)['volume'] - # Use helper in base Tempest volume class which waits for deletion. - self.addCleanup(self.delete_volume, self.volumes_client, volume['id']) - waiters.wait_for_volume_resource_status(self.volumes_client, - volume['id'], 'available') - - @rbac_rule_validation.action(service="cinder", - rules=["volume:delete"]) - @decorators.idempotent_id('6de9f9c2-509f-4558-867b-af21c7163be4') - def test_delete_volume(self): - volume = self.create_volume() - with self.override_role(): - self.volumes_client.delete_volume(volume['id']) - self.volumes_client.wait_for_resource_deletion(volume['id']) - - @rbac_rule_validation.action(service="cinder", rules=["volume:get"]) - @decorators.idempotent_id('c4c3fdd5-b1b1-49c3-b977-a9f40ee9257a') - def test_show_volume(self): - with self.override_role(): - self.volumes_client.show_volume(self.volume['id']) - - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_all"]) - @decorators.idempotent_id('e3ab7906-b04b-4c45-aa11-1104d302f940') - def test_list_volumes(self): - with self.override_role(): - self.volumes_client.list_volumes() - - @decorators.idempotent_id('9b6d5beb-254f-4f1b-9906-0bdce4042f53') - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_all"]) - def test_list_volumes_with_details(self): - with self.override_role(): - self.volumes_client.list_volumes(detail=True) - - @rbac_rule_validation.action(service="cinder", rules=["volume:update"]) - @decorators.idempotent_id('b751b889-9a9b-40d8-ae7d-4b0f65e71ac7') - def test_update_volume(self): - update_name = data_utils.rand_name(self.__class__.__name__ + 'volume') - with self.override_role(): - self.volumes_client.update_volume(self.volume['id'], - name=update_name) diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py deleted file mode 100644 index b3fb0b6c..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py +++ /dev/null @@ -1,41 +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 patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - - -class VolumeHostsV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @rbac_rule_validation.action(service="cinder", - rules=["volume_extension:hosts"]) - @decorators.idempotent_id('64e837f5-5452-4e26-b934-c721ea7a8644') - def test_list_hosts(self): - with self.override_role(): - self.volume_hosts_client.list_hosts() - - @decorators.idempotent_id('9ddf321e-788f-4787-b8cc-dfa59e264143') - @rbac_rule_validation.action(service="cinder", - rules=["volume_extension:hosts"]) - def test_show_host(self): - hosts = self.volume_hosts_client.list_hosts()['hosts'] - host_names = [host['host_name'] for host in hosts] - self.assertNotEmpty(host_names, "No available volume host was found, " - "all hosts found were: %s" % hosts) - - with self.override_role(): - self.volume_hosts_client.show_host(host_names[0]) diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py deleted file mode 100644 index d7ae6ee8..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py +++ /dev/null @@ -1,168 +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 import config -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_cinder_policies_xena: - _METADATA_SHOW = "volume_extension:volume_image_metadata:show" - _METADATA_SET = "volume_extension:volume_image_metadata:set" - _METADATA_REMOVE = "volume_extension:volume_image_metadata:remove" -else: - _METADATA_SHOW = "volume_extension:volume_image_metadata" - _METADATA_SET = "volume_extension:volume_image_metadata" - _METADATA_REMOVE = "volume_extension:volume_image_metadata" - - -class VolumeMetadataV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def resource_setup(cls): - super(VolumeMetadataV3RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - cls.image_id = CONF.compute.image_ref - - def _add_metadata(self, volume): - # Create metadata for the volume. - metadata = {"key1": "value1"} - self.volumes_client.create_volume_metadata( - self.volume['id'], metadata)['metadata'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.volumes_client.delete_volume_metadata_item, - self.volume['id'], "key1") - - @rbac_rule_validation.action(service="cinder", - rules=["volume:create_volume_metadata"]) - @decorators.idempotent_id('232bbb8b-4c29-44dc-9077-b1398c20b738') - def test_create_volume_metadata(self): - with self.override_role(): - self._add_metadata(self.volume) - - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_volume_metadata"]) - @decorators.idempotent_id('87ea37d9-23ab-47b2-a59c-16fc4d2c6dfa') - def test_show_volume_metadata(self): - with self.override_role(): - self.volumes_client.show_volume_metadata( - self.volume['id'])['metadata'] - - @decorators.idempotent_id('5c0f4c19-b448-4f51-9224-dad5faddc3bb') - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_volume_metadata"]) - def test_show_volume_metadata_item(self): - self._add_metadata(self.volume) - - with self.override_role(): - self.volumes_client.show_volume_metadata_item( - self.volume['id'], "key1") - - @rbac_rule_validation.action(service="cinder", - rules=["volume:delete_volume_metadata"]) - @decorators.idempotent_id('7498dfc1-9db2-4423-ad20-e6dcb25d1beb') - def test_delete_volume_metadata_item(self): - self._add_metadata(self.volume) - - with self.override_role(): - self.volumes_client.delete_volume_metadata_item(self.volume['id'], - "key1") - - @rbac_rule_validation.action(service="cinder", - rules=["volume:update_volume_metadata"]) - @decorators.idempotent_id('8ce2ff80-99ba-49ae-9bb1-7e96729ee5af') - def test_update_volume_metadata_item(self): - self._add_metadata(self.volume) - updated_metadata_item = {"key1": "value1_update"} - with self.override_role(): - self.volumes_client.update_volume_metadata_item( - self.volume['id'], "key1", updated_metadata_item)['meta'] - - @decorators.idempotent_id('a231b445-97a5-4657-b05f-245895e88da9') - @rbac_rule_validation.action(service="cinder", - rules=["volume:update_volume_metadata"]) - def test_update_volume_metadata(self): - self._add_metadata(self.volume) - updated_metadata = {"key1": "value1"} - with self.override_role(): - self.volumes_client.update_volume_metadata(self.volume['id'], - updated_metadata) - - @decorators.idempotent_id('39e8f82c-f1fc-4905-bf47-177ce2f71bb9') - @rbac_rule_validation.action( - service="cinder", - rules=[_METADATA_SET]) - def test_list_volumes_details_image_metadata(self): - self.volumes_client.update_volume_image_metadata( - self.volume['id'], image_id=self.image_id) - self.addCleanup(self.volumes_client.delete_volume_image_metadata, - self.volume['id'], 'image_id') - - with self.override_role(): - resp_body = self.volumes_client.list_volumes(detail=True)[ - 'volumes'] - expected_attr = 'volume_image_metadata' - if expected_attr not in resp_body[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @decorators.idempotent_id('53f94d52-0dd5-42cf-a3a4-59b35150b3d5') - @rbac_rule_validation.action( - service="cinder", - rules=[_METADATA_SHOW]) - def test_show_volume_details_image_metadata(self): - self.volumes_client.update_volume_image_metadata( - self.volume['id'], image_id=self.image_id) - self.addCleanup(self.volumes_client.delete_volume_image_metadata, - self.volume['id'], 'image_id') - - with self.override_role(): - resp_body = self.volumes_client.show_volume(self.volume['id'])[ - 'volume'] - expected_attr = 'volume_image_metadata' - if expected_attr not in resp_body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @decorators.idempotent_id('a9d9e825-5ea3-42e6-96f3-7ac4e97b2ed0') - @rbac_rule_validation.action( - service="cinder", - rules=[_METADATA_SET]) - def test_update_volume_image_metadata(self): - with self.override_role(): - self.volumes_client.update_volume_image_metadata( - self.volume['id'], image_id=self.image_id) - self.addCleanup(self.volumes_client.delete_volume_image_metadata, - self.volume['id'], 'image_id') - - @decorators.idempotent_id('a41c8eed-2051-4a25-b401-df036faacbdc') - @rbac_rule_validation.action( - service="cinder", - rules=[_METADATA_REMOVE]) - def test_delete_volume_image_metadata(self): - self.volumes_client.update_volume_image_metadata( - self.volume['id'], image_id=self.image_id) - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.volumes_client.delete_volume_image_metadata, - self.volume['id'], 'image_id') - - with self.override_role(): - self.volumes_client.delete_volume_image_metadata(self.volume['id'], - 'image_id') diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_quotas_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_quotas_rbac.py deleted file mode 100644 index 6d27d2c6..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_quotas_rbac.py +++ /dev/null @@ -1,89 +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 patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -QUOTA_KEYS = ['gigabytes', 'snapshots', 'volumes', 'backups', - 'backup_gigabytes', 'per_volume_gigabytes'] - - -class VolumeQuotasV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def setup_credentials(cls): - super(VolumeQuotasV3RbacTest, cls).setup_credentials() - cls.demo_tenant_id = cls.os_primary.credentials.tenant_id - - @classmethod - def setup_clients(cls): - super(VolumeQuotasV3RbacTest, cls).setup_clients() - cls.quotas_client = cls.os_primary.volume_quotas_client_latest - - def _restore_default_quota_set(self): - default_quota_set = self.quotas_client.show_default_quota_set( - self.demo_tenant_id)['quota_set'] - cleanup_quota_set = dict( - (k, v) for k, v in default_quota_set.items() - if k in QUOTA_KEYS) - self.addCleanup(self.quotas_client.update_quota_set, - self.demo_tenant_id, **cleanup_quota_set) - - @decorators.idempotent_id('427c9f0c-982e-403d-ae45-c05f4d6322ff') - @rbac_rule_validation.action(service="cinder", - rules=["volume_extension:quotas:show"]) - def test_list_quotas(self): - with self.override_role(): - self.quotas_client.show_quota_set(self.demo_tenant_id) - - @decorators.idempotent_id('e47cf444-2753-4983-be6d-fc0d6523720f') - @rbac_rule_validation.action(service="cinder", - rules=["volume_extension:quotas:show"]) - def test_list_quotas_usage_true(self): - with self.override_role(): - self.quotas_client.show_quota_set(self.demo_tenant_id, - params={'usage': True}) - - @rbac_rule_validation.action(service="cinder", - rules=["volume_extension:quotas:show"]) - @decorators.idempotent_id('b3c7177e-b6b1-4d0f-810a-fc95606964dd') - def test_list_default_quotas(self): - with self.override_role(): - self.quotas_client.show_default_quota_set( - self.demo_tenant_id) - - @rbac_rule_validation.action(service="cinder", - rules=["volume_extension:quotas:update"]) - @decorators.idempotent_id('60f8f421-1630-4953-b449-b22af32265c7') - def test_update_quota_set(self): - self._restore_default_quota_set() - new_quota_set = {'gigabytes': 1009, - 'volumes': 11, - 'snapshots': 11} - # Update limits for all quota resources. - with self.override_role(): - self.quotas_client.update_quota_set( - self.demo_tenant_id, **new_quota_set) - - @decorators.idempotent_id('329bdb88-5132-4810-b1fc-350d181577e3') - @rbac_rule_validation.action(service="cinder", - rules=["volume_extension:quotas:delete"]) - def test_delete_quota_set(self): - self._restore_default_quota_set() - - with self.override_role(): - self.quotas_client.delete_quota_set(self.demo_tenant_id) diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_services_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_services_rbac.py deleted file mode 100644 index 945d0162..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_services_rbac.py +++ /dev/null @@ -1,47 +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.common import utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - - -class VolumeServicesV3RbacTest(rbac_base.BaseVolumeRbacTest): - - # TODO(felipemonteiro): Implement a test to cover the policy action, - # "volume_extension:services:update", once the Tempest client endpoint - # is implemented. - - @classmethod - def skip_checks(cls): - super(VolumeServicesV3RbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-services', 'volume'): - msg = "%s skipped as os-services not enabled." % cls.__name__ - raise cls.skipException(msg) - - @classmethod - def setup_clients(cls): - super(VolumeServicesV3RbacTest, cls).setup_clients() - cls.services_client = cls.os_primary.volume_services_client_latest - - @decorators.idempotent_id('b9134f01-97c0-4abd-9455-fe2f03e3f966') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:services:index"]) - def test_list_services(self): - with self.override_role(): - self.services_client.list_services()['services'] diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py deleted file mode 100644 index e52e0741..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py +++ /dev/null @@ -1,110 +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.common import waiters -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - - -class VolumesTransfersV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def setup_clients(cls): - super(VolumesTransfersV3RbacTest, cls).setup_clients() - cls.transfers_client = cls.os_primary.volume_transfers_client_latest - - @classmethod - def resource_setup(cls): - super(VolumesTransfersV3RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - - def _delete_transfer(self, transfer): - # Volume from create_volume_transfer test may get stuck in - # 'awaiting-transfer' state, preventing cleanup and causing - # the test to fail. - test_utils.call_and_ignore_notfound_exc( - self.transfers_client.delete_volume_transfer, transfer['id']) - waiters.wait_for_volume_resource_status( - self.volumes_client, self.volume['id'], 'available') - - def _create_transfer(self): - transfer = self.transfers_client.create_volume_transfer( - volume_id=self.volume['id'])['transfer'] - self.addCleanup(self._delete_transfer, transfer) - return transfer - - @rbac_rule_validation.action(service="cinder", - rules=["volume:create_transfer"]) - @decorators.idempotent_id('25413af4-468d-48ff-94ca-4436f8526b3e') - def test_create_volume_transfer(self): - with self.override_role(): - self._create_transfer() - waiters.wait_for_volume_resource_status( - self.volumes_client, self.volume['id'], 'awaiting-transfer') - - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_transfer"]) - @decorators.idempotent_id('7a0925d3-ed97-4c25-8299-e5cdabe2eb55') - def test_get_volume_transfer(self): - transfer = self._create_transfer() - waiters.wait_for_volume_resource_status( - self.volumes_client, self.volume['id'], 'awaiting-transfer') - - with self.override_role(): - self.transfers_client.show_volume_transfer(transfer['id']) - - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_all_transfers"]) - @decorators.idempotent_id('02a06f2b-5040-49e2-b2b7-619a7db59603') - def test_list_volume_transfers(self): - with self.override_role(): - self.transfers_client.list_volume_transfers() - - @decorators.idempotent_id('e84e45b0-9872-40bf-bf44-971266161a86') - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_all_transfers"]) - def test_list_volume_transfers_details(self): - with self.override_role(): - self.transfers_client.list_volume_transfers(detail=True) - - @rbac_rule_validation.action(service="cinder", - rules=["volume:accept_transfer"]) - @decorators.idempotent_id('987f2a11-d657-4984-a6c9-28f06c1cd014') - def test_accept_volume_transfer(self): - transfer = self._create_transfer() - waiters.wait_for_volume_resource_status( - self.volumes_client, self.volume['id'], 'awaiting-transfer') - - with self.override_role(): - self.transfers_client.accept_volume_transfer( - transfer['id'], auth_key=transfer['auth_key']) - waiters.wait_for_volume_resource_status(self.volumes_client, - self.volume['id'], 'available') - - @rbac_rule_validation.action(service="cinder", - rules=["volume:delete_transfer"]) - @decorators.idempotent_id('4672187e-7fff-454b-832a-5c8865dda868') - def test_delete_volume_transfer(self): - transfer = self._create_transfer() - waiters.wait_for_volume_resource_status( - self.volumes_client, self.volume['id'], 'awaiting-transfer') - - with self.override_role(): - self.transfers_client.delete_volume_transfer(transfer['id']) - waiters.wait_for_volume_resource_status( - self.volumes_client, self.volume['id'], 'available') diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_types_access_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_types_access_rbac.py deleted file mode 100644 index d07a4013..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_types_access_rbac.py +++ /dev/null @@ -1,88 +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.common import utils -from tempest import config -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_cinder_policies_xena: - _TYPE_ACCESS_LIST = "volume_extension:volume_type_access:get_all_for_type" -else: - _TYPE_ACCESS_LIST = "volume_extension:volume_type_access" - - -class VolumeTypesAccessRbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(VolumeTypesAccessRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-volume-type-access', 'volume'): - msg = "os-volume-type-access extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(VolumeTypesAccessRbacTest, cls).resource_setup() - cls.vol_type = cls.create_volume_type( - **{'os-volume-type-access:is_public': False}) - cls.project_id = cls.os_primary.credentials.project_id - - def _add_type_access(self, ignore_not_found=False): - self.volume_types_client.add_type_access( - self.vol_type['id'], project=self.project_id) - - if ignore_not_found: - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.volume_types_client.remove_type_access, - self.vol_type['id'], project=self.project_id) - else: - self.addCleanup(self.volume_types_client.remove_type_access, - self.vol_type['id'], project=self.project_id) - - @decorators.idempotent_id('af70e6ad-e931-419f-9200-8bcc284e4e47') - @rbac_rule_validation.action( - service="cinder", - rules=[_TYPE_ACCESS_LIST]) - def test_list_type_access(self): - self._add_type_access() - - with self.override_role(): - self.volume_types_client.list_type_access(self.vol_type['id'])[ - 'volume_type_access'] - - @decorators.idempotent_id('b462eeba-45d0-4d6e-945a-a1d27708d367') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_type_access:addProjectAccess"]) - def test_add_type_access(self): - with self.override_role(): - self._add_type_access(ignore_not_found=True) - - @decorators.idempotent_id('8f848aeb-636a-46f1-aeeb-e2a60e9d2bfe') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_type_access:removeProjectAccess"]) - def test_remove_type_access(self): - self._add_type_access(ignore_not_found=True) - - with self.override_role(): - self.volume_types_client.remove_type_access( - self.vol_type['id'], project=self.project_id) diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_types_extra_specs_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_types_extra_specs_rbac.py deleted file mode 100644 index f4e625f5..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_types_extra_specs_rbac.py +++ /dev/null @@ -1,107 +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.common import utils -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - - -class VolumeTypesExtraSpecsRbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(VolumeTypesExtraSpecsRbacTest, cls).skip_checks() - if not utils.is_extension_enabled('os-types-extra-specs', 'volume'): - msg = "os-types-extra-specs extension not enabled." - raise cls.skipException(msg) - - @classmethod - def resource_setup(cls): - super(VolumeTypesExtraSpecsRbacTest, cls).resource_setup() - cls.vol_type = cls.create_volume_type() - - def setUp(self): - super(VolumeTypesExtraSpecsRbacTest, self).setUp() - self.spec_key = data_utils.rand_name('-VolumeTypesExtraSpec') - - def _create_volume_type_extra_specs(self, ignore_not_found=False): - extra_specs = {self.spec_key: "val1"} - self.volume_types_client.create_volume_type_extra_specs( - self.vol_type['id'], extra_specs) - - if ignore_not_found: - self.addCleanup( - test_utils.call_and_ignore_notfound_exc, - self.volume_types_client.delete_volume_type_extra_specs, - self.vol_type['id'], self.spec_key) - else: - self.addCleanup( - self.volume_types_client.delete_volume_type_extra_specs, - self.vol_type['id'], self.spec_key) - - @decorators.idempotent_id('76c36be2-2b6c-4acf-9aac-c9dc5c17cdbe') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:types_extra_specs:index"]) - def test_list_volume_types_extra_specs(self): - with self.override_role(): - self.volume_types_client.list_volume_types_extra_specs( - self.vol_type['id'])['extra_specs'] - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:types_extra_specs:create"]) - @decorators.idempotent_id('eea40251-990b-49b0-99ae-10e4585b479b') - def test_create_volume_type_extra_specs(self): - with self.override_role(): - self._create_volume_type_extra_specs(ignore_not_found=True) - - @decorators.idempotent_id('e2dcc9c6-2fef-431d-afaf-92b45bc76d1a') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:types_extra_specs:show"]) - def test_show_volume_type_extra_specs(self): - self._create_volume_type_extra_specs() - - with self.override_role(): - self.volume_types_client.show_volume_type_extra_specs( - self.vol_type['id'], self.spec_key) - - @decorators.idempotent_id('93001912-f938-41c7-8787-62dc7010fd52') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:types_extra_specs:delete"]) - def test_delete_volume_type_extra_specs(self): - self._create_volume_type_extra_specs(ignore_not_found=True) - - with self.override_role(): - self.volume_types_client.delete_volume_type_extra_specs( - self.vol_type['id'], self.spec_key) - - @decorators.idempotent_id('0a444437-7402-4fbe-a18a-93af2ee00618') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:types_extra_specs:update"]) - def test_update_volume_type_extra_specs(self): - self._create_volume_type_extra_specs() - update_extra_specs = {self.spec_key: "val2"} - - with self.override_role(): - self.volume_types_client.update_volume_type_extra_specs( - self.vol_type['id'], self.spec_key, update_extra_specs) diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_types_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_types_rbac.py deleted file mode 100644 index 46d2d558..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volume_types_rbac.py +++ /dev/null @@ -1,62 +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 import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - -if CONF.policy_feature_enabled.changed_cinder_policies_xena: - _TYPE_MANAGE_CREATE = "volume_extension:type_create" - _TYPE_MANAGE_UPDATE = "volume_extension:type_update" - _TYPE_MANAGE_DELETE = "volume_extension:type_delete" -else: - _TYPE_MANAGE_CREATE = "volume_extension:types_manage" - _TYPE_MANAGE_UPDATE = "volume_extension:types_manage" - _TYPE_MANAGE_DELETE = "volume_extension:types_manage" - - -class VolumeTypesRbacTest(rbac_base.BaseVolumeRbacTest): - - @decorators.idempotent_id('e2bbf968-d947-4a15-a4da-a98c3069731e') - @rbac_rule_validation.action( - service="cinder", - rules=[_TYPE_MANAGE_CREATE]) - def test_create_volume_type(self): - with self.override_role(): - self.create_volume_type() - - @decorators.idempotent_id('2b74ac82-e03e-4801-86f3-d05c9acfd66b') - @rbac_rule_validation.action( - service="cinder", - rules=[_TYPE_MANAGE_UPDATE]) - def test_update_volume_type(self): - volume_type = self.create_volume_type() - with self.override_role(): - self.volume_types_client.update_volume_type( - volume_type['id'], description='updated-description') - - @decorators.idempotent_id('90aec0ef-4f9b-4170-be6b-a392c12540be') - @rbac_rule_validation.action( - service="cinder", - rules=[_TYPE_MANAGE_DELETE]) - def test_delete_volume_type(self): - volume_type = self.create_volume_type() - with self.override_role(): - self.volume_types_client.delete_volume_type(volume_type['id']) - self.volume_types_client.wait_for_resource_deletion(volume_type['id']) diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py deleted file mode 100644 index 073b26ce..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py +++ /dev/null @@ -1,256 +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 oslo_serialization import base64 -from oslo_serialization import jsonutils as json - -from tempest.common import waiters -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class VolumesBackupsV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(VolumesBackupsV3RbacTest, cls).skip_checks() - if not CONF.volume_feature_enabled.backup: - raise cls.skipException("Cinder backup feature disabled") - - @classmethod - def resource_setup(cls): - super(VolumesBackupsV3RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - cls.backup = cls._create_backup(volume_id=cls.volume['id']) - - def _decode_url(self, backup_url): - return json.loads(base64.decode_as_text(backup_url)) - - def _encode_backup(self, backup): - retval = json.dumps(backup) - return base64.encode_as_text(retval) - - def _modify_backup_url(self, backup_url, changes): - backup = self._decode_url(backup_url) - backup.update(changes) - return self._encode_backup(backup) - - @decorators.attr(type='slow') - @rbac_rule_validation.action(service="cinder", - rules=["backup:create"]) - @decorators.idempotent_id('6887ec94-0bcf-4ab7-b30f-3808a4b5a2a5') - def test_create_backup(self): - backup_name = data_utils.rand_name(self.__class__.__name__ + '-Backup') - - with self.override_role(): - backup = self.backups_client.create_backup( - volume_id=self.volume['id'], name=backup_name)['backup'] - self.addCleanup(self.backups_client.delete_backup, backup['id']) - waiters.wait_for_volume_resource_status( - self.backups_client, backup['id'], 'available') - waiters.wait_for_volume_resource_status(self.volumes_client, - self.volume['id'], 'available') - - @decorators.attr(type='slow') - @rbac_rule_validation.action(service="cinder", - rules=["backup:get"]) - @decorators.idempotent_id('abd92bdd-b0fb-4dc4-9cfc-de9e968f8c8a') - def test_show_backup(self): - with self.override_role(): - self.backups_client.show_backup(self.backup['id']) - - @rbac_rule_validation.action(service="cinder", - rules=["backup:get_all"]) - @decorators.idempotent_id('4d18f0f0-7e01-4007-b622-dedc859b22f6') - def test_list_backups(self): - with self.override_role(): - self.backups_client.list_backups() - - @decorators.idempotent_id('dbd69865-876f-4835-b70e-7341153fb162') - @rbac_rule_validation.action(service="cinder", - rules=["backup:get_all"]) - def test_list_backups_with_details(self): - with self.override_role(): - self.backups_client.list_backups(detail=True) - - @decorators.attr(type='slow') - @decorators.idempotent_id('50f43bde-205e-438e-9a05-5eac07fc3d63') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:backup_admin_actions:reset_status"]) - def test_reset_backup_status(self): - # Use instance-level create_backup for easier debugging. - backup = self.create_backup(volume_id=self.volume['id']) - waiters.wait_for_volume_resource_status(self.volumes_client, - self.volume['id'], 'available') - with self.override_role(): - self.backups_client.reset_backup_status(backup_id=backup['id'], - status='error') - waiters.wait_for_volume_resource_status(self.backups_client, - backup['id'], 'error') - - @decorators.attr(type='slow') - @rbac_rule_validation.action(service="cinder", - rules=["backup:restore"]) - @decorators.idempotent_id('9c794bf9-2446-4f41-8fe0-80b71e757f9d') - def test_restore_backup(self): - with self.override_role(): - restore = self.backups_client.restore_backup( - self.backup['id'])['restore'] - self.addCleanup(self.volumes_client.delete_volume, - restore['volume_id']) - waiters.wait_for_volume_resource_status( - self.backups_client, restore['backup_id'], 'available') - - @decorators.attr(type='slow') - @rbac_rule_validation.action(service="cinder", - rules=["backup:delete"]) - @decorators.idempotent_id('d5d0c6a2-413d-437e-a73f-4bf2b41a20ed') - def test_delete_backup(self): - # Do not call the create_backup in Tempest's base volume class, because - # it doesn't use ``test_utils.call_and_ignore_notfound_exc`` for clean - # up. - backup = self.backups_client.create_backup( - volume_id=self.volume['id'])['backup'] - self.addCleanup(test_utils.call_and_ignore_notfound_exc, - self.backups_client.delete_backup, backup['id']) - waiters.wait_for_volume_resource_status(self.backups_client, - backup['id'], 'available') - waiters.wait_for_volume_resource_status(self.volumes_client, - self.volume['id'], 'available') - - with self.override_role(): - self.backups_client.delete_backup(backup['id']) - # Wait for deletion so error isn't thrown during clean up. - self.backups_client.wait_for_resource_deletion(backup['id']) - - @decorators.attr(type='slow') - @rbac_rule_validation.action(service="cinder", - rules=["backup:export-import"]) - @decorators.idempotent_id('e984ec8d-e8eb-485c-98bc-f1856020303c') - def test_export_backup(self): - with self.override_role(): - self.backups_client.export_backup(self.backup['id'])[ - 'backup-record'] - - @decorators.attr(type='slow') - @rbac_rule_validation.action(service="cinder", - rules=["backup:backup-import"]) - @decorators.idempotent_id('1e70f039-4556-44cc-9cc1-edf2b7ed648b') - def test_import_backup(self): - export_backup = self.backups_client.export_backup( - self.backup['id'])['backup-record'] - new_id = data_utils.rand_uuid() - new_url = self._modify_backup_url( - export_backup['backup_url'], {'id': new_id}) - - with self.override_role(): - import_backup = self.backups_client.import_backup( - backup_service=export_backup['backup_service'], - backup_url=new_url)['backup'] - self.addCleanup(self.backups_client.delete_backup, import_backup['id']) - waiters.wait_for_volume_resource_status(self.backups_client, - import_backup['id'], - 'available') - - -class VolumesBackupsV318RbacTest(rbac_base.BaseVolumeRbacTest): - """Validates that the ``GET /backups/{backup_id}`` and - ``GET /backups/details`` APIs inject the expected attribute - 'os-backup-project-attr:project_id' into the response body following - successful authorization. - """ - _api_version = 3 - # The minimum microversion for showing 'os-backup-project-attr:project_id' - # is 3.18. - volume_min_microversion = '3.18' - volume_max_microversion = 'latest' - - @classmethod - def skip_checks(cls): - super(VolumesBackupsV318RbacTest, cls).skip_checks() - if not CONF.volume_feature_enabled.backup: - raise cls.skipException("Cinder backup feature disabled") - - @classmethod - def resource_setup(cls): - super(VolumesBackupsV318RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - cls.backup = cls._create_backup(volume_id=cls.volume['id']) - cls.expected_attr = 'os-backup-project-attr:project_id' - - @decorators.idempotent_id('69801485-d5be-4e75-bbb4-168d50b5a8c2') - @rbac_rule_validation.action(service="cinder", - rules=["backup:backup_project_attribute"]) - def test_show_backup_project_attribute(self): - with self.override_role(): - body = self.backups_client.show_backup(self.backup['id'])['backup'] - - # Show backup API attempts to inject the attribute below into the - # response body but only if policy enforcement succeeds. - if self.expected_attr not in body: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=self.expected_attr) - - @decorators.idempotent_id('aa40b7c0-5974-48be-8cbc-e23cc61c4c68') - @rbac_rule_validation.action(service="cinder", - rules=["backup:backup_project_attribute"]) - def test_list_backup_details_project_attribute(self): - with self.override_role(): - body = self.backups_client.list_backups(detail=True)['backups'] - - if self.expected_attr not in body[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=self.expected_attr) - - -class VolumesBackupsV39RbacTest(rbac_base.BaseVolumeRbacTest): - _api_version = 3 - volume_min_microversion = '3.9' - volume_max_microversion = 'latest' - - @classmethod - def skip_checks(cls): - super(VolumesBackupsV39RbacTest, cls).skip_checks() - if not CONF.volume_feature_enabled.backup: - raise cls.skipException("Cinder backup feature disabled") - - @classmethod - def resource_setup(cls): - super(VolumesBackupsV39RbacTest, cls).resource_setup() - cls.volume = cls.create_volume() - cls.backup = cls._create_backup(volume_id=cls.volume['id']) - - @decorators.attr(type='slow') - @decorators.idempotent_id('b45b0e98-6eb8-4c62-aa53-0f8c7c09faa6') - @rbac_rule_validation.action( - service="cinder", - rules=["backup:update"]) - def test_backup_update(self): - update_kwargs = { - 'name': data_utils.rand_name(self.__class__.__name__ + '-Backup'), - 'description': data_utils.rand_name("volume-backup-description") - } - with self.override_role(): - self.backups_client.update_backup(self.backup['id'], - **update_kwargs) diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py deleted file mode 100644 index c7c52d23..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py +++ /dev/null @@ -1,40 +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.common import waiters -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - - -class VolumesExtendV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def resource_setup(cls): - super(VolumesExtendV3RbacTest, cls).resource_setup() - # Create a test shared volume for tests - cls.volume = cls.create_volume() - - @rbac_rule_validation.action(service="cinder", rules=["volume:extend"]) - @decorators.idempotent_id('1627b065-4081-4e14-8340-8e4fb02ceaf2') - def test_volume_extend(self): - # Extend volume test - extend_size = int(self.volume['size']) + 1 - with self.override_role(): - self.volumes_client.extend_volume(self.volume['id'], - new_size=extend_size) - waiters.wait_for_volume_resource_status( - self.volumes_client, self.volume['id'], 'available') diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_manage_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_manage_rbac.py deleted file mode 100644 index 480ebeb3..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volumes_manage_rbac.py +++ /dev/null @@ -1,124 +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.common import waiters -from tempest import config -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators -from tempest.lib import exceptions - -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class VolumesManageV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(VolumesManageV3RbacTest, cls).skip_checks() - - if not CONF.volume_feature_enabled.manage_volume: - raise cls.skipException("Manage volume tests are disabled") - - if len(CONF.volume.manage_volume_ref) != 2: - raise cls.skipException("Manage volume ref is not correctly " - "configured") - - @classmethod - def setup_clients(cls): - super(VolumesManageV3RbacTest, cls).setup_clients() - cls.volume_manage_client = cls.os_primary.volume_manage_client_latest - - def _manage_volume(self, org_volume): - # Manage volume - new_volume_name = data_utils.rand_name( - self.__class__.__name__ + '-volume') - - new_volume_ref = { - 'name': new_volume_name, - 'host': org_volume['os-vol-host-attr:host'], - 'ref': {CONF.volume.manage_volume_ref[0]: - CONF.volume.manage_volume_ref[1] % org_volume['id']}, - 'volume_type': org_volume['volume_type'], - 'availability_zone': org_volume['availability_zone']} - - new_volume_id = self.volume_manage_client.manage_volume( - **new_volume_ref)['volume']['id'] - - waiters.wait_for_volume_resource_status(self.volumes_client, - new_volume_id, 'available') - self.addCleanup(self.delete_volume, - self.volumes_client, new_volume_id) - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_manage"]) - @decorators.idempotent_id('114f9708-939b-407e-aeac-d21ebfabaad3') - def test_volume_manage(self): - volume_id = self.create_volume()['id'] - volume = self.volumes_client.show_volume(volume_id)['volume'] - - # By default, the volume is managed after creation. We need to - # unmanage the volume first before testing manage volume. - self.volumes_client.unmanage_volume(volume['id']) - self.volumes_client.wait_for_resource_deletion(volume['id']) - - new_volume_name = data_utils.rand_name( - self.__class__.__name__ + '-volume') - - new_volume_ref = { - 'name': new_volume_name, - 'host': volume['os-vol-host-attr:host'], - 'ref': {CONF.volume.manage_volume_ref[0]: - CONF.volume.manage_volume_ref[1] % volume['id']}, - 'volume_type': volume['volume_type'], - 'availability_zone': volume['availability_zone']} - - with self.override_role(): - try: - new_volume_id = self.volume_manage_client.manage_volume( - **new_volume_ref)['volume']['id'] - except exceptions.Forbidden as e: - # Since the test role under test does not have permission to - # manage the volume, Forbidden exception is thrown and the - # manageable list will not be cleaned up. Therefore, we need to - # re-manage the volume at the end of the test case for proper - # resource clean up. - self.addCleanup(self._manage_volume, volume) - raise exceptions.Forbidden(e) - - waiters.wait_for_volume_resource_status(self.volumes_client, - new_volume_id, 'available') - self.addCleanup( - self.delete_volume, self.volumes_client, new_volume_id) - - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:volume_unmanage"]) - @decorators.idempotent_id('d5d72abe-60bc-45ac-a8f2-c21b24f0b5d6') - def test_volume_unmanage(self): - volume_id = self.create_volume()['id'] - volume = self.volumes_client.show_volume(volume_id)['volume'] - - with self.override_role(): - self.volumes_client.unmanage_volume(volume['id']) - self.volumes_client.wait_for_resource_deletion(volume['id']) - - # In order to clean up the manageable list, we need to re-manage the - # volume after the test. The _manage_volume method will set up the - # proper resource cleanup - self.addCleanup(self._manage_volume, volume) diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_snapshots_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_snapshots_rbac.py deleted file mode 100644 index f56a4e1f..00000000 --- a/patrole_tempest_plugin/tests/api/volume/test_volumes_snapshots_rbac.py +++ /dev/null @@ -1,140 +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.common import waiters -from tempest import config -from tempest.lib import decorators - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation -from patrole_tempest_plugin.tests.api.volume import rbac_base - -CONF = config.CONF - - -class VolumesSnapshotV3RbacTest(rbac_base.BaseVolumeRbacTest): - - @classmethod - def skip_checks(cls): - super(VolumesSnapshotV3RbacTest, cls).skip_checks() - if not CONF.volume_feature_enabled.snapshot: - raise cls.skipException("Cinder volume snapshots are disabled") - - @classmethod - def resource_setup(cls): - super(VolumesSnapshotV3RbacTest, cls).resource_setup() - # Create a test shared volume for tests - cls.volume = cls.create_volume() - # Create a test shared snapshot for tests - cls.snapshot = cls.create_snapshot(cls.volume['id']) - - def _list_by_param_values(self, with_detail=False, **params): - # Perform list or list_details action with given params. - return self.snapshots_client.list_snapshots( - detail=with_detail, **params)['snapshots'] - - @rbac_rule_validation.action(service="cinder", - rules=["volume:create_snapshot"]) - @decorators.idempotent_id('ac7b2ee5-fbc0-4360-afc2-de8fa4881ede') - def test_create_snapshot(self): - # Create a temp snapshot - with self.override_role(): - self.create_snapshot(self.volume['id']) - - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_snapshot"]) - @decorators.idempotent_id('93a11b40-1ba8-44d6-a196-f8d97220f796') - def test_show_snapshot(self): - # Get the snapshot - with self.override_role(): - self.snapshots_client.show_snapshot( - self.snapshot['id'])['snapshot'] - - @decorators.idempotent_id('5d6f5f21-9293-4f2a-8f44-cabdc24d92cb') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:extended_snapshot_attributes"]) - def test_show_snapshot_with_extended_attributes(self): - """List snapshots with extended attributes.""" - expected_attrs = ('os-extended-snapshot-attributes:project_id', - 'os-extended-snapshot-attributes:progress') - - with self.override_role(): - resp = self.snapshots_client.show_snapshot( - self.snapshot['id'])['snapshot'] - for expected_attr in expected_attrs: - if expected_attr not in resp: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) - - @rbac_rule_validation.action(service="cinder", - rules=["volume:update_snapshot"]) - @decorators.idempotent_id('53fe8ee3-3bea-4ae8-a979-3c98ea72f620') - def test_update_snapshot(self): - new_desc = 'This is the new description of snapshot.' - params = {'description': new_desc} - # Updates snapshot with new values - with self.override_role(): - self.snapshots_client.update_snapshot( - self.snapshot['id'], **params)['snapshot'] - waiters.wait_for_volume_resource_status( - self.snapshots_client, self.snapshot['id'], 'available') - - @rbac_rule_validation.action(service="cinder", - rules=["volume:delete_snapshot"]) - @decorators.idempotent_id('c7fe54ec-3b70-4772-ba11-f166d95888a3') - def test_delete_snapshot(self): - # Create a temp snapshot - temp_snapshot = self.create_snapshot(self.volume['id']) - with self.override_role(): - # Delete the snapshot - self.snapshots_client.delete_snapshot(temp_snapshot['id']) - self.snapshots_client.wait_for_resource_deletion( - temp_snapshot['id']) - - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_all_snapshots"]) - @decorators.idempotent_id('e4edf0c0-2cd3-420f-b8ab-4d98a0718608') - def test_list_snapshots(self): - """List snapshots with params.""" - params = {'name': self.snapshot['name']} - with self.override_role(): - self._list_by_param_values(**params) - - @decorators.idempotent_id('f3155d8e-45ee-45c9-910d-18c0242229e1') - @rbac_rule_validation.action(service="cinder", - rules=["volume:get_all_snapshots"]) - def test_list_snapshots_details(self): - """List snapshots details with params.""" - params = {'name': self.snapshot['name']} - with self.override_role(): - self._list_by_param_values(with_detail=True, **params) - - @decorators.idempotent_id('dd37f388-2731-446d-a78f-676997ebb04a') - @rbac_rule_validation.action( - service="cinder", - rules=["volume_extension:extended_snapshot_attributes"]) - def test_list_snapshots_details_with_extended_attributes(self): - """List snapshots details with extended attributes.""" - expected_attrs = ('os-extended-snapshot-attributes:project_id', - 'os-extended-snapshot-attributes:progress') - params = {'name': self.snapshot['name']} - - with self.override_role(): - resp = self._list_by_param_values(with_detail=True, **params) - for expected_attr in expected_attrs: - if expected_attr not in resp[0]: - raise rbac_exceptions.RbacMissingAttributeResponseBody( - attribute=expected_attr) diff --git a/patrole_tempest_plugin/tests/scenario/__init__.py b/patrole_tempest_plugin/tests/scenario/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/unit/__init__.py b/patrole_tempest_plugin/tests/unit/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/patrole_tempest_plugin/tests/unit/base.py b/patrole_tempest_plugin/tests/unit/base.py deleted file mode 100644 index c08da430..00000000 --- a/patrole_tempest_plugin/tests/unit/base.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2010-2011 OpenStack Foundation -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# Copyright 2017 AT&T Corporation. -# -# 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.tests import base - -from patrole_tempest_plugin.tests.unit import fixtures as patrole_fixtures - - -class TestCase(base.TestCase): - """Test case base class for all unit tests.""" - - def setUp(self): - super(TestCase, self).setUp() - # Disable patrole log for unit tests. - self.useFixture( - patrole_fixtures.ConfPatcher(enable_reporting=False, - group='patrole_log')) diff --git a/patrole_tempest_plugin/tests/unit/fixtures.py b/patrole_tempest_plugin/tests/unit/fixtures.py deleted file mode 100644 index 01b99db3..00000000 --- a/patrole_tempest_plugin/tests/unit/fixtures.py +++ /dev/null @@ -1,158 +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. - -"""Fixtures for Patrole tests.""" -from unittest import mock - -import fixtures -import time - -from tempest import config -from tempest import test - -from patrole_tempest_plugin import rbac_utils - - -CONF = config.CONF - - -class ConfPatcher(fixtures.Fixture): - """Fixture to patch and restore global CONF. Adopted from Nova. - - This also resets overrides for everything that is patched during - its teardown. - """ - - def __init__(self, **kwargs): - """Constructor - - :params group: if specified all config options apply to that group. - :params **kwargs: the rest of the kwargs are processed as a - set of key/value pairs to be set as configuration override. - """ - super(ConfPatcher, self).__init__() - self.group = kwargs.pop('group', None) - self.args = kwargs - - def setUp(self): - super(ConfPatcher, self).setUp() - for k, v in self.args.items(): - self.addCleanup(CONF.clear_override, k, self.group) - CONF.set_override(k, v, self.group) - - -class FakeBaseRbacTest(rbac_utils.RbacUtilsMixin, test.BaseTestCase): - credentials = [] - os_primary = None - - def runTest(self): - pass - - -class RbacUtilsMixinFixture(fixtures.Fixture): - """Fixture for `RbacUtils` class.""" - - USER_ID = mock.sentinel.user_id - PROJECT_ID = mock.sentinel.project_id - - def __init__(self, do_reset_mocks=True, rbac_test_roles=None): - self._do_reset_mocks = do_reset_mocks - self._rbac_test_roles = rbac_test_roles or ['member'] - - def patchobject(self, target, attribute, *args, **kwargs): - p = mock.patch.object(target, attribute, *args, **kwargs) - m = p.start() - self.addCleanup(p.stop) - return m - - def setUp(self): - super(RbacUtilsMixinFixture, self).setUp() - - self.useFixture(ConfPatcher(rbac_test_roles=self._rbac_test_roles, - group='patrole')) - self.useFixture(ConfPatcher( - admin_role='admin', auth_version='v3', group='identity')) - self.useFixture(ConfPatcher( - api_v3=True, group='identity-feature-enabled')) - - # Mock out functionality that can't be used by unit tests. Mocking out - # time.sleep is a test optimization. - self.mock_time = self.patchobject(rbac_utils, 'time', - __name__='mock_time', spec=time) - - test_obj_kwargs = { - 'credentials.user_id': self.USER_ID, - 'credentials.tenant_id': self.PROJECT_ID, - 'credentials.project_id': self.PROJECT_ID, - } - - class FakeRbacTest(FakeBaseRbacTest): - os_primary = mock.Mock() - os_admin = mock.Mock() - - FakeRbacTest.os_primary.configure_mock(**test_obj_kwargs) - - self.admin_roles_client = FakeRbacTest.os_admin.roles_v3_client - self.admin_roles_client.list_all_role_inference_rules.return_value = { - "role_inferences": [ - { - "implies": [{"id": "reader_id", "name": "reader"}], - "prior_role": {"id": "member_id", "name": "member"} - }, - { - "implies": [{"id": "member_id", "name": "member"}], - "prior_role": {"id": "admin_id", "name": "admin"} - } - ] - } - - default_roles = {'admin', 'member', 'reader'}.union( - set(self._rbac_test_roles)) - self.set_roles(list(default_roles), []) - - FakeRbacTest.setUpClass() - self.test_obj = FakeRbacTest() - if self._do_reset_mocks: - self.admin_roles_client.reset_mock() - self.test_obj.os_primary.reset_mock() - self.test_obj.os_admin.reset_mock() - self.mock_time.reset_mock() - - def set_roles(self, roles, roles_on_project=None): - """Set the list of available roles in the system. - - :param roles: List of roles returned by ``list_roles``. - :param roles_on_project: List of roles returned by - ``list_user_roles_on_project``. - :returns: None. - """ - if not roles_on_project: - roles_on_project = [] - if not isinstance(roles, list): - roles = [roles] - if not isinstance(roles_on_project, list): - roles_on_project = [roles_on_project] - - available_roles = { - 'roles': [{'name': role, 'id': '%s_id' % role} for role in roles] - } - available_project_roles = { - 'roles': [{'name': role, 'id': '%s_id' % role} - for role in roles_on_project] - } - - self.admin_roles_client.list_roles.return_value = available_roles - self.admin_roles_client.list_user_roles_on_project.return_value = ( - available_project_roles) diff --git a/patrole_tempest_plugin/tests/unit/resources/admin_rbac_policy.json b/patrole_tempest_plugin/tests/unit/resources/admin_rbac_policy.json deleted file mode 100644 index d6d9605c..00000000 --- a/patrole_tempest_plugin/tests/unit/resources/admin_rbac_policy.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "admin_rule": "role:admin", - "is_admin_rule": "is_admin:True", - "alt_admin_rule": "is_admin:True or (role:admin and is_project_admin:True)", - "member_rule": "role:member", - "reader_rule": "role:reader" -} diff --git a/patrole_tempest_plugin/tests/unit/resources/alt_admin_rbac_policy.json b/patrole_tempest_plugin/tests/unit/resources/alt_admin_rbac_policy.json deleted file mode 100644 index bf07182c..00000000 --- a/patrole_tempest_plugin/tests/unit/resources/alt_admin_rbac_policy.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "context_is_admin": "role:super_admin", - "admin_rule": "role:super_admin", - "non_admin_rule": "role:fake_admin" -} diff --git a/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.json b/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.json deleted file mode 100644 index d9591680..00000000 --- a/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "even_rule": "role:two or role:four or role:six or role:eight", - "odd_rule": "role:one or role:three or role:five or role:seven or role:nine", - "zero_rule": "role:zero", - "prime_rule": "role:one or role:two or role:three or role:five or role:seven", - "all_rule": "", - - "policy_action_1": "rule:even_rule", - "policy_action_2": "rule:odd_rule", - "policy_action_3": "rule:zero_rule", - "policy_action_4": "rule:prime_rule", - "policy_action_5": "rule:all_rule", - "policy_action_6": "role:eight" -} diff --git a/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.yaml b/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.yaml deleted file mode 100644 index 444bd2e1..00000000 --- a/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -even_rule: role:two or role:four or role:six or role:eight -odd_rule: role:one or role:three or role:five or role:seven or role:nine -zero_rule: role:zero -prime_rule: role:one or role:two or role:three or role:five or role:seven -all_rule: '' - -policy_action_1: rule:even_rule -policy_action_2: rule:odd_rule -policy_action_3: rule:zero_rule -policy_action_4: rule:prime_rule -policy_action_5: rule:all_rule -policy_action_6: role:eight diff --git a/patrole_tempest_plugin/tests/unit/resources/rbac_roles.yaml b/patrole_tempest_plugin/tests/unit/resources/rbac_roles.yaml deleted file mode 100644 index 357e0e6b..00000000 --- a/patrole_tempest_plugin/tests/unit/resources/rbac_roles.yaml +++ /dev/null @@ -1,10 +0,0 @@ -Test: - test:create: - - test_member - - _member_ - test:create2: - - test_member - test:create3: - - test_member, _member_ - test:create4: - - test_member, !_member_ \ No newline at end of file diff --git a/patrole_tempest_plugin/tests/unit/resources/tenant_rbac_policy.json b/patrole_tempest_plugin/tests/unit/resources/tenant_rbac_policy.json deleted file mode 100644 index ea65c880..00000000 --- a/patrole_tempest_plugin/tests/unit/resources/tenant_rbac_policy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "rule1": "tenant_id:%(network:tenant_id)s", - "rule2": "tenant_id:%(tenant_id)s", - "rule3": "project_id:%(project_id)s", - "rule4": "user_id:%(user_id)s", - "admin_tenant_rule": "role:admin and tenant_id:%(tenant_id)s", - "admin_user_rule": "role:admin and user_id:%(user_id)s" -} \ No newline at end of file diff --git a/patrole_tempest_plugin/tests/unit/test_hacking.py b/patrole_tempest_plugin/tests/unit/test_hacking.py deleted file mode 100644 index edfaa7eb..00000000 --- a/patrole_tempest_plugin/tests/unit/test_hacking.py +++ /dev/null @@ -1,302 +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.tests import base - -from patrole_tempest_plugin.hacking import checks - - -class RBACHackingTestCase(base.TestCase): - - def test_import_no_clients_in_api_tests(self): - for client in checks.PYTHON_CLIENTS: - import_string = "import " + client + "client" - self.assertTrue(checks.import_no_clients_in_api_tests( - import_string, - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertFalse(checks.import_no_clients_in_api_tests( - import_string, - "./patrole_tempest_plugin/tests/scenario/fake_test.py")) - self.assertFalse(checks.import_no_clients_in_api_tests( - import_string, - "./patrole_tempest_plugin/tests/unit/fake_test.py")) - self.assertFalse(checks.import_no_clients_in_api_tests( - import_string, - "./patrole_tempest_plugin/fake_test.py")) - - def test_no_setup_teardown_class_for_tests(self): - self.assertTrue(checks.no_setup_teardown_class_for_tests( - " def setUpClass(cls):", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertIsNone(checks.no_setup_teardown_class_for_tests( - " def setUpClass(cls): # noqa", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertTrue(checks.no_setup_teardown_class_for_tests( - " def setUpClass(cls):", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertTrue(checks.no_setup_teardown_class_for_tests( - " def setUpClass(cls):", - "./patrole_tempest_plugin/tests/scenario/fake_test.py")) - self.assertTrue(checks.no_setup_teardown_class_for_tests( - " def tearDownClass(cls):", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertIsNone(checks.no_setup_teardown_class_for_tests( - " def tearDownClass(cls): # noqa", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertTrue(checks.no_setup_teardown_class_for_tests( - " def tearDownClass(cls):", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertTrue(checks.no_setup_teardown_class_for_tests( - " def tearDownClass(cls):", - "./patrole_tempest_plugin/tests/scenario/fake_test.py")) - - def test_service_tags_not_in_module_path(self): - self.assertTrue(checks.service_tags_not_in_module_path( - "@utils.services('volume')", - "./patrole_tempest_plugin/tests/api/volume/fake_test_rbac.py")) - self.assertFalse(checks.service_tags_not_in_module_path( - "@utils.services('image')", - "./patrole_tempest_plugin/tests/api/volume/fake_test_rbac.py")) - - def test_no_hyphen_at_end_of_rand_name(self): - self.assertIsNone(checks.no_hyphen_at_end_of_rand_name( - "data_utils.rand_name('test')", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertIsNone(checks.no_hyphen_at_end_of_rand_name( - "data_utils.rand_name('test')", - "./patrole_tempest_plugin/tests/api/compute/fake_test_rbac.py")) - self.assertIsNone(checks.no_hyphen_at_end_of_rand_name( - "data_utils.rand_name('test')", - "./patrole_tempest_plugin/tests/scenario/fake_test.py")) - self.assertIsNone(checks.no_hyphen_at_end_of_rand_name( - "data_utils.rand_name('test')", - "./patrole_tempest_plugin/tests/unit/fake_test.py")) - self.assertTrue(checks.no_hyphen_at_end_of_rand_name( - "data_utils.rand_name('test-')", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertTrue(checks.no_hyphen_at_end_of_rand_name( - "data_utils.rand_name('test-')", - "./patrole_tempest_plugin/tests/api/compute/fake_test_rbac.py")) - self.assertTrue(checks.no_hyphen_at_end_of_rand_name( - "data_utils.rand_name('test-')", - "./patrole_tempest_plugin/tests/scenario/fake_test.py")) - self.assertTrue(checks.no_hyphen_at_end_of_rand_name( - "data_utils.rand_name('test-')", - "./patrole_tempest_plugin/tests/unit/fake_test.py")) - - def test_no_mutable_default_args(self): - self.assertEqual(0, len(list(checks.no_mutable_default_args( - " def test_function(test_param_1, test_param_2")))) - self.assertEqual(1, len(list(checks.no_mutable_default_args( - " def test_function(test_param_1, test_param_2={}")))) - - def test_no_testtools_skip_decorator(self): - self.assertEqual(1, len(list(checks.no_testtools_skip_decorator( - " @testtools.skip('Bug')")))) - self.assertEqual(0, len(list(checks.no_testtools_skip_decorator( - " @testtools.skipTest('reason')")))) - self.assertEqual(0, len(list(checks.no_testtools_skip_decorator( - " @testtools.skipUnless(reason, 'message')")))) - self.assertEqual(0, len(list(checks.no_testtools_skip_decorator( - " @testtools.skipIf(reason, 'message')")))) - - def test_use_rand_uuid_instead_of_uuid4(self): - self.assertTrue(checks.use_rand_uuid_instead_of_uuid4( - "new_uuid = uuid.uuid4()", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertTrue(checks.use_rand_uuid_instead_of_uuid4( - "new_hex_uuid = uuid.uuid4().hex", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertIsNotNone(checks.use_rand_uuid_instead_of_uuid4( - "new_uuid = data_utils.rand_uuid()", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertIsNotNone(checks.use_rand_uuid_instead_of_uuid4( - "new_hex_uuid = data_utils.rand_uuid_hex()", - "./patrole_tempest_plugin/tests/fake_test.py")) - - def _test_no_rbac_rule_validation_decorator( - self, filename, with_other_decorators=True, - with_rbac_decorator=True, expected_success=True): - other_decorators = [ - "@decorators.idempotent_id(123)", - "@decorators.attr(type=['slow'])", - "@utils.requires_ext(extension='ext', service='svc')" - ] - - if with_other_decorators: - # Include multiple decorators to verify that this check works with - # arbitrarily many decorators. These insert decorators above the - # rbac_rule_validation decorator. - for decorator in other_decorators: - self.assertIsNone(checks.no_rbac_rule_validation_decorator( - " %s" % decorator, filename)) - if with_rbac_decorator: - self.assertIsNone(checks.no_rbac_rule_validation_decorator( - " @rbac_rule_validation.action('rule')", - filename)) - if with_other_decorators: - # Include multiple decorators to verify that this check works with - # arbitrarily many decorators. These insert decorators between - # the test and the @rbac_rule_validation decorator. - for decorator in other_decorators: - self.assertIsNone(checks.no_rbac_rule_validation_decorator( - " %s" % decorator, filename)) - final_result = checks.no_rbac_rule_validation_decorator( - " def test_rbac_test", - filename) - if expected_success: - self.assertIsNone(final_result) - else: - self.assertIsInstance(final_result, tuple) - self.assertFalse(final_result[0]) - - def test_no_rbac_rule_validation_decorator(self): - self._test_no_rbac_rule_validation_decorator( - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py") - self._test_no_rbac_rule_validation_decorator( - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py", - False) - self._test_no_rbac_rule_validation_decorator( - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py", - with_other_decorators=True, with_rbac_decorator=False, - expected_success=False) - self._test_no_rbac_rule_validation_decorator( - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py", - with_other_decorators=False, with_rbac_decorator=False, - expected_success=False) - - self._test_no_rbac_rule_validation_decorator( - "./patrole_tempest_plugin/tests/scenario/fake_test.py") - self._test_no_rbac_rule_validation_decorator( - "./patrole_tempest_plugin/tests/scenario/fake_test.py", - False) - self._test_no_rbac_rule_validation_decorator( - "./patrole_tempest_plugin/tests/scenario/fake_test.py", - with_other_decorators=True, with_rbac_decorator=False, - expected_success=False) - self._test_no_rbac_rule_validation_decorator( - "./patrole_tempest_plugin/tests/scenario/fake_test.py", - with_other_decorators=False, with_rbac_decorator=False, - expected_success=False) - - def test_no_rbac_suffix_in_test_filename(self): - self.assertFalse(checks.no_rbac_suffix_in_test_filename( - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertFalse(checks.no_rbac_suffix_in_test_filename( - "./patrole_tempest_plugin/tests/scenario/fake_test.py")) - self.assertFalse(checks.no_rbac_suffix_in_test_filename( - "./patrole_tempest_plugin/tests/unit/fake_test.py")) - self.assertFalse(checks.no_rbac_suffix_in_test_filename( - "./patrole_tempest_plugin/tests/api/fake_rbac_base.py")) - self.assertFalse(checks.no_rbac_suffix_in_test_filename( - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertTrue(checks.no_rbac_suffix_in_test_filename( - "./patrole_tempest_plugin/tests/api/fake_test.py")) - - def test_no_rbac_test_suffix_in_test_class_name(self): - self.assertFalse(checks.no_rbac_test_suffix_in_test_class_name( - "class FakeTest", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertFalse(checks.no_rbac_test_suffix_in_test_class_name( - "class FakeTest", - "./patrole_tempest_plugin/tests/scenario/fake_test.py")) - self.assertFalse(checks.no_rbac_test_suffix_in_test_class_name( - "class FakeTest", - "./patrole_tempest_plugin/tests/unit/fake_test.py")) - self.assertFalse(checks.no_rbac_test_suffix_in_test_class_name( - "class FakeTest", - "./patrole_tempest_plugin/tests/api/fake_rbac_base.py")) - self.assertFalse(checks.no_rbac_test_suffix_in_test_class_name( - "class FakeRbacTest", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertTrue(checks.no_rbac_test_suffix_in_test_class_name( - "class FakeTest", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - - def test_no_client_alias_in_test_cases(self): - self.assertFalse(checks.no_client_alias_in_test_cases( - " self.client", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertFalse(checks.no_client_alias_in_test_cases( - " cls.client", - "./patrole_tempest_plugin/tests/fake_test.py")) - self.assertFalse(checks.no_client_alias_in_test_cases( - " self.client", - "./patrole_tempest_plugin/tests/unit/fake_test.py")) - self.assertFalse(checks.no_client_alias_in_test_cases( - " cls.client", - "./patrole_tempest_plugin/tests/unit/fake_test.py")) - self.assertFalse(checks.no_client_alias_in_test_cases( - " self.client", - "./patrole_tempest_plugin/tests/scenario/fake_test.py")) - self.assertFalse(checks.no_client_alias_in_test_cases( - " cls.client", - "./patrole_tempest_plugin/tests/scenario/fake_test.py")) - self.assertTrue(checks.no_client_alias_in_test_cases( - " self.client", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertTrue(checks.no_client_alias_in_test_cases( - " cls.client", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - - def no_extension_rbac_test_suffix_in_plugin_test_class_name(self): - check = checks.no_extension_rbac_test_suffix_in_plugin_test_class_name - - # Passing cases: these do not inherit from "ExtRbacTest" base class. - self.assertFalse(check( - "class FakeRbacTest(BaseFakeRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertFalse(check( - "class FakeRbacTest(base.BaseFakeRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - - # Passing cases: these **do** end in correct test class suffix. - self.assertFalse(check( - "class FakeExtRbacTest(BaseFakeExtRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertFalse(check( - "class FakeExtRbacTest(base.BaseFakeExtRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - - # Passing cases: plugin base class inherits from another base class. - self.assertFalse(check( - "class BaseFakeExtRbacTest(base.BaseFakeRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertFalse(check( - "class BaseFakeExtRbacTest(BaseFakeRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - - # Failing cases: these **do not** end in correct test class suffix. - # Case 1: RbacTest subclass doesn't end in ExtRbacTest. - self.assertTrue(check( - "class FakeRbacTest(base.BaseFakeExtRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertTrue(check( - "class FakeRbacTest(BaseFakeExtRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertTrue(check( - "class FakeRbacTest(BaseFakeNetworkExtRbacTest)", - "./patrole_tempest_plugin/tests/api/network/fake_test_rbac.py")) - # Case 2: ExtRbacTest subclass doesn't inherit from - # BaseExtRbacTest. - self.assertTrue(check( - "class FakeExtRbacTest(base.BaseFakeRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertTrue(check( - "class FakeExtRbacTest(BaseFakeRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) - self.assertTrue(check( - "class FakeNeutronExtRbacTest(BaseFakeNeutronRbacTest)", - "./patrole_tempest_plugin/tests/api/fake_test_rbac.py")) diff --git a/patrole_tempest_plugin/tests/unit/test_policy_authority.py b/patrole_tempest_plugin/tests/unit/test_policy_authority.py deleted file mode 100644 index fc7cafb7..00000000 --- a/patrole_tempest_plugin/tests/unit/test_policy_authority.py +++ /dev/null @@ -1,639 +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. - -import os -from unittest import mock - -from tempest import config - -from patrole_tempest_plugin import policy_authority -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin.tests.unit import base -from patrole_tempest_plugin.tests.unit import fixtures - -CONF = config.CONF - - -class PolicyAuthorityTest(base.TestCase): - - services = { - 'services': [ - {'name': 'custom_rbac_policy'}, - {'name': 'admin_rbac_policy'}, - {'name': 'alt_admin_rbac_policy'}, - {'name': 'tenant_rbac_policy'}, - {'name': 'test_service'} - ] - } - - def setUp(self): - super(PolicyAuthorityTest, self).setUp() - - mock_admin = self.patchobject(policy_authority.PolicyAuthority, - 'os_admin') - mock_admin.identity_services_client.list_services.\ - return_value = self.services - mock_admin.identity_services_v3_client.list_services.\ - return_value = self.services - - current_directory = os.path.dirname(os.path.realpath(__file__)) - self.custom_policy_file = os.path.join(current_directory, - 'resources', - 'custom_rbac_policy.json') - self.admin_policy_file = os.path.join(current_directory, - 'resources', - 'admin_rbac_policy.json') - self.alt_admin_policy_file = os.path.join(current_directory, - 'resources', - 'alt_admin_rbac_policy.json') - self.tenant_policy_file = os.path.join(current_directory, - 'resources', - 'tenant_rbac_policy.json') - self.conf_policy_path_json = os.path.join( - current_directory, 'resources', '%s.json') - - self.conf_policy_path_yaml = os.path.join( - current_directory, 'resources', '%s.yaml') - - self.useFixture(fixtures.ConfPatcher( - custom_policy_files=[self.conf_policy_path_json], group='patrole')) - self.useFixture(fixtures.ConfPatcher( - api_v3=True, api_v2=False, group='identity-feature-enabled')) - - # Guarantee a blank slate for each test. - for attr in ('available_services', 'policy_files'): - if attr in dir(policy_authority.PolicyAuthority): - delattr(policy_authority.PolicyAuthority, attr) - - self.test_obj = self.useFixture(fixtures.RbacUtilsMixinFixture()).\ - test_obj - - @staticmethod - def _get_fake_policies(rules): - fake_rules = [] - rules = policy_authority.policy.Rules.from_dict(rules) - for name, check in rules.items(): - fake_rule = mock.Mock(check=check, __name__='foo') - fake_rule.name = name - fake_rule.deprecated_rule = False - fake_rules.append(fake_rule) - return fake_rules - - def _test_policy_file(self, roles, allowed_rules, - disallowed_rules, authority=None, service=None): - if authority is None: - self.assertIsNotNone(service) - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - authority = policy_authority.PolicyAuthority( - test_tenant_id, test_user_id, service) - - roles = self.test_obj.get_all_needed_roles(roles) - - for rule in allowed_rules: - allowed = authority.allowed(rule, roles) - self.assertTrue(allowed) - - for rule in disallowed_rules: - allowed = authority.allowed(rule, roles) - self.assertFalse(allowed) - - return authority - - @mock.patch.object(policy_authority, 'LOG', autospec=True) - def _test_custom_policy(self, *args): - default_roles = ['zero', 'one', 'two', 'three', 'four', - 'five', 'six', 'seven', 'eight', 'nine'] - - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - authority = policy_authority.PolicyAuthority( - test_tenant_id, test_user_id, "custom_rbac_policy") - - expected = { - 'policy_action_1': ['two', 'four', 'six', 'eight'], - 'policy_action_2': ['one', 'three', 'five', 'seven', 'nine'], - 'policy_action_3': ['zero'], - 'policy_action_4': ['one', 'two', 'three', 'five', 'seven'], - 'policy_action_5': ['zero', 'one', 'two', 'three', 'four', 'five', - 'six', 'seven', 'eight', 'nine'], - 'policy_action_6': ['eight'], - } - - for rule, role_list in expected.items(): - for role in role_list: - self.assertTrue(authority.allowed(rule, [role])) - for role in set(default_roles) - set(role_list): - self.assertFalse(authority.allowed(rule, [role])) - - @mock.patch.object(policy_authority, 'LOG', autospec=True) - def _test_custom_multi_roles_policy(self, *args): - default_roles = ['zero', 'one', 'two', 'three', 'four', - 'five', 'six', 'seven', 'eight', 'nine'] - - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - authority = policy_authority.PolicyAuthority( - test_tenant_id, test_user_id, "custom_rbac_policy") - - expected = { - 'policy_action_1': ['two', 'four', 'six', 'eight'], - 'policy_action_2': ['one', 'three', 'five', 'seven', 'nine'], - 'policy_action_4': ['one', 'two', 'three', 'five', 'seven'], - 'policy_action_5': ['zero', 'one', 'two', 'three', 'four', 'five', - 'six', 'seven', 'eight', 'nine'], - } - - for rule, role_list in expected.items(): - allowed_roles_lists = [roles for roles in [ - role_list[len(role_list) // 2:], - role_list[:len(role_list) // 2]] if roles] - for test_roles in allowed_roles_lists: - self.assertTrue(authority.allowed(rule, test_roles)) - - disallowed_roles = list(set(default_roles) - set(role_list)) - disallowed_roles_lists = [roles for roles in [ - disallowed_roles[len(disallowed_roles) // 2:], - disallowed_roles[:len(disallowed_roles) // 2]] if roles] - for test_roles in disallowed_roles_lists: - self.assertFalse(authority.allowed(rule, test_roles)) - - def test_empty_rbac_test_roles(self): - self._test_policy_file( - roles=[], - allowed_rules=['policy_action_5'], - disallowed_rules=['policy_action_1', 'policy_action_2', - 'policy_action_3', 'policy_action_4', - 'policy_action_6'], - service="custom_rbac_policy" - ) - - def test_custom_policy_json(self): - # The CONF.patrole.custom_policy_files has a path to JSON file by - # default, so we don't need to use ConfPatcher here. - self._test_custom_policy() - - def test_custom_policy_yaml(self): - self.useFixture(fixtures.ConfPatcher( - custom_policy_files=[self.conf_policy_path_yaml], group='patrole')) - self._test_custom_policy() - - def test_custom_multi_roles_policy_json(self): - # The CONF.patrole.custom_policy_files has a path to JSON file by - # default, so we don't need to use ConfPatcher here. - self._test_custom_multi_roles_policy() - - def test_custom_multi_roles_policy_yaml(self): - self.useFixture(fixtures.ConfPatcher( - custom_policy_files=[self.conf_policy_path_yaml], group='patrole')) - self._test_custom_multi_roles_policy() - - def test_admin_policy_file_with_admin_role(self): - # admin role implies member and reader roles - self._test_policy_file( - roles=['admin'], - allowed_rules=['admin_rule', 'is_admin_rule', 'alt_admin_rule', - 'member_rule', 'reader_rule'], - disallowed_rules=[], - service="admin_rbac_policy" - ) - - def test_admin_policy_file_with_member_role(self): - # member role implies reader role - self._test_policy_file( - roles=['member'], - allowed_rules=['member_rule', 'reader_rule'], - disallowed_rules=['admin_rule', 'is_admin_rule', 'alt_admin_rule'], - service="admin_rbac_policy" - ) - - def test_admin_policy_file_with_reader_role(self): - self._test_policy_file( - roles=['reader'], - allowed_rules=['reader_rule'], - disallowed_rules=['admin_rule', 'is_admin_rule', 'alt_admin_rule', - 'member_rule'], - service="admin_rbac_policy" - ) - - def test_alt_admin_policy_file_with_context_is_admin(self): - authority = self._test_policy_file( - roles=['fake_admin'], - allowed_rules=['non_admin_rule'], - disallowed_rules=['admin_rule'], - service="alt_admin_rbac_policy" - ) - - self._test_policy_file( - roles=['super_admin'], - allowed_rules=['admin_rule'], - disallowed_rules=['non_admin_rule'], - authority=authority - ) - - def test_tenant_user_policy(self): - """Test whether rules with format tenant_id/user_id formatting work. - - Test whether Neutron rules that contain project_id, tenant_id, and - network:tenant_id pass. And test whether Nova rules that contain - user_id pass. - """ - allowed_rules = ['rule1', 'rule2', 'rule3', 'rule4'] - disallowed_rules = ['admin_tenant_rule', 'admin_user_rule'] - - # Check whether Member role can perform expected actions. - authority = self._test_policy_file( - roles=['member'], - allowed_rules=allowed_rules, - disallowed_rules=disallowed_rules, - service="tenant_rbac_policy", - ) - - # Check whether admin role can perform expected actions. - allowed_rules.extend(disallowed_rules) - self._test_policy_file( - roles=['admin'], - allowed_rules=allowed_rules, - disallowed_rules=[], - authority=authority - ) - - # Check whether _try_rule is called with the correct target dictionary. - with mock.patch.object( - authority, '_try_rule', return_value=True, autospec=True) \ - as mock_try_rule: - - expected_target = { - "project_id": mock.sentinel.tenant_id, - "tenant_id": mock.sentinel.tenant_id, - "network:tenant_id": mock.sentinel.tenant_id, - "user_id": mock.sentinel.user_id - } - - expected_access_data = { - "roles": sorted(['member', 'reader']), - "is_admin": False, - "is_admin_project": True, - "user_id": mock.sentinel.user_id, - "tenant_id": mock.sentinel.tenant_id, - "project_id": mock.sentinel.tenant_id - } - - for rule in allowed_rules: - allowed = authority.allowed( - rule, self.test_obj.get_all_needed_roles(['member'])) - self.assertTrue(allowed) - # for sure that roles are in same order - mock_try_rule.call_args[0][2]["roles"] = sorted( - mock_try_rule.call_args[0][2]["roles"]) - mock_try_rule.assert_called_once_with( - rule, expected_target, expected_access_data, mock.ANY) - mock_try_rule.reset_mock() - - @mock.patch.object(policy_authority, 'LOG', autospec=True) - def test_invalid_service_raises_exception(self, m_log): - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - service = 'invalid_service' - - self.assertRaises(rbac_exceptions.RbacInvalidServiceException, - policy_authority.PolicyAuthority, - test_tenant_id, - test_user_id, - service) - - m_log.debug.assert_called_once_with( - '%s is NOT a valid service.', service) - - @mock.patch.object(policy_authority, 'LOG', autospec=True) - def test_service_is_none_raises_exception(self, m_log): - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - service = None - - self.assertRaises(rbac_exceptions.RbacInvalidServiceException, - policy_authority.PolicyAuthority, - test_tenant_id, - test_user_id, - service) - - m_log.debug.assert_called_once_with('%s is NOT a valid service.', None) - - @mock.patch.object(policy_authority, 'LOG', autospec=True) - def test_invalid_policy_rule_throws_rbac_parsing_exception(self, m_log): - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - authority = policy_authority.PolicyAuthority( - test_tenant_id, test_user_id, "custom_rbac_policy") - - fake_rule = 'fake_rule' - expected_message = ( - 'Policy action "{0}" not found in policy files: {1} or among ' - 'registered policy in code defaults for {2} service.').format( - fake_rule, [self.custom_policy_file], "custom_rbac_policy") - - e = self.assertRaises(rbac_exceptions.RbacParsingException, - authority.allowed, fake_rule, [None]) - self.assertIn(expected_message, str(e)) - m_log.debug.assert_called_once_with(expected_message) - - @mock.patch.object(policy_authority, 'LOG', autospec=True) - def test_unknown_exception_throws_rbac_parsing_exception(self, m_log): - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - - authority = policy_authority.PolicyAuthority( - test_tenant_id, test_user_id, "custom_rbac_policy") - authority.rules = mock.MagicMock( - __name__='foo', - **{'__getitem__.return_value.side_effect': Exception( - mock.sentinel.error)}) - - expected_message = ( - 'Policy action "[{0}]" not found in policy files: {1} or among ' - 'registered policy in code defaults for {2} service.').format( - mock.sentinel.rule, [self.custom_policy_file], - "custom_rbac_policy") - - e = self.assertRaises(rbac_exceptions.RbacParsingException, - authority.allowed, [mock.sentinel.rule], [None]) - self.assertIn(expected_message, str(e)) - m_log.debug.assert_called_once_with(expected_message) - - @mock.patch.object(policy_authority, 'stevedore', autospec=True) - def test_get_rules_from_file_and_from_code(self, mock_stevedore): - fake_policy_rules = self._get_fake_policies({ - 'code_policy_action_1': 'rule:code_rule_1', - 'code_policy_action_2': 'rule:code_rule_2', - 'code_policy_action_3': 'rule:code_rule_3', - }) - - mock_manager = mock.Mock(obj=fake_policy_rules, __name__='foo') - mock_manager.configure_mock(name='tenant_rbac_policy') - mock_stevedore.named.NamedExtensionManager.return_value = [ - mock_manager - ] - - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - authority = policy_authority.PolicyAuthority( - test_tenant_id, test_user_id, "tenant_rbac_policy") - - rules = authority.get_rules() - self.assertIsInstance(rules, policy_authority.policy.Rules) - - actual_policy_data = {k: str(v) for k, v in rules.items()} - expected_policy_data = { - "code_policy_action_1": "rule:code_rule_1", - "code_policy_action_2": "rule:code_rule_2", - "code_policy_action_3": "rule:code_rule_3", - "rule1": "tenant_id:%(network:tenant_id)s", - "rule2": "tenant_id:%(tenant_id)s", - "rule3": "project_id:%(project_id)s", - "rule4": "user_id:%(user_id)s", - "admin_tenant_rule": "(role:admin and tenant_id:%(tenant_id)s)", - "admin_user_rule": "(role:admin and user_id:%(user_id)s)" - } - - self.assertEqual(expected_policy_data, actual_policy_data) - - @mock.patch.object(policy_authority, 'stevedore', autospec=True) - def test_get_rules_from_file_and_from_code_with_overwrite( - self, mock_stevedore): - # The custom policy file should overwrite default rules rule1 and rule2 - # that are defined in code. - fake_policy_rules = self._get_fake_policies({ - 'rule1': 'rule:code_rule_1', - 'rule2': 'rule:code_rule_2', - 'code_policy_action_3': 'rule:code_rule_3', - }) - - mock_manager = mock.Mock(obj=fake_policy_rules, __name__='foo') - mock_manager.configure_mock(name='tenant_rbac_policy') - mock_stevedore.named.NamedExtensionManager.return_value = [ - mock_manager - ] - - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - - authority = policy_authority.PolicyAuthority( - test_tenant_id, test_user_id, 'tenant_rbac_policy') - rules = authority.get_rules() - self.assertIsInstance(rules, policy_authority.policy.Rules) - - actual_policy_data = {k: str(v) for k, v in rules.items()} - expected_policy_data = { - "code_policy_action_3": "rule:code_rule_3", - "rule1": "tenant_id:%(network:tenant_id)s", - "rule2": "tenant_id:%(tenant_id)s", - "rule3": "project_id:%(project_id)s", - "rule4": "user_id:%(user_id)s", - "admin_tenant_rule": "(role:admin and tenant_id:%(tenant_id)s)", - "admin_user_rule": "(role:admin and user_id:%(user_id)s)" - } - - self.assertEqual(expected_policy_data, actual_policy_data) - - @mock.patch.object(policy_authority, 'stevedore', autospec=True) - def test_get_rules_cannot_find_policy(self, mock_stevedore): - mock_stevedore.named.NamedExtensionManager.return_value = None - e = self.assertRaises(rbac_exceptions.RbacParsingException, - policy_authority.PolicyAuthority, - None, None, 'test_service') - - expected_error = ( - 'Policy files for {0} service were not found among the registered ' - 'in-code policies or in any of the possible policy files: {1}.' - .format('test_service', - [CONF.patrole.custom_policy_files[0] % 'test_service'])) - self.assertIn(expected_error, str(e)) - - @mock.patch.object(policy_authority.policy, 'parse_file_contents', - autospec=True) - @mock.patch.object(policy_authority, 'stevedore', autospec=True) - def test_get_rules_without_valid_policy(self, mock_stevedore, - mock_parse_file_contents): - mock_stevedore.named.NamedExtensionManager.return_value = None - mock_parse_file_contents.side_effect = ValueError - e = self.assertRaises(rbac_exceptions.RbacParsingException, - policy_authority.PolicyAuthority, - None, None, 'tenant_rbac_policy') - - expected_error = ( - 'Policy files for {0} service were not found among the registered ' - 'in-code policies or in any of the possible policy files:' - .format('tenant_rbac_policy')) - self.assertIn(expected_error, str(e)) - - def test_discover_policy_files(self): - policy_parser = policy_authority.PolicyAuthority( - None, None, 'tenant_rbac_policy') - - # Ensure that "policy_files" is set at class and instance levels. - self.assertIn('policy_files', - dir(policy_authority.PolicyAuthority)) - self.assertIn('policy_files', dir(policy_parser)) - self.assertIn('tenant_rbac_policy', policy_parser.policy_files) - self.assertEqual([self.conf_policy_path_json % 'tenant_rbac_policy'], - policy_parser.policy_files['tenant_rbac_policy']) - - @mock.patch.object(policy_authority, 'policy', autospec=True) - @mock.patch.object(policy_authority.PolicyAuthority, 'get_rules', - autospec=True) - @mock.patch.object(policy_authority.PolicyAuthority, 'os_admin', - autospec=True) - @mock.patch.object(policy_authority, 'os', autospec=True) - @mock.patch.object(policy_authority, 'glob', autospec=True) - def test_discover_policy_files_with_many_invalid_one_valid(self, m_glob, - m_os, m_admin, - *args): - service = 'test_service' - custom_policy_files = ['foo/%s', 'bar/%s', 'baz/%s'] - m_glob.iglob.side_effect = [iter([path % service]) - for path in custom_policy_files] - # Only the 3rd path is valid. - m_os.path.isfile.side_effect = [False, False, True] - - # Ensure the outer for loop runs only once in `discover_policy_files`. - m_admin.identity_services_v3_client.\ - list_services.return_value = { - 'services': [{'name': service}]} - - # The expected policy will be 'baz/test_service'. - self.useFixture(fixtures.ConfPatcher( - custom_policy_files=custom_policy_files, - group='patrole')) - - policy_parser = policy_authority.PolicyAuthority( - None, None, service) - - # Ensure that "policy_files" is set at class and instance levels. - self.assertTrue(hasattr(policy_authority.PolicyAuthority, - 'policy_files')) - self.assertTrue(hasattr(policy_parser, 'policy_files')) - self.assertEqual(['baz/%s' % service], - policy_parser.policy_files[service]) - - def test_discover_policy_files_with_no_valid_files(self): - expected_error = ( - 'Policy files for {0} service were not found among the registered ' - 'in-code policies or in any of the possible policy files: {1}.' - .format('test_service', - [self.conf_policy_path_json % 'test_service'])) - - e = self.assertRaises(rbac_exceptions.RbacParsingException, - policy_authority.PolicyAuthority, - None, None, 'test_service') - self.assertIn(expected_error, str(e)) - - self.assertTrue(hasattr(policy_authority.PolicyAuthority, - 'policy_files')) - self.assertEqual( - [], - policy_authority.PolicyAuthority.policy_files['test_service']) - - def _test_validate_service(self, v2_services, v3_services, - expected_failure=False, expected_services=None): - with mock.patch.object(policy_authority.PolicyAuthority, 'os_admin', - autospec=True) as m_admin: - m_admin.identity_services_client.list_services.\ - return_value = v2_services - m_admin.identity_services_v3_client.list_services.\ - return_value = v3_services - - test_tenant_id = mock.sentinel.tenant_id - test_user_id = mock.sentinel.user_id - - mock_os = self.patchobject(policy_authority, 'os') - mock_os.path.join.return_value = self.admin_policy_file - - if not expected_services: - expected_services = [s['name'] for s in self.services['services']] - - # Guarantee a blank slate for this test. - if hasattr(policy_authority.PolicyAuthority, 'available_services'): - delattr(policy_authority.PolicyAuthority, - 'available_services') - - if expected_failure: - policy_parser = None - - expected_exception = 'invalid_service is NOT a valid service' - with self.assertRaisesRegex( - rbac_exceptions.RbacInvalidServiceException, - expected_exception): - policy_authority.PolicyAuthority( - test_tenant_id, test_user_id, "INVALID_SERVICE") - else: - policy_parser = policy_authority.PolicyAuthority( - test_tenant_id, test_user_id, "tenant_rbac_policy") - - # Check that the attribute is available at object and class levels. - # If initialization failed, only check at class level. - if policy_parser: - self.assertTrue(hasattr(policy_parser, 'available_services')) - self.assertEqual(expected_services, - policy_parser.available_services) - self.assertTrue(hasattr(policy_authority.PolicyAuthority, - 'available_services')) - self.assertEqual( - expected_services, - policy_authority.PolicyAuthority.available_services) - - def test_validate_service(self): - """Positive test case to ensure ``validate_service`` works. - - There are 3 possibilities: - 1) Identity v3 API enabled. - 2) Identity v2 API enabled. - 3) Both are enabled. - """ - self.useFixture(fixtures.ConfPatcher( - api_v2=True, api_v3=False, group='identity-feature-enabled')) - self._test_validate_service(self.services, [], False) - - self.useFixture(fixtures.ConfPatcher( - api_v2=False, api_v3=True, group='identity-feature-enabled')) - self._test_validate_service([], self.services, False) - - self.useFixture(fixtures.ConfPatcher( - api_v2=True, api_v3=True, group='identity-feature-enabled')) - self._test_validate_service(self.services, self.services, False) - - def test_validate_service_except_invalid_service(self): - """Negative test case to ensure ``validate_service`` works. - - There are 4 possibilities: - 1) Identity v3 API enabled. - 2) Identity v2 API enabled. - 3) Both are enabled. - 4) Neither are enabled. - """ - self.useFixture(fixtures.ConfPatcher( - api_v2=True, api_v3=False, group='identity-feature-enabled')) - self._test_validate_service(self.services, [], True) - - self.useFixture(fixtures.ConfPatcher( - api_v2=False, api_v3=True, group='identity-feature-enabled')) - self._test_validate_service([], self.services, True) - - self.useFixture(fixtures.ConfPatcher( - api_v2=True, api_v3=True, group='identity-feature-enabled')) - self._test_validate_service(self.services, self.services, True) - - self.useFixture(fixtures.ConfPatcher( - api_v2=False, api_v3=False, group='identity-feature-enabled')) - self._test_validate_service([], [], True, []) diff --git a/patrole_tempest_plugin/tests/unit/test_rbac_rule_validation.py b/patrole_tempest_plugin/tests/unit/test_rbac_rule_validation.py deleted file mode 100644 index 471bcdc4..00000000 --- a/patrole_tempest_plugin/tests/unit/test_rbac_rule_validation.py +++ /dev/null @@ -1,1089 +0,0 @@ -# Copyright 2017 AT&T Inc. -# -# 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 unittest import mock - -import fixtures -import functools -from oslo_config import cfg -from tempest.lib import exceptions - -from patrole_tempest_plugin import rbac_exceptions -from patrole_tempest_plugin import rbac_rule_validation as rbac_rv -from patrole_tempest_plugin.tests.unit import base -from patrole_tempest_plugin.tests.unit import fixtures as patrole_fixtures - -CONF = cfg.CONF - - -class BaseRBACRuleValidationTest(base.TestCase): - - test_roles = ['member'] - - def setUp(self): - super(BaseRBACRuleValidationTest, self).setUp() - self.rbac_utils_fixture = self.useFixture( - patrole_fixtures.RbacUtilsMixinFixture( - rbac_test_roles=self.test_roles)) - self.test_obj = self.rbac_utils_fixture.test_obj - - -class BaseRBACMultiRoleRuleValidationTest(BaseRBACRuleValidationTest): - - test_roles = ['member', 'anotherrole'] - - -class RBACRuleValidationTest(BaseRBACRuleValidationTest): - """Test suite for validating fundamental functionality for the - ``rbac_rule_validation`` decorator. - """ - - def setUp(self): - super(RBACRuleValidationTest, self).setUp() - # This behavior is tested in separate test class below. - self.useFixture(fixtures.MockPatchObject( - rbac_rv, '_validate_override_role_called')) - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_have_permission_no_exc(self, mock_authority, - mock_log): - """Test that having permission and no exception thrown is success. - - Positive test case success scenario. - """ - mock_authority.PolicyAuthority.return_value.allowed.return_value = True - - @rbac_rv.action(mock.sentinel.service, rules=[mock.sentinel.action]) - def test_policy(*args): - pass - - test_policy(self.test_obj) - mock_log.error.assert_not_called() - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_lack_permission_throw_exc(self, mock_authority, - mock_log): - """Test that having no permission and exception thrown is success. - - Negative test case success scenario. - """ - mock_authority.PolicyAuthority.return_value.allowed.return_value =\ - False - - @rbac_rv.action(mock.sentinel.service, rules=[mock.sentinel.action]) - def test_policy(*args): - raise exceptions.Forbidden() - - test_policy(self.test_obj) - mock_log.error.assert_not_called() - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_forbidden_negative(self, mock_authority, - mock_log): - """Test RbacUnderPermissionException error is thrown and have - permission fails. - - Negative test case: if Forbidden is thrown and the user should be - allowed to perform the action, then the RbacUnderPermissionException - exception should be raised. - """ - mock_authority.PolicyAuthority.return_value.allowed.return_value = True - - @rbac_rv.action(mock.sentinel.service, rules=[mock.sentinel.action]) - def test_policy(*args): - raise exceptions.Forbidden() - - test_re = (r"User with roles \['member'\] was not allowed to perform " - r"the following actions: \[%s\].*" % (mock.sentinel.action)) - self.assertRaisesRegex( - rbac_exceptions.RbacUnderPermissionException, test_re, test_policy, - self.test_obj) - self.assertRegex(mock_log.error.mock_calls[0][1][0], test_re) - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_rbac_failed_response_body_positive( - self, mock_authority, mock_log): - """Test BasePatroleResponseBodyException error is thrown without - permission passes. - - Positive test case: if subclass of BasePatroleResponseBodyException is - thrown and the user is not allowed to perform the action, then this is - a success. - """ - mock_authority.PolicyAuthority.return_value.allowed.return_value =\ - False - - def _do_test(exception_cls, **kwargs): - @rbac_rv.action(mock.sentinel.service, - rules=[mock.sentinel.action]) - def test_policy(*args): - raise exception_cls(**kwargs) - - mock_log.error.assert_not_called() - mock_log.warning.assert_not_called() - - _do_test(rbac_exceptions.RbacMissingAttributeResponseBody, - attribute=mock.sentinel.attr) - _do_test(rbac_exceptions.RbacPartialResponseBody, - body=mock.sentinel.body) - _do_test(rbac_exceptions.RbacEmptyResponseBody) - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_soft_authorization_exceptions( - self, mock_authority, mock_log): - """Test RbacUnderPermissionException error is thrown when any of the - soft authorization-related exceptions are raised by a test. - - Negative test case: if subclass of BasePatroleResponseBodyException is - thrown and the user is allowed to perform the action, then this is an - expected failure. - """ - mock_authority.PolicyAuthority.return_value.allowed.return_value = True - - def _do_test(exception_cls, **kwargs): - @rbac_rv.action(mock.sentinel.service, - rules=[mock.sentinel.action]) - def test_policy(*args): - raise exception_cls(**kwargs) - - test_re = (r".*User with roles \[%s\] was not allowed to " - r"perform the following actions: \[%s\].*" % ( - ', '.join("'%s'" % r for r in self.test_roles), - mock.sentinel.action)) - self.assertRaisesRegex( - rbac_exceptions.RbacUnderPermissionException, test_re, - test_policy, self.test_obj) - self.assertRegex(mock_log.error.mock_calls[0][1][0], test_re) - - _do_test(rbac_exceptions.RbacMissingAttributeResponseBody, - attribute=mock.sentinel.attr) - _do_test(rbac_exceptions.RbacPartialResponseBody, - body=mock.sentinel.body) - _do_test(rbac_exceptions.RbacEmptyResponseBody) - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_expect_not_found_but_raises_forbidden(self, mock_authority, - mock_log): - """Test that expecting 404 but getting 403 works for all scenarios. - - Tests the following scenarios: - 1) Test no permission and 404 is expected but 403 is thrown throws - exception. - 2) Test have permission and 404 is expected but 403 is thrown throws - exception. - """ - @rbac_rv.action(mock.sentinel.service, rules=[mock.sentinel.action], - expected_error_codes=[404]) - def test_policy(*args): - raise exceptions.Forbidden('Test message') - - error_re = r'Expected .* to be raised but .* was raised instead' - - for allowed in [True, False]: - mock_authority.PolicyAuthority.return_value.allowed.\ - return_value = allowed - self.assertRaisesRegex( - rbac_exceptions.RbacExpectedWrongException, error_re, - test_policy, self.test_obj) - self.assertTrue(mock_log.error.called) - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_expect_not_found_and_raise_not_found(self, mock_authority, - mock_log): - """Test that expecting 404 and getting 404 works for all scenarios. - - Tests the following scenarios: - 1) Test no permission and 404 is expected and 404 is thrown succeeds. - 2) Test have permission and 404 is expected and 404 is thrown fails. - - In both cases, a LOG.warning is called with the "irregular message" - that signals to user that a 404 was expected and caught. - """ - policy_names = ['foo:bar'] - - @rbac_rv.action(mock.sentinel.service, rules=policy_names, - expected_error_codes=[404]) - def test_policy(*args): - raise exceptions.NotFound() - - expected_errors = [ - (r"User with roles \['member'\] was not allowed to perform the " - r"following actions: \['%s'\].*" % policy_names[0]), - None - ] - - for pos, allowed in enumerate([True, False]): - mock_authority.PolicyAuthority.return_value.allowed\ - .return_value = allowed - - error_re = expected_errors[pos] - - if error_re: - self.assertRaisesRegex( - rbac_exceptions.RbacUnderPermissionException, error_re, - test_policy, self.test_obj) - self.assertRegex(mock_log.error.mock_calls[0][1][0], error_re) - else: - test_policy(self.test_obj) - mock_log.error.assert_not_called() - - mock_log.warning.assert_called_with( - "NotFound exception was caught for test %s. Expected policies " - "which may have caused the error: %s. The service %s throws a " - "404 instead of a 403, which is irregular", - test_policy.__name__, - ', '.join(policy_names), - mock.sentinel.service) - - mock_log.warning.reset_mock() - mock_log.error.reset_mock() - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_overpermission_negative(self, mock_authority, - mock_log): - """Test that RbacOverPermissionException is correctly handled. - - Tests that case where no exception is thrown but the Patrole framework - says that the role should not be allowed to perform the policy action. - """ - mock_authority.PolicyAuthority.return_value.allowed.return_value =\ - False - - @rbac_rv.action(mock.sentinel.service, rules=[mock.sentinel.action]) - def test_policy_expect_forbidden(*args): - pass - - @rbac_rv.action(mock.sentinel.service, rules=[mock.sentinel.action], - expected_error_codes=[404]) - def test_policy_expect_not_found(*args): - pass - - for test_policy in ( - test_policy_expect_forbidden, test_policy_expect_not_found): - - error_re = r".*OverPermission: .* \[%s\]$" % mock.sentinel.action - self.assertRaisesRegex(rbac_exceptions.RbacOverPermissionException, - error_re, test_policy, self.test_obj) - self.assertRegex(mock_log.error.mock_calls[0][1][0], error_re) - mock_log.error.reset_mock() - - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_invalid_policy_rule_raises_parsing_exception( - self, mock_authority): - """Test that invalid policy action causes test to raise an exception. - """ - mock_authority.PolicyAuthority.return_value.allowed.\ - side_effect = rbac_exceptions.RbacParsingException - - @rbac_rv.action(mock.sentinel.service, mock.sentinel.action) - def test_policy(*args): - pass - - error_re = 'Attempted to test an invalid policy file or action' - self.assertRaisesRegex(rbac_exceptions.RbacParsingException, error_re, - test_policy, self.test_obj) - - mock_authority.PolicyAuthority.assert_called_once_with( - mock.sentinel.project_id, mock.sentinel.user_id, - mock.sentinel.service, extra_target_data={}) - - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_get_exception_type_404(self, _): - """Test that getting a 404 exception type returns NotFound.""" - expected_exception = exceptions.NotFound - expected_irregular_msg = ( - "NotFound exception was caught for test %s. Expected policies " - "which may have caused the error: %s. The service %s throws a " - "404 instead of a 403, which is irregular") - - actual_exception, actual_irregular_msg = \ - rbac_rv._get_exception_type(404) - - self.assertEqual(expected_exception, actual_exception) - self.assertEqual(expected_irregular_msg, actual_irregular_msg) - - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_get_exception_type_403(self, _): - """Test that getting a 403 exception type returns Forbidden.""" - expected_exception = exceptions.Forbidden - expected_irregular_msg = None - - actual_exception, actual_irregular_msg = \ - rbac_rv._get_exception_type(403) - - self.assertEqual(expected_exception, actual_exception) - self.assertEqual(expected_irregular_msg, actual_irregular_msg) - - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - def test_exception_thrown_when_type_is_not_int(self, mock_log, _): - """Test that non-integer exception type raises error.""" - self.assertRaises(rbac_exceptions.RbacInvalidErrorCode, - rbac_rv._get_exception_type, "403") - - mock_log.error.assert_called_once_with("Please pass an expected error " - "code. Currently supported " - "codes: [403, 404]") - - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - def test_exception_thrown_when_type_is_403_or_404(self, mock_log, _): - """Test that unsupported exceptions throw error.""" - invalid_exceptions = [200, 400, 500] - for exc in invalid_exceptions: - self.assertRaises(rbac_exceptions.RbacInvalidErrorCode, - rbac_rv._get_exception_type, exc) - mock_log.error.assert_called_once_with( - "Please pass an expected error code. Currently supported " - "codes: [403, 404]") - - mock_log.error.reset_mock() - - -class RBACMultiRoleRuleValidationTest(BaseRBACMultiRoleRuleValidationTest, - RBACRuleValidationTest): - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_forbidden_negative(self, mock_authority, - mock_log): - """Test RbacUnderPermissionException error is thrown and have - permission fails. - - Negative test case: if Forbidden is thrown and the user should be - allowed to perform the action, then the RbacUnderPermissionException - exception should be raised. - """ - mock_authority.PolicyAuthority.return_value.allowed.return_value = True - - @rbac_rv.action(mock.sentinel.service, rules=[mock.sentinel.action]) - def test_policy(*args): - raise exceptions.Forbidden() - - test_re = (r"User with roles \['member', 'anotherrole'\] was not " - r"allowed to perform the following actions: \[%s\].*" % - (mock.sentinel.action)) - self.assertRaisesRegex( - rbac_exceptions.RbacUnderPermissionException, test_re, test_policy, - self.test_obj) - self.assertRegex(mock_log.error.mock_calls[0][1][0], test_re) - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_expect_not_found_and_raise_not_found(self, mock_authority, - mock_log): - """Test that expecting 404 and getting 404 works for all scenarios. - - Tests the following scenarios: - 1) Test no permission and 404 is expected and 404 is thrown succeeds. - 2) Test have permission and 404 is expected and 404 is thrown fails. - - In both cases, a LOG.warning is called with the "irregular message" - that signals to user that a 404 was expected and caught. - """ - policy_names = ['foo:bar'] - - @rbac_rv.action(mock.sentinel.service, rules=policy_names, - expected_error_codes=[404]) - def test_policy(*args): - raise exceptions.NotFound() - - expected_errors = [ - (r"User with roles \['member', 'anotherrole'\] was not allowed to " - r"perform the following actions: \['%s'\].*" % policy_names[0]), - None - ] - - for pos, allowed in enumerate([True, False]): - mock_authority.PolicyAuthority.return_value.allowed\ - .return_value = allowed - - error_re = expected_errors[pos] - - if error_re: - self.assertRaisesRegex( - rbac_exceptions.RbacUnderPermissionException, error_re, - test_policy, self.test_obj) - self.assertRegex(mock_log.error.mock_calls[0][1][0], error_re) - else: - test_policy(self.test_obj) - mock_log.error.assert_not_called() - - mock_log.warning.assert_called_with( - "NotFound exception was caught for test %s. Expected policies " - "which may have caused the error: %s. The service %s throws a " - "404 instead of a 403, which is irregular", - test_policy.__name__, - ', '.join(policy_names), - mock.sentinel.service) - - mock_log.warning.reset_mock() - mock_log.error.reset_mock() - - -class RBACRuleValidationLoggingTest(BaseRBACRuleValidationTest): - """Test class for validating the RBAC log, dedicated to just logging - Patrole RBAC validation work flows. - """ - - def setUp(self): - super(RBACRuleValidationLoggingTest, self).setUp() - # This behavior is tested in separate test class below. - self.useFixture(fixtures.MockPatchObject( - rbac_rv, '_validate_override_role_called')) - - @mock.patch.object(rbac_rv, 'RBACLOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rbac_report_logging_disabled(self, mock_authority, mock_rbaclog): - """Test case to ensure that we DON'T write logs when enable_reporting - is False - """ - self.useFixture( - patrole_fixtures.ConfPatcher(enable_reporting=False, - group='patrole_log')) - - mock_authority.PolicyAuthority.return_value.allowed.return_value = True - - @rbac_rv.action(mock.sentinel.service, rules=[mock.sentinel.action]) - def test_policy(*args): - pass - - test_policy(self.test_obj) - self.assertFalse(mock_rbaclog.info.called) - - @mock.patch.object(rbac_rv, 'RBACLOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rbac_report_logging_enabled(self, mock_authority, mock_rbaclog): - """Test case to ensure that we DO write logs when enable_reporting is - True - """ - self.useFixture( - patrole_fixtures.ConfPatcher(enable_reporting=True, - group='patrole_log')) - - mock_authority.PolicyAuthority.return_value.allowed.return_value = True - policy_names = ['foo:bar', 'baz:qux'] - - @rbac_rv.action(mock.sentinel.service, rules=policy_names) - def test_policy(*args): - pass - - test_policy(self.test_obj) - mock_rbaclog.info.assert_called_once_with( - "[Service]: %s, [Test]: %s, [Rules]: %s, " - "[Expected]: %s, [Actual]: %s", - mock.sentinel.service, - 'test_policy', - ', '.join(policy_names), - "Allowed", - "Allowed") - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_with_callable_rule(self, mock_authority, - mock_log): - """Test that a callable as the rule is evaluated correctly.""" - mock_authority.PolicyAuthority.return_value.allowed.return_value = True - - @rbac_rv.action(mock.sentinel.service, - rules=[lambda: mock.sentinel.action]) - def test_policy(*args): - pass - - test_policy(self.test_obj) - - policy_authority = mock_authority.PolicyAuthority.return_value - policy_authority.allowed.assert_called_with( - mock.sentinel.action, - self.test_obj.get_all_needed_roles(CONF.patrole.rbac_test_roles)) - - mock_log.error.assert_not_called() - - @mock.patch.object(rbac_rv, 'LOG', autospec=True) - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_with_conditional_callable_rule( - self, mock_authority, mock_log): - """Test that a complex callable with conditional logic as the rule is - evaluated correctly. - """ - mock_authority.PolicyAuthority.return_value.allowed.return_value = True - expected_roles = self.test_obj.get_all_needed_roles( - CONF.patrole.rbac_test_roles) - - def partial_func(x): - return "foo" if x == "bar" else "qux" - foo_callable = functools.partial(partial_func, "bar") - bar_callable = functools.partial(partial_func, "baz") - - @rbac_rv.action(mock.sentinel.service, - rules=[foo_callable]) - def test_foo_policy(*args): - pass - - @rbac_rv.action(mock.sentinel.service, - rules=[bar_callable]) - def test_bar_policy(*args): - pass - - test_foo_policy(self.test_obj) - policy_authority = mock_authority.PolicyAuthority.return_value - policy_authority.allowed.assert_called_with( - "foo", - expected_roles) - policy_authority.allowed.reset_mock() - - test_bar_policy(self.test_obj) - policy_authority = mock_authority.PolicyAuthority.return_value - policy_authority.allowed.assert_called_with( - "qux", - expected_roles) - - mock_log.error.assert_not_called() - - -class RBACMultiRoleRuleValidationLoggingTest( - BaseRBACMultiRoleRuleValidationTest, RBACRuleValidationLoggingTest): - pass - - -class RBACRuleValidationNegativeTest(BaseRBACRuleValidationTest): - - def setUp(self): - super(RBACRuleValidationNegativeTest, self).setUp() - # This behavior is tested in separate test class below. - self.useFixture(fixtures.MockPatchObject( - rbac_rv, '_validate_override_role_called')) - - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_invalid_service_raises_exc(self, mock_authority): - """Test that invalid service raises the appropriate exception.""" - mock_authority.PolicyAuthority.return_value.allowed.side_effect = ( - rbac_exceptions.RbacInvalidServiceException) - - @rbac_rv.action(mock.sentinel.service, mock.sentinel.action) - def test_policy(*args): - pass - - self.assertRaises(rbac_exceptions.RbacInvalidServiceException, - test_policy, self.test_obj) - - -class RBACMultiRoleRuleValidationNegativeTest( - BaseRBACMultiRoleRuleValidationTest, RBACRuleValidationNegativeTest): - pass - - -class RBACRuleValidationTestMultiPolicy(BaseRBACRuleValidationTest): - """Test suite for validating multi-policy support for the - ``rbac_rule_validation`` decorator. - """ - - def setUp(self): - super(RBACRuleValidationTestMultiPolicy, self).setUp() - # This behavior is tested in separate test class below. - self.useFixture(fixtures.MockPatchObject( - rbac_rv, '_validate_override_role_called')) - - def _assert_policy_authority_called_with(self, rules, mock_authority): - m_authority = mock_authority.PolicyAuthority.return_value - m_authority.allowed.assert_has_calls([ - mock.call( - rule, - self.test_obj.get_all_needed_roles( - CONF.patrole.rbac_test_roles) - ) for rule in rules - ]) - m_authority.allowed.reset_mock() - - @mock.patch.object(rbac_rv, 'policy_authority', autospec=True) - def test_rule_validation_multi_policy_have_permission_success( - self, mock_authority): - """Test that when expected result is authorized and test passes that - the overall evaluation succeeds. - """ - mock_authority.PolicyAuthority.return_value.allowed.\ - return_value = True - - rules = [mock.sentinel.action1, mock.sentinel.action2] - - @rbac_rv.action(mock.sentinel.service, rules=rules, - expected_error_codes=[403, 403]) - def test_policy(*args): - pass - - t