From c2e51939b43afcdc20e24f86595655bf588a81a0 Mon Sep 17 00:00:00 2001 From: Michael Johnson Date: Tue, 28 Mar 2023 00:16:32 +0000 Subject: [PATCH] Update designate for RBAC "direction change" The RBAC goal has changed[1] and system scope is no longer going to be used. This patch updates Designate to align to this change in direction by removing the system scope from the policies. It also updates the functional tests to be ready for the switch to using the new keystone roles by default. [1] https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html#direction-change Depends-On: https://review.opendev.org/c/openstack/designate-tempest-plugin/+/879111 Change-Id: I1937e215dbd072b0a095df659c75f17a3f48c937 --- .zuul.yaml | 9 +- designate/api/middleware.py | 13 +- designate/common/constants.py | 3 + designate/common/policies/base.py | 4 +- designate/common/policies/blacklist.py | 13 +- designate/common/policies/context.py | 11 +- designate/common/policies/pool.py | 15 +- designate/common/policies/quota.py | 7 +- designate/common/policies/record.py | 5 +- designate/common/policies/recordset.py | 17 +- designate/common/policies/service_status.py | 7 +- designate/common/policies/shared_zones.py | 9 +- designate/common/policies/tenant.py | 7 +- designate/common/policies/tld.py | 11 +- designate/common/policies/tsigkey.py | 11 +- designate/common/policies/zone.py | 27 +- designate/common/policies/zone_export.py | 13 +- designate/common/policies/zone_import.py | 11 +- .../common/policies/zone_transfer_accept.py | 7 +- .../common/policies/zone_transfer_request.py | 11 +- designate/context.py | 1 - designate/tests/test_api/test_v2/__init__.py | 3 +- .../test_api/test_v2/test_floatingips.py | 3 +- .../test_api/test_v2/test_hostheaders.py | 6 +- .../test_api/test_v2/test_import_export.py | 66 +++-- .../tests/test_api/test_v2/test_quotas.py | 68 +++-- .../tests/test_api/test_v2/test_recordsets.py | 241 +++++++++++------- .../test_api/test_v2/test_shared_zones.py | 23 +- .../tests/test_api/test_v2/test_zones.py | 202 +++++++++------ designate/tests/test_central/test_service.py | 80 +++--- designate/tests/test_storage/__init__.py | 6 +- 31 files changed, 551 insertions(+), 359 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index f2dc6eb83..a45220f09 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -62,7 +62,7 @@ nslookup_target: 'opendev.org' - job: - name: designate-bind9-scoped-tokens + name: designate-bind9-keystone-default-roles post-run: playbooks/designate-bind9/post.yaml parent: designate-base vars: @@ -70,12 +70,9 @@ post-config: $DESIGNATE_CONF: oslo_policy: - enforce_scope: True enforce_new_defaults: True test-config: "$TEMPEST_CONFIG": - enforce_scope: - designate: True dns_feature_enabled: enforce_new_defaults: True @@ -189,7 +186,7 @@ voting: false - designate-bind9-centos-9-stream: voting: false - - designate-bind9-scoped-tokens + - designate-bind9-keystone-default-roles - designate-pdns4 - designate-grenade-bind9 - designate-grenade-pdns4 @@ -199,7 +196,7 @@ fail-fast: true jobs: - designate-bind9 - - designate-bind9-scoped-tokens + - designate-bind9-keystone-default-roles - designate-pdns4 - designate-grenade-pdns4 - designate-ipv6-only-pdns4 diff --git a/designate/api/middleware.py b/designate/api/middleware.py index 9451b8428..932ee874f 100644 --- a/designate/api/middleware.py +++ b/designate/api/middleware.py @@ -202,11 +202,22 @@ class TestContextMiddleware(ContextMiddleware): all_tenants = strutils.bool_from_string( headers.get('X-Test-All-Tenants', 'False')) + role_header = headers.get('X-Test-Role', None) + role_header = role_header.lower() if role_header else None + if role_header == 'admin': + roles = ['admin', 'member', 'reader'] + elif role_header == 'member': + roles = ['member', 'reader'] + elif role_header == 'reader': + roles = ['reader'] + else: + roles = [] + self.make_context( request, user_id=headers.get('X-Test-User-ID', self.default_user_id), project_id=headers.get('X-Test-Tenant-ID', self.default_tenant_id), - all_tenants=all_tenants + all_tenants=all_tenants, roles=roles ) diff --git a/designate/common/constants.py b/designate/common/constants.py index cf837271e..ada9cc031 100644 --- a/designate/common/constants.py +++ b/designate/common/constants.py @@ -49,3 +49,6 @@ QUOTA_ZONE_RECORDSETS = 'zone_recordsets' QUOTA_ZONES = 'zones' VALID_QUOTAS = [QUOTA_API_EXPORT_SIZE, QUOTA_RECORDSET_RECORDS, QUOTA_ZONE_RECORDS, QUOTA_ZONE_RECORDSETS, QUOTA_ZONES] + +# RBAC scopes +PROJECT = 'project' diff --git a/designate/common/policies/base.py b/designate/common/policies/base.py index 90e3fda22..41bdcf075 100644 --- a/designate/common/policies/base.py +++ b/designate/common/policies/base.py @@ -27,13 +27,13 @@ RULE_ANY = "@" # They're allowed to create, read, update, or delete any system-specific # resource. They can also operate on project-specific resources where # applicable (e.g., cleaning up blacklists) -SYSTEM_ADMIN = 'role:admin and system_scope:all' +SYSTEM_ADMIN = 'role:admin' # Generic policy check string for read-only access to system-level resources. # This persona is useful for someone who needs access for auditing or even # support. These uses are also able to view project-specific resources where # applicable (e.g., listing all pools) -SYSTEM_READER = 'role:reader and system_scope:all' +SYSTEM_READER = 'role:admin' # This check string is reserved for actions that require the highest level of # authorization on a project or resources within the project diff --git a/designate/common/policies/blacklist.py b/designate/common/policies/blacklist.py index af23db7df..432d3027a 100644 --- a/designate/common/policies/blacklist.py +++ b/designate/common/policies/blacklist.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -64,7 +65,7 @@ rules = [ policy.DocumentedRuleDefault( name="create_blacklist", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Create blacklist.', operations=[ { @@ -77,7 +78,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_blacklists", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Find blacklists.', operations=[ { @@ -90,7 +91,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_blacklist", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Get blacklist.', operations=[ { @@ -103,7 +104,7 @@ rules = [ policy.DocumentedRuleDefault( name="update_blacklist", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Update blacklist.', operations=[ { @@ -116,7 +117,7 @@ rules = [ policy.DocumentedRuleDefault( name="delete_blacklist", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Delete blacklist.', operations=[ { @@ -129,7 +130,7 @@ rules = [ policy.DocumentedRuleDefault( name="use_blacklisted_zone", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Allowed bypass the blacklist.', operations=[ { diff --git a/designate/common/policies/context.py b/designate/common/policies/context.py index e5959d0e6..47ff705b7 100644 --- a/designate/common/policies/context.py +++ b/designate/common/policies/context.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base @@ -54,31 +55,31 @@ rules = [ policy.RuleDefault( name="all_tenants", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Action on all tenants.', deprecated_rule=deprecated_all_tenants), policy.RuleDefault( name="edit_managed_records", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Edit managed records.', deprecated_rule=deprecated_edit_managed_records), policy.RuleDefault( name="use_low_ttl", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Use low TTL.', deprecated_rule=deprecated_use_low_ttl), policy.RuleDefault( name="use_sudo", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Accept sudo from user to tenant.', deprecated_rule=deprecated_use_sudo), policy.RuleDefault( name="hard_delete", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Clean backend resources associated with zone", deprecated_rule=deprecated_hard_delete), ] diff --git a/designate/common/policies/pool.py b/designate/common/policies/pool.py index da39ef16f..2ca4f9ba9 100644 --- a/designate/common/policies/pool.py +++ b/designate/common/policies/pool.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -70,14 +71,14 @@ rules = [ policy.RuleDefault( name="create_pool", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Create pool.', deprecated_rule=deprecated_create_pool ), policy.DocumentedRuleDefault( name="find_pools", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Find pool.', operations=[ { @@ -90,7 +91,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_pool", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Find pools.', operations=[ { @@ -103,7 +104,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_pool", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Get pool.', operations=[ { @@ -116,21 +117,21 @@ rules = [ policy.RuleDefault( name="update_pool", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Update pool.', deprecated_rule=deprecated_update_pool ), policy.RuleDefault( name="delete_pool", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Delete pool.', deprecated_rule=deprecated_delete_pool ), policy.DocumentedRuleDefault( name="zone_create_forced_pool", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='load and set the pool to the one provided in the Zone attributes.', # noqa operations=[ { diff --git a/designate/common/policies/quota.py b/designate/common/policies/quota.py index 7b28d8411..3f01c0ae4 100644 --- a/designate/common/policies/quota.py +++ b/designate/common/policies/quota.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -45,7 +46,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_quotas", check_str=base.SYSTEM_OR_PROJECT_READER_OR_ALL_TENANTS_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="View Current Project's Quotas.", operations=[ { @@ -58,7 +59,7 @@ rules = [ policy.DocumentedRuleDefault( name="set_quota", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Set Quotas.', operations=[ { @@ -71,7 +72,7 @@ rules = [ policy.DocumentedRuleDefault( name="reset_quotas", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description='Reset Quotas.', operations=[ { diff --git a/designate/common/policies/record.py b/designate/common/policies/record.py index 61efe4f9b..f6a0ab4d2 100644 --- a/designate/common/policies/record.py +++ b/designate/common/policies/record.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -40,7 +41,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_records", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description='Find records.', operations=[ { @@ -56,7 +57,7 @@ rules = [ policy.RuleDefault( name="count_records", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], deprecated_rule=deprecated_count_records ) ] diff --git a/designate/common/policies/recordset.py b/designate/common/policies/recordset.py index 0b6f16143..5ac25747d 100644 --- a/designate/common/policies/recordset.py +++ b/designate/common/policies/recordset.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -125,7 +126,7 @@ rules = [ policy.DocumentedRuleDefault( name="create_recordset", check_str=SYSTEM_ADMIN_OR_PROJECT_MEMBER_ZONE_TYPE, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Create Recordset", operations=[ { @@ -138,13 +139,13 @@ rules = [ policy.RuleDefault( name="get_recordsets", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], deprecated_rule=deprecated_get_recordsets ), policy.DocumentedRuleDefault( name="get_recordset", check_str=base.SYSTEM_OR_PROJECT_READER_OR_SHARED, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Get recordset", operations=[ { @@ -157,14 +158,14 @@ rules = [ policy.RuleDefault( name="find_recordset", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="List a Recordset in a Zone", deprecated_rule=deprecated_find_recordset ), policy.DocumentedRuleDefault( name="find_recordsets", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="List Recordsets in a Zone", operations=[ { @@ -177,7 +178,7 @@ rules = [ policy.DocumentedRuleDefault( name="update_recordset", check_str=SYSTEM_ADMIN_OR_PROJECT_MEMBER_RECORD_OWNER_ZONE_TYPE, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Update recordset", operations=[ { @@ -190,7 +191,7 @@ rules = [ policy.DocumentedRuleDefault( name="delete_recordset", check_str=SYSTEM_ADMIN_OR_PROJECT_MEMBER_RECORD_OWNER_ZONE_TYPE, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Delete RecordSet", operations=[ { @@ -203,7 +204,7 @@ rules = [ policy.RuleDefault( name="count_recordset", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Count recordsets", deprecated_rule=deprecated_count_recordset, ) diff --git a/designate/common/policies/service_status.py b/designate/common/policies/service_status.py index 4672aa3bb..03f4eaff3 100644 --- a/designate/common/policies/service_status.py +++ b/designate/common/policies/service_status.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -46,7 +47,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_service_status", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Find a single Service Status", operations=[ { @@ -59,7 +60,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_service_statuses", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="List service statuses.", operations=[ { @@ -72,7 +73,7 @@ rules = [ policy.RuleDefault( name="update_service_status", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], deprecated_rule=deprecated_update_service_status ) ] diff --git a/designate/common/policies/shared_zones.py b/designate/common/policies/shared_zones.py index 80e85dee4..853dc6603 100644 --- a/designate/common/policies/shared_zones.py +++ b/designate/common/policies/shared_zones.py @@ -14,6 +14,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base @@ -53,7 +54,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_zone_share", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Get a Zone Share", operations=[ { @@ -66,7 +67,7 @@ rules = [ policy.DocumentedRuleDefault( name="share_zone", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Share a Zone", operations=[ { @@ -92,14 +93,14 @@ rules = [ policy.RuleDefault( name="find_project_zone_share", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Check the can query for a specific projects shares.", deprecated_rule=deprecated_find_project_zone_share ), policy.DocumentedRuleDefault( name="unshare_zone", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Unshare Zone", operations=[ { diff --git a/designate/common/policies/tenant.py b/designate/common/policies/tenant.py index e70b3f7a4..6a2a23cc5 100644 --- a/designate/common/policies/tenant.py +++ b/designate/common/policies/tenant.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -46,21 +47,21 @@ rules = [ policy.RuleDefault( name="find_tenants", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Find all Tenants.", deprecated_rule=deprecated_find_tenants ), policy.RuleDefault( name="get_tenant", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Get all Tenants.", deprecated_rule=deprecated_get_tenant ), policy.RuleDefault( name="count_tenants", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Count tenants", deprecated_rule=deprecated_count_tenants ) diff --git a/designate/common/policies/tld.py b/designate/common/policies/tld.py index 798983925..64135d4fe 100644 --- a/designate/common/policies/tld.py +++ b/designate/common/policies/tld.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -58,7 +59,7 @@ rules = [ policy.DocumentedRuleDefault( name="create_tld", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Create Tld", operations=[ { @@ -71,7 +72,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_tlds", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="List Tlds", operations=[ { @@ -84,7 +85,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_tld", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Show Tld", operations=[ { @@ -97,7 +98,7 @@ rules = [ policy.DocumentedRuleDefault( name="update_tld", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Update Tld", operations=[ { @@ -110,7 +111,7 @@ rules = [ policy.DocumentedRuleDefault( name="delete_tld", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Delete Tld", operations=[ { diff --git a/designate/common/policies/tsigkey.py b/designate/common/policies/tsigkey.py index b8d593110..f047b6ee2 100644 --- a/designate/common/policies/tsigkey.py +++ b/designate/common/policies/tsigkey.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -58,7 +59,7 @@ rules = [ policy.DocumentedRuleDefault( name="create_tsigkey", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Create Tsigkey", operations=[ { @@ -71,7 +72,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_tsigkeys", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="List Tsigkeys", operations=[ { @@ -84,7 +85,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_tsigkey", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Show a Tsigkey", operations=[ { @@ -97,7 +98,7 @@ rules = [ policy.DocumentedRuleDefault( name="update_tsigkey", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Update Tsigkey", operations=[ { @@ -110,7 +111,7 @@ rules = [ policy.DocumentedRuleDefault( name="delete_tsigkey", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Delete a Tsigkey", operations=[ { diff --git a/designate/common/policies/zone.py b/designate/common/policies/zone.py index a5ad56872..669f2c112 100644 --- a/designate/common/policies/zone.py +++ b/designate/common/policies/zone.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -106,7 +107,7 @@ rules = [ policy.DocumentedRuleDefault( name="create_zone", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Create Zone", operations=[ { @@ -119,13 +120,13 @@ rules = [ policy.RuleDefault( name="get_zones", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], deprecated_rule=deprecated_get_zones ), policy.DocumentedRuleDefault( name="get_zone", check_str=base.SYSTEM_OR_PROJECT_READER_OR_SHARED, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Get Zone", operations=[ { @@ -138,13 +139,13 @@ rules = [ policy.RuleDefault( name="get_zone_servers", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], deprecated_rule=deprecated_get_zone_servers ), policy.DocumentedRuleDefault( name="get_zone_ns_records", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Get the Name Servers for a Zone", operations=[ { @@ -157,7 +158,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_zones", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="List existing zones", operations=[ { @@ -170,7 +171,7 @@ rules = [ policy.DocumentedRuleDefault( name="update_zone", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Update Zone", operations=[ { @@ -183,7 +184,7 @@ rules = [ policy.DocumentedRuleDefault( name="delete_zone", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Delete Zone", operations=[ { @@ -196,7 +197,7 @@ rules = [ policy.DocumentedRuleDefault( name="xfr_zone", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Manually Trigger an Update of a Secondary Zone", operations=[ { @@ -209,7 +210,7 @@ rules = [ policy.DocumentedRuleDefault( name="abandon_zone", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], description="Abandon Zone", operations=[ { @@ -222,19 +223,19 @@ rules = [ policy.RuleDefault( name="count_zones", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], deprecated_rule=deprecated_count_zones ), policy.RuleDefault( name="count_zones_pending_notify", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], deprecated_rule=deprecated_count_zones_pending_notify ), policy.RuleDefault( name="purge_zones", check_str=base.SYSTEM_ADMIN, - scope_types=['system'], + scope_types=[constants.PROJECT], deprecated_rule=deprecated_purge_zones ), ] diff --git a/designate/common/policies/zone_export.py b/designate/common/policies/zone_export.py index ca45971b9..15285ea99 100644 --- a/designate/common/policies/zone_export.py +++ b/designate/common/policies/zone_export.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -64,7 +65,7 @@ rules = [ policy.DocumentedRuleDefault( name="zone_export", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Retrive a Zone Export from the Designate Datastore", operations=[ { @@ -77,7 +78,7 @@ rules = [ policy.DocumentedRuleDefault( name="create_zone_export", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Create Zone Export", operations=[ { @@ -90,7 +91,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_zone_exports", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="List Zone Exports", operations=[ { @@ -103,7 +104,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_zone_export", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Get Zone Exports", operations=[ { @@ -116,7 +117,7 @@ rules = [ policy.DocumentedRuleDefault( name="update_zone_export", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Update Zone Exports", operations=[ { @@ -129,7 +130,7 @@ rules = [ policy.DocumentedRuleDefault( name="delete_zone_export", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Delete a zone export", operations=[ { diff --git a/designate/common/policies/zone_import.py b/designate/common/policies/zone_import.py index 8d4f2b171..fb4ad7ffb 100644 --- a/designate/common/policies/zone_import.py +++ b/designate/common/policies/zone_import.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -58,7 +59,7 @@ rules = [ policy.DocumentedRuleDefault( name="create_zone_import", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Create Zone Import", operations=[ { @@ -71,7 +72,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_zone_imports", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="List all Zone Imports", operations=[ { @@ -84,7 +85,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_zone_import", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Get Zone Imports", operations=[ { @@ -97,7 +98,7 @@ rules = [ policy.DocumentedRuleDefault( name="update_zone_import", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Update Zone Imports", operations=[ { @@ -110,7 +111,7 @@ rules = [ policy.DocumentedRuleDefault( name="delete_zone_import", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Delete a Zone Import", operations=[ { diff --git a/designate/common/policies/zone_transfer_accept.py b/designate/common/policies/zone_transfer_accept.py index ae718b2e0..65394314f 100644 --- a/designate/common/policies/zone_transfer_accept.py +++ b/designate/common/policies/zone_transfer_accept.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -46,7 +47,7 @@ rules = [ policy.DocumentedRuleDefault( name="create_zone_transfer_accept", check_str=base.RULE_ZONE_TRANSFER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Create Zone Transfer Accept", operations=[ { @@ -59,7 +60,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_zone_transfer_accept", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Get Zone Transfer Accept", operations=[ { @@ -72,7 +73,7 @@ rules = [ policy.DocumentedRuleDefault( name="find_zone_transfer_accepts", check_str=base.SYSTEM_READER, - scope_types=['system'], + scope_types=[constants.PROJECT], description="List Zone Transfer Accepts", operations=[ { diff --git a/designate/common/policies/zone_transfer_request.py b/designate/common/policies/zone_transfer_request.py index 7fdbd1c47..cf4d29b40 100644 --- a/designate/common/policies/zone_transfer_request.py +++ b/designate/common/policies/zone_transfer_request.py @@ -16,6 +16,7 @@ from oslo_log import versionutils from oslo_policy import policy +from designate.common import constants from designate.common.policies import base DEPRECATED_REASON = """ @@ -58,7 +59,7 @@ rules = [ policy.DocumentedRuleDefault( name="create_zone_transfer_request", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Create Zone Transfer Accept", operations=[ { @@ -71,7 +72,7 @@ rules = [ policy.DocumentedRuleDefault( name="get_zone_transfer_request", check_str=base.RULE_ZONE_TRANSFER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Show a Zone Transfer Request", operations=[ { @@ -84,7 +85,7 @@ rules = [ policy.RuleDefault( name="get_zone_transfer_request_detailed", check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], deprecated_rule=deprecated_create_zone_transfer_request ), policy.DocumentedRuleDefault( @@ -101,7 +102,7 @@ rules = [ policy.DocumentedRuleDefault( name="update_zone_transfer_request", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Update a Zone Transfer Request", operations=[ { @@ -114,7 +115,7 @@ rules = [ policy.DocumentedRuleDefault( name="delete_zone_transfer_request", check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=[constants.PROJECT], description="Delete a Zone Transfer Request", operations=[ { diff --git a/designate/context.py b/designate/context.py index 8a804ac76..0d9cb4120 100644 --- a/designate/context.py +++ b/designate/context.py @@ -151,7 +151,6 @@ class DesignateContext(context.RequestContext): # TODO(kiall): Remove Me kwargs['is_admin'] = True kwargs['roles'] = ['admin', 'reader'] - kwargs['system_scope'] = 'all' return cls(None, **kwargs) diff --git a/designate/tests/test_api/test_v2/__init__.py b/designate/tests/test_api/test_v2/__init__.py index cd49c1b56..938b803a6 100644 --- a/designate/tests/test_api/test_v2/__init__.py +++ b/designate/tests/test_api/test_v2/__init__.py @@ -120,7 +120,8 @@ class ApiV2TestCase(ApiTestCase): if marker is not None: params['marker'] = marker - r = self.client.get(url, params, status=expected_status) + r = self.client.get(url, params, status=expected_status, + headers={'X-Test-Role': 'member'}) if expected_status != 200: if expected_type: self._assert_exception(expected_type, expected_status, r) diff --git a/designate/tests/test_api/test_v2/test_floatingips.py b/designate/tests/test_api/test_v2/test_floatingips.py index f7cf20f1e..546f3beed 100644 --- a/designate/tests/test_api/test_v2/test_floatingips.py +++ b/designate/tests/test_api/test_v2/test_floatingips.py @@ -202,7 +202,8 @@ class ApiV2ReverseFloatingIPTest(ApiV2TestCase): response = self.client.patch_json( '/reverse/floatingips/%s' % ":".join([fip['region'], fip['id']]), fixture.to_dict(), - headers={'X-Test-Tenant-Id': 'tenant'}) + headers={'X-Test-Tenant-Id': 'tenant', + 'X-Test-Role': 'member'}) self.assertEqual(202, response.status_int) self.assertEqual('application/json', response.content_type) diff --git a/designate/tests/test_api/test_v2/test_hostheaders.py b/designate/tests/test_api/test_v2/test_hostheaders.py index 65d83739b..f82f3731d 100644 --- a/designate/tests/test_api/test_v2/test_hostheaders.py +++ b/designate/tests/test_api/test_v2/test_hostheaders.py @@ -30,7 +30,8 @@ class ApiV2HostHeadersTest(ApiV2TestCase): fixture = self.get_zone_fixture(fixture=0) response = self.client.post_json('/zones/', fixture, - headers={'Host': 'testhost.com'}) + headers={'Host': 'testhost.com', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) self.assertEqual('application/json', response.content_type) @@ -41,7 +42,8 @@ class ApiV2HostHeadersTest(ApiV2TestCase): # Get zone with host header response = self.client.get('/zones/', - headers={'Host': 'testhost.com'}) + headers={'Host': 'testhost.com', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) diff --git a/designate/tests/test_api/test_v2/test_import_export.py b/designate/tests/test_api/test_v2/test_import_export.py index a8af5f05c..7c7ec4f8d 100644 --- a/designate/tests/test_api/test_v2/test_import_export.py +++ b/designate/tests/test_api/test_v2/test_import_export.py @@ -50,14 +50,15 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): fixture = self.get_zonefile_fixture(variant='noorigin') response = self.client.post_json('/zones/tasks/imports', fixture, - headers={'Content-type': 'text/dns'}) + headers={'Content-type': 'text/dns', + 'X-Test-Role': 'member'}) import_id = response.json_body['id'] self.wait_for_import(import_id, error_is_ok=True) url = '/zones/tasks/imports/%s' % import_id - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) self.assertEqual('ERROR', response.json['status']) origin_msg = ("The $ORIGIN statement is required and must be the" " first statement in the zonefile.") @@ -67,14 +68,15 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): fixture = self.get_zonefile_fixture(variant='nosoa') response = self.client.post_json('/zones/tasks/imports', fixture, - headers={'Content-type': 'text/dns'}) + headers={'Content-type': 'text/dns', + 'X-Test-Role': 'member'}) import_id = response.json_body['id'] self.wait_for_import(import_id, error_is_ok=True) url = '/zones/tasks/imports/%s' % import_id - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) self.assertEqual('ERROR', response.json['status']) origin_msg = ("Malformed zonefile.") self.assertEqual(origin_msg, response.json['message']) @@ -83,14 +85,15 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): fixture = self.get_zonefile_fixture(variant='malformed') response = self.client.post_json('/zones/tasks/imports', fixture, - headers={'Content-type': 'text/dns'}) + headers={'Content-type': 'text/dns', + 'X-Test-Role': 'member'}) import_id = response.json_body['id'] self.wait_for_import(import_id, error_is_ok=True) url = '/zones/tasks/imports/%s' % import_id - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) self.assertEqual('ERROR', response.json['status']) origin_msg = ("Malformed zonefile.") self.assertEqual(origin_msg, response.json['message']) @@ -100,13 +103,14 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): # fixture, making sure they're the same according to dnspython post_response = self.client.post('/zones/tasks/imports', self.get_zonefile_fixture(), - headers={'Content-type': 'text/dns'}) + headers={'Content-type': 'text/dns', + 'X-Test-Role': 'member'}) import_id = post_response.json_body['id'] self.wait_for_import(import_id) url = '/zones/tasks/imports/%s' % import_id - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) self.policy({'zone_export': '@'}) get_response = self.adminclient.get('/zones/export/%s' % @@ -134,7 +138,8 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): def test_delete_import(self): post_response = self.client.post('/zones/tasks/imports', self.get_zonefile_fixture(), - headers={'Content-type': 'text/dns'}) + headers={'Content-type': 'text/dns', + 'X-Test-Role': 'member'}) import_id = post_response.json_body['id'] @@ -142,6 +147,7 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): delete_response = self.client.delete( '/zones/tasks/imports/%s' % import_id, + headers={'X-Test-Role': 'member'} ) self.assertEqual('', delete_response.text) @@ -151,14 +157,16 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): # Metadata tests def test_metadata_exists_imports(self): - response = self.client.get('/zones/tasks/imports') + response = self.client.get('/zones/tasks/imports', + headers={'X-Test-Role': 'member'}) # Make sure the fields exist self.assertIn('metadata', response.json) self.assertIn('total_count', response.json['metadata']) def test_metadata_exists_exports(self): - response = self.client.get('/zones/tasks/imports') + response = self.client.get('/zones/tasks/imports', + headers={'X-Test-Role': 'member'}) # Make sure the fields exist self.assertIn('metadata', response.json) @@ -166,7 +174,8 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): @unittest.skip("See bug 1582241 and 1570859") def test_total_count_imports(self): - response = self.client.get('/zones/tasks/imports') + response = self.client.get('/zones/tasks/imports', + headers={'X-Test-Role': 'member'}) # There are no imported zones by default self.assertEqual(0, response.json['metadata']['total_count']) @@ -174,15 +183,18 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): # Create a zone import self.client.post('/zones/tasks/imports', self.get_zonefile_fixture(), - headers={'Content-type': 'text/dns'}) + headers={'Content-type': 'text/dns', + 'X-Test-Role': 'member'}) - response = self.client.get('/zones/tasks/imports') + response = self.client.get('/zones/tasks/imports', + headers={'X-Test-Role': 'member'}) # Make sure total_count picked it up self.assertEqual(1, response.json['metadata']['total_count']) def test_total_count_exports(self): - response = self.client.get('/zones/tasks/exports') + response = self.client.get('/zones/tasks/exports', + headers={'X-Test-Role': 'member'}) # There are no exported zones by default self.assertEqual(0, response.json['metadata']['total_count']) @@ -190,14 +202,16 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): def test_create_export(self): zone = self.create_zone() create_response = self.client.post( - '/zones/%s/tasks/export' % zone['id'] + '/zones/%s/tasks/export' % zone['id'], + headers={'X-Test-Role': 'member'} ) self.assertEqual('PENDING', create_response.json_body['status']) self.assertEqual(zone['id'], create_response.json_body['zone_id']) get_response = self.client.get( - '/zones/tasks/exports/%s' % create_response.json_body['id'] + '/zones/tasks/exports/%s' % create_response.json_body['id'], + headers={'X-Test-Role': 'member'} ) self.assertEqual('PENDING', get_response.json_body['status']) @@ -206,39 +220,45 @@ class APIV2ZoneImportExportTest(ApiV2TestCase): def test_update_export(self): zone = self.create_zone() create_response = self.client.post( - '/zones/%s/tasks/export' % zone['id'] + '/zones/%s/tasks/export' % zone['id'], + headers={'X-Test-Role': 'member'} ) self.assertEqual('PENDING', create_response.json_body['status']) self.assertEqual(zone['id'], create_response.json_body['zone_id']) delete_response = self.client.delete( - '/zones/tasks/exports/%s' % create_response.json_body['id'] + '/zones/tasks/exports/%s' % create_response.json_body['id'], + headers={'X-Test-Role': 'member'} ) self.assertEqual('', delete_response.text) self._assert_exception( 'zone_export_not_found', 404, self.client.get, - '/zones/tasks/exports/%s' % create_response.json_body['id'] + '/zones/tasks/exports/%s' % create_response.json_body['id'], + headers={'X-Test-Role': 'member'} ) def test_delete_export(self): zone = self.create_zone() create_response = self.client.post( - '/zones/%s/tasks/export' % zone['id'] + '/zones/%s/tasks/export' % zone['id'], + headers={'X-Test-Role': 'member'} ) self.assertEqual('PENDING', create_response.json_body['status']) self.assertEqual(zone['id'], create_response.json_body['zone_id']) delete_response = self.client.delete( - '/zones/tasks/exports/%s' % create_response.json_body['id'] + '/zones/tasks/exports/%s' % create_response.json_body['id'], + headers={'X-Test-Role': 'member'} ) self.assertEqual('', delete_response.text) self._assert_exception( 'zone_export_not_found', 404, self.client.get, - '/zones/tasks/exports/%s' % create_response.json_body['id'] + '/zones/tasks/exports/%s' % create_response.json_body['id'], + headers={'X-Test-Role': 'member'} ) diff --git a/designate/tests/test_api/test_v2/test_quotas.py b/designate/tests/test_api/test_v2/test_quotas.py index be79981e9..330b11985 100644 --- a/designate/tests/test_api/test_v2/test_quotas.py +++ b/designate/tests/test_api/test_v2/test_quotas.py @@ -24,12 +24,10 @@ class ApiV2QuotasTest(ApiV2TestCase): def test_get_quotas(self): self.config(quota_api_export_size=1) - context = self.get_context(project_id='a') + result = self.client.get('/quotas/a', status=200, + headers={'X-Test-Tenant-Id': 'a', + 'X-Test-Role': 'member'}) - result = self.client.get( - '/quotas/%s' % context.project_id, status=200, - headers={'X-Test-Tenant-Id': context.project_id} - ) self.assertEqual( { 'zones': 10, @@ -44,9 +42,8 @@ class ApiV2QuotasTest(ApiV2TestCase): def test_get_all_quotas(self): self.config(quota_zone_recordsets=1) - result = self.client.get( - '/quotas', status=200, - ) + result = self.client.get('/quotas', status=200, + headers={'X-Test-Role': 'member'}) self.assertEqual( { @@ -62,16 +59,14 @@ class ApiV2QuotasTest(ApiV2TestCase): def test_set_quotas(self): self.policy({'set_quota': '@'}) - context = self.get_context(project_id='a') - self.client.patch_json( - '/quotas/%s' % context.project_id, {'zones': 123}, status=200, - headers={'X-Test-Tenant-Id': context.project_id} - ) + self.client.patch_json('/quotas/a', {'zones': 123}, status=200, + headers={'X-Test-Tenant-Id': 'a', + 'X-Test-Role': 'member'}) + + result = self.client.get('/quotas/a', status=200, + headers={'X-Test-Tenant-Id': 'a', + 'X-Test-Role': 'member'}) - result = self.client.get( - '/quotas/%s' % context.project_id, status=200, - headers={'X-Test-Tenant-Id': context.project_id} - ) self.assertEqual( { 'zones': 123, @@ -91,16 +86,14 @@ class ApiV2QuotasTest(ApiV2TestCase): self.policy({'set_quota': '@'}) - context = self.get_context(project_id='a') - self.client.patch_json( - '/quotas/%s' % context.project_id, {'zones': 123}, status=200, - headers={'X-Test-Tenant-Id': context.project_id} - ) + self.client.patch_json('/quotas/a', {'zones': 123}, status=200, + headers={'X-Test-Tenant-Id': 'a', + 'X-Test-Role': 'member'}) + + result = self.client.get('/quotas/a', status=200, + headers={'X-Test-Tenant-Id': 'a', + 'X-Test-Role': 'member'}) - result = self.client.get( - '/quotas/%s' % context.project_id, status=200, - headers={'X-Test-Tenant-Id': context.project_id} - ) self.assertEqual( { 'zones': 123, @@ -117,13 +110,11 @@ class ApiV2QuotasTest(ApiV2TestCase): self.policy({'set_quota': '@'}) - context = self.get_context(project_id='a') - # Update recordset_records quota. result = self.client.patch_json( - '/quotas/%s' % context.project_id, {'recordset_records': 123}, - status=200, - headers={'X-Test-Tenant-Id': context.project_id} + '/quotas/a', {'recordset_records': 123}, + status=200, headers={'X-Test-Tenant-Id': 'a', + 'X-Test-Role': 'member'} ) self.assertEqual( { @@ -137,16 +128,15 @@ class ApiV2QuotasTest(ApiV2TestCase): ) # Delete quota. - self.client.delete( - '/quotas/%s' % context.project_id, status=204, - headers={'X-Test-Tenant-Id': context.project_id} - ) + self.client.delete('/quotas/a', status=204, + headers={'X-Test-Tenant-Id': 'a', + 'X-Test-Role': 'member'}) # Make sure we are back to the default quotas. - result = self.client.get( - '/quotas/%s' % context.project_id, status=200, - headers={'X-Test-Tenant-Id': context.project_id} - ) + result = self.client.get('/quotas/a', status=200, + headers={'X-Test-Tenant-Id': 'a', + 'X-Test-Role': 'member'}) + self.assertEqual( { 'zones': 10, diff --git a/designate/tests/test_api/test_v2/test_recordsets.py b/designate/tests/test_api/test_v2/test_recordsets.py index c9d750f6f..fa03e9347 100644 --- a/designate/tests/test_api/test_v2/test_recordsets.py +++ b/designate/tests/test_api/test_v2/test_recordsets.py @@ -37,7 +37,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Prepare a RecordSet fixture fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) response = self.client.post_json( - '/zones/%s/recordsets' % self.zone['id'], fixture) + '/zones/%s/recordsets' % self.zone['id'], fixture, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(201, response.status_int) @@ -60,7 +61,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) fixture['ttl'] = 0 response = self.client.post_json( - '/zones/%s/recordsets' % self.zone['id'], fixture) + '/zones/%s/recordsets' % self.zone['id'], fixture, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(201, response.status_int) @@ -75,7 +77,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - response = self.client.put_json(url, body, status=200) + response = self.client.put_json(url, body, status=200, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -89,7 +92,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Check the zone's status is as expected response = self.client.get('/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']), - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) self.assertEqual('application/json', response.content_type) @@ -106,7 +110,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): ) response = self.client.post_json( - '/zones/%s/recordsets' % self.zone['id'], fixture) + '/zones/%s/recordsets' % self.zone['id'], fixture, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) @@ -120,7 +125,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Check the zone's status is as expected response = self.client.get('/zones/%s' % self.zone['id'], - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) self.assertEqual('application/json', response.content_type) @@ -147,7 +153,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Ensure it fails with a 400 self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_with_name_too_long(self): fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) @@ -155,7 +162,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): body = fixture url = '/zones/%s/recordsets' % self.zone['id'] self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_with_name_missing(self): fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) @@ -163,7 +171,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): body = fixture url = '/zones/%s/recordsets' % self.zone['id'] self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_type_is_missing(self): # Prepare a RecordSet fixture @@ -186,7 +195,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Ensure it fails with a 400 self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_with_invalid_type(self): fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) @@ -194,7 +204,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): body = fixture url = '/zones/%s/recordsets' % self.zone['id'] self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_description_too_long(self): fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) @@ -202,7 +213,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): body = fixture url = '/zones/%s/recordsets' % self.zone['id'] self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_with_negative_ttl(self): fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) @@ -210,7 +222,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): body = fixture url = '/zones/%s/recordsets' % self.zone['id'] self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_with_ttl_greater_than_max(self): fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) @@ -218,7 +231,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): body = fixture url = '/zones/%s/recordsets' % self.zone['id'] self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_with_invalid_ttl(self): fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) @@ -226,10 +240,12 @@ class ApiV2RecordSetsTest(ApiV2TestCase): body = fixture url = '/zones/%s/recordsets' % self.zone['id'] self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_invalid_id(self): - self._assert_invalid_uuid(self.client.post, '/zones/%s/recordsets') + self._assert_invalid_uuid(self.client.post, '/zones/%s/recordsets', + headers={'X-Test-Role': 'member'}) def test_create_recordset_validation(self): # NOTE: The schemas should be tested separatly to the API. So we @@ -245,7 +261,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Ensure it fails with a 400 self._assert_exception( - 'invalid_object', 400, self.client.post_json, url, body) + 'invalid_object', 400, self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'create_recordset', side_effect=messaging.MessagingTimeout()) @@ -257,7 +274,7 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets' % self.zone['id'] self._assert_exception('timeout', 504, self.client.post_json, url, - body) + body, headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'create_recordset', side_effect=exceptions.DuplicateRecordSet()) @@ -269,7 +286,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets' % self.zone['id'] self._assert_exception('duplicate_recordset', 409, - self.client.post_json, url, body) + self.client.post_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_recordset_invalid_zone(self): fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) @@ -279,24 +297,28 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/ba751950-6193-11e3-949a-0800200c9a66/recordsets' self._assert_exception('zone_not_found', 404, self.client.post_json, - url, body) + url, body, headers={'X-Test-Role': 'member'}) def test_recordsets_invalid_url(self): url = '/zones/recordsets' - self._assert_exception('not_found', 404, self.client.get, url) - self._assert_exception('not_found', 404, self.client.post_json, url) + self._assert_exception('not_found', 404, self.client.get, url, + headers={'X-Test-Role': 'member'}) + self._assert_exception('not_found', 404, self.client.post_json, url, + headers={'X-Test-Role': 'member'}) # Pecan returns a 405 for Patch and delete operations - response = self.client.patch_json(url, status=405) + response = self.client.patch_json(url, status=405, + headers={'X-Test-Role': 'member'}) self.assertEqual(405, response.status_int) - response = self.client.delete(url, status=405) + response = self.client.delete(url, status=405, + headers={'X-Test-Role': 'member'}) self.assertEqual(405, response.status_int) def test_get_recordsets(self): url = '/zones/%s/recordsets' % self.zone['id'] - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -352,7 +374,7 @@ class ApiV2RecordSetsTest(ApiV2TestCase): for fixture in fixtures: response = self.client.post_json( '/zones/%s/recordsets' % self.zone['id'], - fixture) + fixture, headers={'X-Test-Role': 'member'}) get_urls = [ # Filter by Name @@ -380,7 +402,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): correct_results = [1, 1, 2, 1, 1, 2, 1, 1] for get_url, correct_result in zip(get_urls, correct_results): - response = self.client.get(get_url) + response = self.client.get(get_url, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -397,21 +420,22 @@ class ApiV2RecordSetsTest(ApiV2TestCase): def test_get_recordsets_timeout(self, _): url = '/zones/ba751950-6193-11e3-949a-0800200c9a66/recordsets' - self._assert_exception('timeout', 504, self.client.get, url) + self._assert_exception('timeout', 504, self.client.get, url, + headers={'X-Test-Role': 'member'}) def test_get_deleted_recordsets(self): zone = self.create_zone(fixture=1) recordset = self.create_recordset(zone, records=[]) url = '/zones/%s/recordsets' % zone['id'] - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) # Now delete the recordset url = '/zones/%s/recordsets/%s' % (zone['id'], recordset.id) - self.client.delete(url, status=202) + self.client.delete(url, status=202, headers={'X-Test-Role': 'member'}) # Simulate the zone having been deleted on the backend zone_serial = self.central_service.get_zone( @@ -423,20 +447,21 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Try to get the record and ensure that we get a # recordset_not_found error self._assert_exception('recordset_not_found', 404, self.client.get, - url) + url, headers={'X-Test-Role': 'member'}) def test_get_deleted_recordset_after_deleting_zone(self): zone = self.create_zone(fixture=1) self.create_recordset(zone) url = '/zones/%s/recordsets' % zone['id'] - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) # Now delete the zone - self.client.delete('/zones/%s' % zone['id'], status=202) + self.client.delete('/zones/%s' % zone['id'], status=202, + headers={'X-Test-Role': 'member'}) # Simulate the zone having been deleted on the backend zone_serial = self.central_service.get_zone( @@ -447,14 +472,15 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Try to get the record and ensure that we get a # zone_not_found error - self._assert_exception('zone_not_found', 404, self.client.get, url) + self._assert_exception('zone_not_found', 404, self.client.get, url, + headers={'X-Test-Role': 'member'}) def test_get_recordset(self): # Create a recordset recordset = self.create_recordset(self.zone, records=[]) url = '/zones/%s/recordsets/%s' % (self.zone['id'], recordset['id']) - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -474,7 +500,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): self.assertEqual('ACTIVE', response.json['status']) def test_get_recordset_invalid_id(self): - self._assert_invalid_uuid(self.client.get, '/zones/%s/recordsets/%s') + self._assert_invalid_uuid(self.client.get, '/zones/%s/recordsets/%s', + headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_recordset', side_effect=messaging.MessagingTimeout()) @@ -483,7 +510,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): self.zone['id']) self._assert_exception('timeout', 504, self.client.get, url, - headers={'Accept': 'application/json'}) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_recordset', side_effect=exceptions.RecordSetNotFound()) @@ -493,7 +521,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): self._assert_exception('recordset_not_found', 404, self.client.get, url, - headers={'Accept': 'application/json'}) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) def test_update_recordset(self): # Create a recordset @@ -504,7 +533,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - response = self.client.put_json(url, body, status=200) + response = self.client.put_json(url, body, status=200, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -524,7 +554,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Check the zone's status is as expected response = self.client.get('/zones/%s' % recordset['zone_id'], - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) self.assertEqual('application/json', response.content_type) @@ -547,7 +578,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - response = self.client.put_json(url, body, status=202) + response = self.client.put_json(url, body, status=202, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) @@ -563,7 +595,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Check the zone's status is as expected response = self.client.get('/zones/%s' % recordset['zone_id'], - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) self.assertEqual('application/json', response.content_type) @@ -581,7 +614,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - response = self.client.put_json(url, body, status=202) + response = self.client.put_json(url, body, status=202, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) @@ -595,7 +629,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Check the zone's status is as expected response = self.client.get('/zones/%s' % recordset['zone_id'], - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) self.assertEqual('application/json', response.content_type) @@ -611,7 +646,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - self.client.put_json(url, body, status=202) + self.client.put_json(url, body, status=202, + headers={'X-Test-Role': 'member'}) def test_create_txt_record_too_long(self): # See bug #1474012 @@ -621,7 +657,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) self._assert_exception('invalid_object', 400, - self.client.put_json, url, body) + self.client.put_json, url, body, + headers={'X-Test-Role': 'member'}) def test_create_txt_record_multiple_strings(self): # create TXT record with string split in 2 @@ -631,7 +668,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): body = {'description': 'Tester', 'records': [record]} url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - self.client.put_json(url, body, status=202) + self.client.put_json(url, body, status=202, + headers={'X-Test-Role': 'member'}) def test_update_recordset_with_record_clear(self): # Create a recordset with one record @@ -642,7 +680,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - response = self.client.put_json(url, body, status=200) + response = self.client.put_json(url, body, status=200, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -654,7 +693,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Check the zone's status is as expected response = self.client.get('/zones/%s' % recordset['zone_id'], - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) self.assertEqual('application/json', response.content_type) @@ -664,7 +704,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): def test_update_recordset_invalid_id(self): self._assert_invalid_uuid( - self.client.put_json, '/zones/%s/recordsets/%s') + self.client.put_json, '/zones/%s/recordsets/%s', + headers={'X-Test-Role': 'member'}) def test_update_recordset_validation(self): # NOTE: The schemas should be tested separatly to the API. So we @@ -682,14 +723,14 @@ class ApiV2RecordSetsTest(ApiV2TestCase): recordset['id']) self._assert_exception('invalid_object', 400, self.client.put_json, - url, body) + url, body, headers={'X-Test-Role': 'member'}) # Prepare an update body with junk in the body body = {'description': 'Tester', 'junk': 'Junk Field'} # Ensure it fails with a 400 self._assert_exception('invalid_object', 400, self.client.put_json, - url, body) + url, body, headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_recordset', side_effect=exceptions.DuplicateRecordSet()) @@ -702,7 +743,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): % (self.zone['id'])) self._assert_exception('duplicate_recordset', 409, - self.client.put_json, url, body) + self.client.put_json, url, body, + headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_recordset', side_effect=messaging.MessagingTimeout()) @@ -715,7 +757,7 @@ class ApiV2RecordSetsTest(ApiV2TestCase): % (self.zone['id'])) self._assert_exception('timeout', 504, self.client.put_json, url, - body) + body, headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_recordset', side_effect=exceptions.RecordSetNotFound()) @@ -728,7 +770,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): % (self.zone['id'])) self._assert_exception('recordset_not_found', 404, - self.client.put_json, url, body) + self.client.put_json, url, body, + headers={'X-Test-Role': 'member'}) def test_update_recordset_invalid_ttl(self): recordset = self.create_recordset(self.zone) @@ -736,7 +779,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) self._assert_exception('invalid_object', 400, - self.client.put_json, url, body) + self.client.put_json, url, body, + headers={'X-Test-Role': 'member'}) def test_update_recordset_negative_ttl(self): recordset = self.create_recordset(self.zone) @@ -744,7 +788,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) self._assert_exception('invalid_object', 400, - self.client.put_json, url, body) + self.client.put_json, url, body, + headers={'X-Test-Role': 'member'}) def test_update_recordset_ttl_greater_than_max(self): recordset = self.create_recordset(self.zone) @@ -752,7 +797,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) self._assert_exception('invalid_object', 400, - self.client.put_json, url, body) + self.client.put_json, url, body, + headers={'X-Test-Role': 'member'}) def test_update_recordset_description_too_long(self): recordset = self.create_recordset(self.zone) @@ -760,14 +806,16 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) self._assert_exception('invalid_object', 400, - self.client.put_json, url, body) + self.client.put_json, url, body, + headers={'X-Test-Role': 'member'}) def test_delete_recordset(self): recordset = self.create_recordset(self.zone, records=[]) url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - response = self.client.delete(url, status=202) + response = self.client.delete(url, status=202, + headers={'X-Test-Role': 'member'}) self.assertEqual('application/json', response.content_type) # Currently recordset does not have a status field. As there are no @@ -777,7 +825,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Check the zone's status is as expected response = self.client.get('/zones/%s' % recordset['zone_id'], - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) self.assertEqual('application/json', response.content_type) @@ -791,7 +840,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - response = self.client.delete(url, status=202) + response = self.client.delete(url, status=202, + headers={'X-Test-Role': 'member'}) self.assertEqual('application/json', response.content_type) self.assertEqual('DELETE', response.json['action']) @@ -799,7 +849,8 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Check the zone's status is as expected response = self.client.get('/zones/%s' % recordset['zone_id'], - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) self.assertEqual('application/json', response.content_type) @@ -814,16 +865,18 @@ class ApiV2RecordSetsTest(ApiV2TestCase): % (self.zone['id'])) self._assert_exception('recordset_not_found', 404, - self.client.delete, url) + self.client.delete, url, + headers={'X-Test-Role': 'member'}) def test_delete_recordset_invalid_id(self): self._assert_invalid_uuid( - self.client.delete, '/zones/%s/recordsets/%s') + self.client.delete, '/zones/%s/recordsets/%s', + headers={'X-Test-Role': 'member'}) def test_metadata_exists(self): url = '/zones/%s/recordsets' % self.zone['id'] - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # Make sure the fields exist self.assertIn('metadata', response.json) @@ -832,7 +885,7 @@ class ApiV2RecordSetsTest(ApiV2TestCase): def test_total_count(self): url = '/zones/%s/recordsets' % self.zone['id'] - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # The NS and SOA records are there by default self.assertEqual(2, response.json['metadata']['total_count']) @@ -840,9 +893,10 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Create a recordset fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) response = self.client.post_json( - '/zones/%s/recordsets' % self.zone['id'], fixture) + '/zones/%s/recordsets' % self.zone['id'], fixture, + headers={'X-Test-Role': 'member'}) - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # Make sure total_count picked up the change self.assertEqual(3, response.json['metadata']['total_count']) @@ -854,19 +908,20 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Create a recordset fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) response = self.client.post_json( - '/zones/%s/recordsets' % self.zone['id'], fixture) + '/zones/%s/recordsets' % self.zone['id'], fixture, + headers={'X-Test-Role': 'member'}) - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # Make sure total_count picked up the change self.assertEqual(3, response.json['metadata']['total_count']) url = '/zones/%s/recordsets?data=nyan' % self.zone['id'] - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) self.assertEqual(0, response.json['metadata']['total_count']) url = '/zones/%s/recordsets?data=ns1.example.org.' % self.zone['id'] - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) self.assertEqual(1, response.json['metadata']['total_count']) # Test paging @@ -885,23 +940,25 @@ class ApiV2RecordSetsTest(ApiV2TestCase): # Even with paging enabled, total_count is still the total number of # recordsets matching the "data" filter url = '/zones/%s/recordsets?limit=1&data=nyan' % new_zone.id - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) self.assertEqual(2, response.json['metadata']['total_count']) def test_total_count_pagination(self): # Create two recordsets fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) response = self.client.post_json( - '/zones/%s/recordsets' % self.zone['id'], fixture) + '/zones/%s/recordsets' % self.zone['id'], fixture, + headers={'X-Test-Role': 'member'}) fixture = self.get_recordset_fixture(self.zone['name'], fixture=1) response = self.client.post_json( - '/zones/%s/recordsets' % self.zone['id'], fixture) + '/zones/%s/recordsets' % self.zone['id'], fixture, + headers={'X-Test-Role': 'member'}) # Paginate the recordsets to two, there should be four now url = '/zones/%s/recordsets?limit=2' % self.zone['id'] - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # There are two recordsets returned self.assertEqual(2, len(response.json['recordsets'])) @@ -919,7 +976,7 @@ class ApiV2RecordSetsTest(ApiV2TestCase): recordset = self.create_recordset(secondary) url = '/zones/%s/recordsets/%s' % (secondary['id'], recordset['id']) - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -942,7 +999,7 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets' % secondary['id'] - response = self.client.get(url) + response = self.client.get(url, headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -977,7 +1034,7 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets' % secondary['id'] self._assert_exception('forbidden', 403, self.client.post_json, url, - fixture) + fixture, headers={'X-Test-Role': 'member'}) def test_update_secondary_zone_recordset(self): fixture = self.get_zone_fixture('SECONDARY', 1) @@ -991,7 +1048,7 @@ class ApiV2RecordSetsTest(ApiV2TestCase): recordset['id']) self._assert_exception('forbidden', 403, self.client.put_json, url, - {'ttl': 100}) + {'ttl': 100}, headers={'X-Test-Role': 'member'}) def test_delete_secondary_zone_recordset(self): fixture = self.get_zone_fixture('SECONDARY', 1) @@ -1004,17 +1061,19 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - self._assert_exception('forbidden', 403, self.client.delete, url) + self._assert_exception('forbidden', 403, self.client.delete, url, + headers={'X-Test-Role': 'member'}) def test_no_create_rs_deleting_zone(self): # Prepare a create fixture = self.get_recordset_fixture(self.zone['name'], fixture=0) body = fixture - self.client.delete('/zones/%s' % self.zone['id'], status=202) + self.client.delete('/zones/%s' % self.zone['id'], status=202, + headers={'X-Test-Role': 'member'}) self._assert_exception('bad_request', 400, self.client.post_json, '/zones/%s/recordsets' % self.zone['id'], - body) + body, headers={'X-Test-Role': 'member'}) def test_no_update_rs_deleting_zone(self): # Create a recordset @@ -1024,9 +1083,10 @@ class ApiV2RecordSetsTest(ApiV2TestCase): body = {'description': 'Tester'} url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - self.client.delete('/zones/%s' % self.zone['id'], status=202) + self.client.delete('/zones/%s' % self.zone['id'], status=202, + headers={'X-Test-Role': 'member'}) self._assert_exception('bad_request', 400, self.client.put_json, url, - body) + body, headers={'X-Test-Role': 'member'}) def test_no_delete_rs_deleting_zone(self): # Create a recordset @@ -1035,10 +1095,13 @@ class ApiV2RecordSetsTest(ApiV2TestCase): url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], recordset['id']) - self.client.delete('/zones/%s' % self.zone['id'], status=202) - self._assert_exception('bad_request', 400, self.client.delete, url) + self.client.delete('/zones/%s' % self.zone['id'], status=202, + headers={'X-Test-Role': 'member'}) + self._assert_exception('bad_request', 400, self.client.delete, url, + headers={'X-Test-Role': 'member'}) def test_invalid_recordset_filter(self): invalid_url = '/zones/%s/recordsets?action=NONE' % self.zone['id'] self._assert_exception( - 'bad_request', 400, self.client.get, invalid_url) + 'bad_request', 400, self.client.get, invalid_url, + headers={'X-Test-Role': 'member'}) diff --git a/designate/tests/test_api/test_v2/test_shared_zones.py b/designate/tests/test_api/test_v2/test_shared_zones.py index a49e034ff..d100df7f6 100644 --- a/designate/tests/test_api/test_v2/test_shared_zones.py +++ b/designate/tests/test_api/test_v2/test_shared_zones.py @@ -27,7 +27,7 @@ class ApiV2SharedZonesTest(ApiV2TestCase): self.endpoint_url.format(self.zone.id), { 'target_project_id': self.target_project_id, - } + }, headers={'X-Test-Role': 'member'} ) def test_share_zone(self): @@ -55,19 +55,22 @@ class ApiV2SharedZonesTest(ApiV2TestCase): def test_share_zone_with_no_target_id_no_zone_id(self): self._assert_exception( 'invalid_uuid', 400, self.client.post_json, - self.endpoint_url.format(""), {"target_project_id": ""} + self.endpoint_url.format(""), {"target_project_id": ""}, + headers={'X-Test-Role': 'member'} ) def test_share_zone_with_target_id_no_zone_id(self): self._assert_exception( 'invalid_uuid', 400, self.client.post_json, - self.endpoint_url.format(""), {"target_project_id": "2"} + self.endpoint_url.format(""), {"target_project_id": "2"}, + headers={'X-Test-Role': 'member'} ) def test_share_zone_with_invalid_zone_id(self): self._assert_exception( 'invalid_uuid', 400, self.client.post_json, - self.endpoint_url.format("invalid"), {"target_project_id": "2"} + self.endpoint_url.format("invalid"), {"target_project_id": "2"}, + headers={'X-Test-Role': 'member'} ) def test_get_zone_share(self): @@ -75,7 +78,8 @@ class ApiV2SharedZonesTest(ApiV2TestCase): response = self.client.get( '{}/{}'.format(self.endpoint_url.format(self.zone.id), - shared_zone.json['id']) + shared_zone.json['id']), + headers={'X-Test-Role': 'member'} ) # Check the headers are what we expect @@ -98,7 +102,8 @@ class ApiV2SharedZonesTest(ApiV2TestCase): self.assertIn('updated_at', response.json) def test_list_zone_shares(self): - response = self.client.get(self.endpoint_url.format(self.zone.id)) + response = self.client.get(self.endpoint_url.format(self.zone.id), + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -114,7 +119,8 @@ class ApiV2SharedZonesTest(ApiV2TestCase): self._create_valid_shared_zone() - data = self.client.get(self.endpoint_url.format(self.zone.id)) + data = self.client.get(self.endpoint_url.format(self.zone.id), + headers={'X-Test-Role': 'member'}) self.assertEqual(1, len(data.json['shared_zones'])) @@ -123,7 +129,8 @@ class ApiV2SharedZonesTest(ApiV2TestCase): response = self.client.delete( '{}/{}'.format(self.endpoint_url.format(self.zone.id), - shared_zone.json['id']) + shared_zone.json['id']), + headers={'X-Test-Role': 'member'} ) # Check the headers are what we expect diff --git a/designate/tests/test_api/test_v2/test_zones.py b/designate/tests/test_api/test_v2/test_zones.py index 2718cbd65..7e39c944e 100644 --- a/designate/tests/test_api/test_v2/test_zones.py +++ b/designate/tests/test_api/test_v2/test_zones.py @@ -36,7 +36,8 @@ class ApiV2ZonesTest(ApiV2TestCase): def test_create_zone(self): # Create a zone fixture = self.get_zone_fixture(fixture=0) - response = self.client.post_json('/zones/', fixture) + response = self.client.post_json('/zones/', fixture, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) self.assertEqual('application/json', response.content_type) @@ -61,7 +62,8 @@ class ApiV2ZonesTest(ApiV2TestCase): fixture = self.get_zone_fixture(fixture=0) del fixture['type'] - response = self.client.post_json('/zones/', fixture) + response = self.client.post_json('/zones/', fixture, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) @@ -95,14 +97,16 @@ class ApiV2ZonesTest(ApiV2TestCase): body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_email_too_long(self): fixture = self.get_zone_fixture(fixture=0) fixture.update({'email': 'a' * 255 + '@abc.com'}) body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_invalid_email(self): invalid_emails = [ @@ -117,29 +121,32 @@ class ApiV2ZonesTest(ApiV2TestCase): for email in invalid_emails: fixture.update({'email': email}) body = fixture - self._assert_exception('invalid_object', 400, - self.client.post_json, - '/zones', body) + self._assert_exception( + 'invalid_object', 400, self.client.post_json, + '/zones', body, headers={'X-Test-Role': 'member'}) def test_create_zone_email_missing(self): fixture = self.get_zone_fixture(fixture=0) del fixture['email'] body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_ttl_less_than_zero(self): fixture = self.get_zone_fixture(fixture=0) fixture['ttl'] = -1 body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_ttl_is_zero(self): fixture = self.get_zone_fixture(fixture=0) fixture['ttl'] = 0 body = fixture - response = self.client.post_json('/zones', body) + response = self.client.post_json('/zones', body, + headers={'X-Test-Role': 'member'}) self.assertEqual(202, response.status_int) def test_create_zone_ttl_is_greater_than_max(self): @@ -147,19 +154,22 @@ class ApiV2ZonesTest(ApiV2TestCase): fixture['ttl'] = 2174483648 body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_ttl_is_invalid(self): fixture = self.get_zone_fixture(fixture=0) fixture['ttl'] = "!@?>" body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_ttl_is_not_required_field(self): fixture = self.get_zone_fixture(fixture=0) body = fixture - response = self.client.post_json('/zones', body) + response = self.client.post_json('/zones', body, + headers={'X-Test-Role': 'member'}) self.assertEqual(202, response.status_int) self.assertEqual('application/json', response.content_type) @@ -168,21 +178,24 @@ class ApiV2ZonesTest(ApiV2TestCase): fixture['description'] = "a" * 161 body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_name_is_missing(self): fixture = self.get_zone_fixture(fixture=0) del fixture['name'] body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_name_too_long(self): fixture = self.get_zone_fixture(fixture=0) fixture['name'] = 'x' * 255 + ".com" body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_body_validation(self): fixture = self.get_zone_fixture(fixture=0) @@ -191,7 +204,8 @@ class ApiV2ZonesTest(ApiV2TestCase): # Ensure it fails with a 400 body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) fixture = self.get_zone_fixture(fixture=0) # Add created_at to the body @@ -199,7 +213,8 @@ class ApiV2ZonesTest(ApiV2TestCase): # Ensure it fails with a 400 body = fixture self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', body) + '/zones', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_invalid_name(self): # Try to create a zone with an invalid name @@ -207,7 +222,8 @@ class ApiV2ZonesTest(ApiV2TestCase): # Ensure it fails with a 400 self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones', fixture) + '/zones', fixture, + headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'create_zone', side_effect=messaging.MessagingTimeout()) @@ -217,7 +233,8 @@ class ApiV2ZonesTest(ApiV2TestCase): body = fixture self._assert_exception('timeout', 504, self.client.post_json, - '/zones/', body) + '/zones/', body, + headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'create_zone', side_effect=exceptions.DuplicateZone()) @@ -227,30 +244,38 @@ class ApiV2ZonesTest(ApiV2TestCase): body = fixture self._assert_exception('duplicate_zone', 409, self.client.post_json, - '/zones/', body) + '/zones/', body, + headers={'X-Test-Role': 'member'}) def test_create_zone_missing_content_type(self): self._assert_exception('unsupported_content_type', 415, - self.client.post, '/zones') + self.client.post, '/zones', + headers={'X-Test-Role': 'member'}) def test_create_zone_bad_content_type(self): self._assert_exception( 'unsupported_content_type', 415, self.client.post, '/zones', - headers={'Content-type': 'test/goat'}) + headers={'Content-type': 'test/goat', + 'X-Test-Role': 'member'}) def test_zone_invalid_url(self): url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980/invalid' self._assert_exception('not_found', 404, self.client.get, url, - headers={'Accept': 'application/json'}) - self._assert_exception('not_found', 404, self.client.patch_json, url) - self._assert_exception('not_found', 404, self.client.delete, url) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) + self._assert_exception('not_found', 404, self.client.patch_json, url, + headers={'X-Test-Role': 'member'}) + self._assert_exception('not_found', 404, self.client.delete, url, + headers={'X-Test-Role': 'member'}) # Pecan returns a 405 for post - response = self.client.post(url, status=405) + response = self.client.post(url, status=405, + headers={'X-Test-Role': 'member'}) self.assertEqual(405, response.status_int) def test_get_zones(self): - response = self.client.get('/zones/') + response = self.client.get('/zones/', + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -276,14 +301,16 @@ class ApiV2ZonesTest(ApiV2TestCase): @patch.object(central_service.Service, 'find_zones', side_effect=messaging.MessagingTimeout()) def test_get_zones_timeout(self, _): - self._assert_exception('timeout', 504, self.client.get, '/zones/') + self._assert_exception('timeout', 504, self.client.get, '/zones/', + headers={'X-Test-Role': 'member'}) def test_get_zone(self): # Create a zone zone = self.create_zone() response = self.client.get('/zones/%s' % zone['id'], - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -302,26 +329,30 @@ class ApiV2ZonesTest(ApiV2TestCase): self.assertEqual(zone['email'], response.json['email']) def test_get_zone_invalid_id(self): - self._assert_invalid_uuid(self.client.get, '/zones/%s') + self._assert_invalid_uuid(self.client.get, '/zones/%s', + headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_zone', side_effect=messaging.MessagingTimeout()) def test_get_zone_timeout(self, _): url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980' self._assert_exception('timeout', 504, self.client.get, url, - headers={'Accept': 'application/json'}) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_zone', side_effect=exceptions.ZoneNotFound()) def test_get_zone_missing(self, _): url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980' self._assert_exception('zone_not_found', 404, self.client.get, url, - headers={'Accept': 'application/json'}) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) def test_get_zone_bad_accept(self): url = '/zones/6e2146f3-87bc-4f47-adc5-4df0a5c78218' - self.client.get(url, headers={'Accept': 'test/goat'}, status=406) + self.client.get(url, status=406, headers={'Accept': 'test/goat', + 'X-Test-Role': 'member'}) def test_update_zone(self): # Create a zone @@ -331,7 +362,8 @@ class ApiV2ZonesTest(ApiV2TestCase): body = {'email': 'prefix-%s' % zone['email']} response = self.client.patch_json('/zones/%s' % zone['id'], body, - status=202) + status=202, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) @@ -349,7 +381,8 @@ class ApiV2ZonesTest(ApiV2TestCase): response.json['email']) def test_update_zone_invalid_id(self): - self._assert_invalid_uuid(self.client.patch_json, '/zones/%s') + self._assert_invalid_uuid(self.client.patch_json, '/zones/%s', + headers={'X-Test-Role': 'member'}) def test_update_zone_validation(self): # NOTE: The schemas should be tested separatly to the API. So we @@ -365,7 +398,7 @@ class ApiV2ZonesTest(ApiV2TestCase): # Ensure it fails with a 400 self._assert_exception('invalid_object', 400, self.client.patch_json, - url, body) + url, body, headers={'X-Test-Role': 'member'}) # Prepare an update body with negative ttl in the body body = {'email': 'prefix-%s' % zone['email'], @@ -373,7 +406,7 @@ class ApiV2ZonesTest(ApiV2TestCase): # Ensure it fails with a 400 self._assert_exception('invalid_object', 400, self.client.patch_json, - url, body) + url, body, headers={'X-Test-Role': 'member'}) # Prepare an update body with ttl > maximum (2147483647) in the body body = {'email': 'prefix-%s' % zone['email'], @@ -381,7 +414,7 @@ class ApiV2ZonesTest(ApiV2TestCase): # Ensure it fails with a 400 self._assert_exception('invalid_object', 400, self.client.patch_json, - url, body) + url, body, headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_zone', side_effect=exceptions.DuplicateZone()) @@ -393,7 +426,7 @@ class ApiV2ZonesTest(ApiV2TestCase): # Ensure it fails with a 409 self._assert_exception('duplicate_zone', 409, self.client.patch_json, - url, body) + url, body, headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_zone', side_effect=messaging.MessagingTimeout()) @@ -405,7 +438,7 @@ class ApiV2ZonesTest(ApiV2TestCase): # Ensure it fails with a 504 self._assert_exception('timeout', 504, self.client.patch_json, - url, body) + url, body, headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'get_zone', side_effect=exceptions.ZoneNotFound()) @@ -417,12 +450,13 @@ class ApiV2ZonesTest(ApiV2TestCase): # Ensure it fails with a 404 self._assert_exception('zone_not_found', 404, self.client.patch_json, - url, body) + url, body, headers={'X-Test-Role': 'member'}) def test_delete_zone(self): zone = self.create_zone() - response = self.client.delete('/zones/%s' % zone['id'], status=202) + response = self.client.delete('/zones/%s' % zone['id'], status=202, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) @@ -431,18 +465,20 @@ class ApiV2ZonesTest(ApiV2TestCase): self.assertEqual('PENDING', response.json['status']) # The deleted zone should still be listed - zones = self.client.get('/zones/') + zones = self.client.get('/zones/', headers={'X-Test-Role': 'member'}) self.assertEqual(1, len(zones.json['zones'])) def test_delete_zone_invalid_id(self): - self._assert_invalid_uuid(self.client.delete, '/zones/%s') + self._assert_invalid_uuid(self.client.delete, '/zones/%s', + headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'delete_zone', side_effect=messaging.MessagingTimeout()) def test_delete_zone_timeout(self, _): url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980' - self._assert_exception('timeout', 504, self.client.delete, url) + self._assert_exception('timeout', 504, self.client.delete, url, + headers={'X-Test-Role': 'member'}) @patch.object(central_service.Service, 'delete_zone', side_effect=exceptions.ZoneNotFound()) @@ -450,42 +486,48 @@ class ApiV2ZonesTest(ApiV2TestCase): url = '/zones/2fdadfb1-cf96-4259-ac6b-bb7b6d2ff980' self._assert_exception('zone_not_found', 404, self.client.delete, - url) + url, headers={'X-Test-Role': 'member'}) def test_post_abandon_zone(self): zone = self.create_zone() url = '/zones/%s/tasks/abandon' % zone.id # Ensure that we get permission denied - self._assert_exception('forbidden', 403, self.client.post_json, url) + self._assert_exception('forbidden', 403, self.client.post_json, url, + headers={'X-Test-Role': 'member'}) # Ensure that abandon zone succeeds with the right policy self.policy({'abandon_zone': '@'}) - response = self.client.post_json(url) + response = self.client.post_json(url, + headers={'X-Test-Role': 'member'}) self.assertEqual(204, response.status_int) def test_get_abandon_zone(self): zone = self.create_zone() url = '/zones/%s/tasks/abandon' % zone.id - self._assert_exception('method_not_allowed', 405, self.client.get, url) + self._assert_exception('method_not_allowed', 405, self.client.get, url, + headers={'X-Test-Role': 'member'}) def test_get_invalid_abandon(self): # This is an invalid endpoint - should return 404 url = '/zones/tasks/abandon' - self._assert_exception('not_found', 404, self.client.get, url) + self._assert_exception('not_found', 404, self.client.get, url, + headers={'X-Test-Role': 'member'}) def test_get_zone_tasks(self): # This is an invalid endpoint - should return 404 zone = self.create_zone() url = '/zones/%s/tasks' % zone.id - self._assert_exception('not_found', 404, self.client.get, url) + self._assert_exception('not_found', 404, self.client.get, url, + headers={'X-Test-Role': 'member'}) def test_create_secondary(self): # Create a zone fixture = self.get_zone_fixture('SECONDARY', 0) fixture['masters'] = ["10.0.0.1"] - response = self.client.post_json('/zones/', fixture) + response = self.client.post_json('/zones/', fixture, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) @@ -516,7 +558,8 @@ class ApiV2ZonesTest(ApiV2TestCase): fixture = self.get_zone_fixture('SECONDARY', 0) self._assert_exception('invalid_object', 400, self.client.post_json, - '/zones/', fixture) + '/zones/', fixture, + headers={'X-Test-Role': 'member'}) def test_update_secondary(self): # Create a zone @@ -538,8 +581,9 @@ class ApiV2ZonesTest(ApiV2TestCase): # Prepare an update body body = {'masters': masters} - response = self.client.patch_json('/zones/%s' % zone['id'], body, - status=202) + response = self.client.patch_json( + '/zones/%s' % zone['id'], body, status=202, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(202, response.status_int) @@ -573,7 +617,7 @@ class ApiV2ZonesTest(ApiV2TestCase): response = self.client.post_json( '/zones/%s/tasks/xfr' % zone['id'], - None, status=202) + None, status=202, headers={'X-Test-Role': 'member'}) self.assertTrue(worker.perform_zone_xfr.called) @@ -588,7 +632,7 @@ class ApiV2ZonesTest(ApiV2TestCase): response = self.client.post_json( '/zones/%s/tasks/xfr' % zone['id'], - None, status=400) + None, status=400, headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(400, response.status_int) @@ -605,27 +649,32 @@ class ApiV2ZonesTest(ApiV2TestCase): body = {'email': 'foo@bar.io'} self._assert_exception('invalid_object', 400, self.client.patch_json, - '/zones/%s' % zone['id'], body) + '/zones/%s' % zone['id'], body, + headers={'X-Test-Role': 'member'}) # Metadata tests def test_metadata_exists(self): - response = self.client.get('/zones/') + response = self.client.get('/zones/', + headers={'X-Test-Role': 'member'}) # Make sure the fields exist self.assertIn('metadata', response.json) self.assertIn('total_count', response.json['metadata']) def test_total_count(self): - response = self.client.get('/zones/') + response = self.client.get('/zones/', + headers={'X-Test-Role': 'member'}) # There are no zones by default self.assertEqual(0, response.json['metadata']['total_count']) # Create a zone fixture = self.get_zone_fixture(fixture=0) - response = self.client.post_json('/zones/', fixture) + response = self.client.post_json('/zones/', fixture, + headers={'X-Test-Role': 'member'}) - response = self.client.get('/zones/') + response = self.client.get('/zones/', + headers={'X-Test-Role': 'member'}) # Make sure total_count picked it up self.assertEqual(1, response.json['metadata']['total_count']) @@ -633,13 +682,16 @@ class ApiV2ZonesTest(ApiV2TestCase): def test_total_count_pagination(self): # Create two zones fixture = self.get_zone_fixture(fixture=0) - response = self.client.post_json('/zones/', fixture) + response = self.client.post_json('/zones/', fixture, + headers={'X-Test-Role': 'member'}) fixture = self.get_zone_fixture(fixture=1) - response = self.client.post_json('/zones/', fixture) + response = self.client.post_json('/zones/', fixture, + headers={'X-Test-Role': 'member'}) # Paginate so that there is only one zone returned - response = self.client.get('/zones?limit=1') + response = self.client.get('/zones?limit=1', + headers={'X-Test-Role': 'member'}) self.assertEqual(1, len(response.json['zones'])) @@ -653,9 +705,11 @@ class ApiV2ZonesTest(ApiV2TestCase): # Prepare an update body body = {'zone': {'email': 'prefix-%s' % zone['email']}} - self.client.delete('/zones/%s' % zone['id'], status=202) + self.client.delete('/zones/%s' % zone['id'], status=202, + headers={'X-Test-Role': 'member'}) self._assert_exception('bad_request', 400, self.client.patch_json, - '/zones/%s' % zone['id'], body) + '/zones/%s' % zone['id'], body, + headers={'X-Test-Role': 'member'}) def test_get_nameservers(self): # Create a zone @@ -664,7 +718,8 @@ class ApiV2ZonesTest(ApiV2TestCase): # Prepare an update body response = self.client.get('/zones/%s/nameservers' % zone['id'], - headers=[('Accept', 'application/json')]) + headers={'Accept': 'application/json', + 'X-Test-Role': 'member'}) self.assertIn('nameservers', response.json) self.assertEqual(1, len(response.json['nameservers'])) @@ -689,7 +744,8 @@ class ApiV2ZonesTest(ApiV2TestCase): ] for fixture in fixtures: - response = self.client.post_json('/zones/', fixture) + response = self.client.post_json('/zones/', fixture, + headers={'X-Test-Role': 'member'}) get_urls = [ # Filter by Type @@ -714,7 +770,8 @@ class ApiV2ZonesTest(ApiV2TestCase): for get_url, correct_result in zip(get_urls, correct_results): - response = self.client.get(get_url) + response = self.client.get(get_url, + headers={'X-Test-Role': 'member'}) # Check the headers are what we expect self.assertEqual(200, response.status_int) @@ -726,4 +783,5 @@ class ApiV2ZonesTest(ApiV2TestCase): def test_invalid_zones_filter(self): invalid_url = '/zones?id=155477ef-e6c5-4b94-984d-8fc68c0c1a14' self._assert_exception( - 'bad_request', 400, self.client.get, invalid_url) + 'bad_request', 400, self.client.get, invalid_url, + headers={'X-Test-Role': 'member'}) diff --git a/designate/tests/test_central/test_service.py b/designate/tests/test_central/test_service.py index 641bac7b0..846684fa5 100644 --- a/designate/tests/test_central/test_service.py +++ b/designate/tests/test_central/test_service.py @@ -424,8 +424,10 @@ class CentralServiceTest(CentralTestCase): admin_context = self.get_admin_context() admin_context.all_tenants = True - tenant_one_context = self.get_context(project_id='1') - tenant_two_context = self.get_context(project_id='2') + tenant_one_context = self.get_context(project_id='1', + roles=['member', 'reader']) + tenant_two_context = self.get_context(project_id='2', + roles=['member', 'reader']) # in the beginning, there should be nothing tenants = self.central_service.count_tenants(admin_context) @@ -799,8 +801,10 @@ class CentralServiceTest(CentralTestCase): admin_context = self.get_admin_context() admin_context.all_tenants = True - tenant_one_context = self.get_context(project_id='1') - tenant_two_context = self.get_context(project_id='2') + tenant_one_context = self.get_context(project_id='1', + roles=['member', 'reader']) + tenant_two_context = self.get_context(project_id='2', + roles=['member', 'reader']) # Ensure we have no zones to start with. zones = self.central_service.find_zones(admin_context) @@ -1776,7 +1780,7 @@ class CentralServiceTest(CentralTestCase): def test_find_recordsets_shared_zone(self): zone = self.create_zone() - context = self.get_context(project_id='1') + context = self.get_context(project_id='1', roles=['member', 'reader']) self.share_zone(context=self.admin_context, zone_id=zone.id, target_project_id='1') @@ -2064,7 +2068,7 @@ class CentralServiceTest(CentralTestCase): zone = self.create_zone() original_serial = zone.serial - context = self.get_context(project_id='1') + context = self.get_context(project_id='1', roles=['member', 'reader']) self.share_zone(context=self.admin_context, zone_id=zone.id, target_project_id='1') @@ -3312,9 +3316,12 @@ class CentralServiceTest(CentralTestCase): self.assertEqual(zt_request.key, retrived_zt.key) def test_get_zone_transfer_request_scoped(self): - tenant_1_context = self.get_context(project_id='1') - tenant_2_context = self.get_context(project_id='2') - tenant_3_context = self.get_context(project_id='3') + tenant_1_context = self.get_context(project_id='1', + roles=['member', 'reader']) + tenant_2_context = self.get_context(project_id='2', + roles=['member', 'reader']) + tenant_3_context = self.get_context(project_id='3', + roles=['member', 'reader']) zone = self.create_zone(context=tenant_1_context) zt_request = self.create_zone_transfer_request( zone, @@ -3363,8 +3370,10 @@ class CentralServiceTest(CentralTestCase): exc.exc_info[0]) def test_create_zone_transfer_accept(self): - tenant_1_context = self.get_context(project_id='1') - tenant_2_context = self.get_context(project_id="2") + tenant_1_context = self.get_context(project_id='1', + roles=['member', 'reader']) + tenant_2_context = self.get_context(project_id="2", + roles=['member', 'reader']) admin_context = self.get_admin_context() admin_context.all_tenants = True @@ -3413,8 +3422,10 @@ class CentralServiceTest(CentralTestCase): 'COMPLETE', result['zt_request'].status) def test_create_zone_transfer_accept_scoped(self): - tenant_1_context = self.get_context(project_id='1') - tenant_2_context = self.get_context(project_id="2") + tenant_1_context = self.get_context(project_id='1', + roles=['member', 'reader']) + tenant_2_context = self.get_context(project_id="2", + roles=['member', 'reader']) admin_context = self.get_admin_context() admin_context.all_tenants = True @@ -3465,7 +3476,8 @@ class CentralServiceTest(CentralTestCase): 'COMPLETE', result['zt_request'].status) def test_create_zone_transfer_accept_failed_key(self): - tenant_1_context = self.get_context(project_id='1') + tenant_1_context = self.get_context(project_id='1', + roles=['member', 'reader']) tenant_2_context = self.get_context(project_id="2") admin_context = self.get_admin_context() admin_context.all_tenants = True @@ -3492,8 +3504,10 @@ class CentralServiceTest(CentralTestCase): self.assertEqual(exceptions.IncorrectZoneTransferKey, exc.exc_info[0]) def test_create_zone_tarnsfer_accept_out_of_tenant_scope(self): - tenant_1_context = self.get_context(project_id='1') - tenant_3_context = self.get_context(project_id="3") + tenant_1_context = self.get_context(project_id='1', + roles=['member', 'reader']) + tenant_3_context = self.get_context(project_id="3", + roles=['member', 'reader']) admin_context = self.get_admin_context() admin_context.all_tenants = True @@ -3522,7 +3536,8 @@ class CentralServiceTest(CentralTestCase): # Zone Import Tests def test_create_zone_import(self): # Create a Zone Import - context = self.get_context(project_id=utils.generate_uuid()) + context = self.get_context(project_id=utils.generate_uuid(), + roles=['member', 'reader']) request_body = self.get_zonefile_fixture() zone_import = self.central_service.create_zone_import(context, request_body) @@ -3536,14 +3551,16 @@ class CentralServiceTest(CentralTestCase): self.wait_for_import(zone_import.id) def test_create_zone_import_duplicate_threading(self): - context = self.get_context(project_id=utils.generate_uuid()) + context = self.get_context(project_id=utils.generate_uuid(), + roles=['member', 'reader']) request_body = self.get_zonefile_fixture() zone_import = self.central_service.create_zone_import(context, request_body) self.wait_for_import(zone_import.id) def create_zone_import(): - context = self.get_context(project_id=utils.generate_uuid()) + context = self.get_context(project_id=utils.generate_uuid(), + roles=['member', 'reader']) request_body = self.get_zonefile_fixture() zone_import = self.central_service.create_zone_import(context, request_body) @@ -3653,7 +3670,8 @@ class CentralServiceTest(CentralTestCase): ) # Create a Zone Import - context = self.get_context(project_id=utils.generate_uuid()) + context = self.get_context(project_id=utils.generate_uuid(), + roles=['member', 'reader']) request_body = self.get_zonefile_fixture() zone_import = self.central_service.create_zone_import(context, request_body) @@ -3671,7 +3689,8 @@ class CentralServiceTest(CentralTestCase): self.assertEqual('ERROR', zone_import.status) def test_find_zone_imports(self): - context = self.get_context(project_id=utils.generate_uuid()) + context = self.get_context(project_id=utils.generate_uuid(), + roles=['member', 'reader']) # Ensure we have no zone_imports to start with. zone_imports = self.central_service.find_zone_imports( @@ -3708,7 +3727,8 @@ class CentralServiceTest(CentralTestCase): def test_get_zone_import(self): # Create a Zone Import - context = self.get_context(project_id=utils.generate_uuid()) + context = self.get_context(project_id=utils.generate_uuid(), + roles=['member', 'reader']) request_body = self.get_zonefile_fixture() zone_import = self.central_service.create_zone_import( context, request_body) @@ -3726,7 +3746,8 @@ class CentralServiceTest(CentralTestCase): def test_update_zone_import(self): # Create a Zone Import - context = self.get_context(project_id=utils.generate_uuid()) + context = self.get_context(project_id=utils.generate_uuid(), + roles=['member', 'reader']) request_body = self.get_zonefile_fixture() zone_import = self.central_service.create_zone_import( context, request_body) @@ -3749,7 +3770,8 @@ class CentralServiceTest(CentralTestCase): def test_delete_zone_import(self): # Create a Zone Import - context = self.get_context(project_id=utils.generate_uuid()) + context = self.get_context(project_id=utils.generate_uuid(), + roles=['member', 'reader']) request_body = self.get_zonefile_fixture() zone_import = self.central_service.create_zone_import( context, request_body) @@ -3769,7 +3791,7 @@ class CentralServiceTest(CentralTestCase): def test_share_zone(self): # Create a Shared Zone - context = self.get_context(project_id='1') + context = self.get_context(project_id='1', roles=['member', 'reader']) zone = self.create_zone(context=context) shared_zone = self.share_zone(context=context, zone_id=zone.id) @@ -3796,7 +3818,7 @@ class CentralServiceTest(CentralTestCase): self.assertEqual(zone.id, shared_zone.zone_id) def test_unshare_zone(self): - context = self.get_context(project_id='1') + context = self.get_context(project_id='1', roles=['member', 'reader']) zone = self.create_zone(context=context) shared_zone = self.share_zone(context=context, zone_id=zone.id) @@ -3831,7 +3853,7 @@ class CentralServiceTest(CentralTestCase): new_shared_zone_obj.project_id) def test_unshare_zone_with_child_objects(self): - context = self.get_context(project_id='1') + context = self.get_context(project_id='1', roles=['member', 'reader']) zone = self.create_zone(context=context) shared_zone = self.share_zone(context=context, zone_id=zone.id) @@ -3855,7 +3877,7 @@ class CentralServiceTest(CentralTestCase): ) def test_find_shared_zones(self): - context = self.get_context(project_id='1') + context = self.get_context(project_id='1', roles=['member', 'reader']) zone = self.create_zone(context=context) # Ensure we have no shared zones to start with. @@ -3923,7 +3945,7 @@ class CentralServiceTest(CentralTestCase): self.assertEqual(second_shared_zone.id, shared_zones[1].id) def test_get_shared_zone(self): - context = self.get_context(project_id='1') + context = self.get_context(project_id='1', roles=['member', 'reader']) zone = self.create_zone(context=context) shared_zone = self.share_zone(context=context, zone_id=zone.id) diff --git a/designate/tests/test_storage/__init__.py b/designate/tests/test_storage/__init__.py index 7aa2a79ae..6f2dc7f0c 100644 --- a/designate/tests/test_storage/__init__.py +++ b/designate/tests/test_storage/__init__.py @@ -2982,8 +2982,10 @@ class StorageTestCase(object): self.assertEqual(result.id, accept.id) def test_transfer_zone_ownership(self): - tenant_1_context = self.get_context(project_id='1') - tenant_2_context = self.get_context(project_id='2') + tenant_1_context = self.get_context(project_id='1', + roles=['member', 'reader']) + tenant_2_context = self.get_context(project_id='2', + roles=['member', 'reader']) admin_context = self.get_admin_context() admin_context.all_tenants = True