Fix support for scoped tokens and default roles
This patch is the base patch to enable support for Keystone scoped tokens[1] and default roles[2] in the Designate API. It also migrates to using project_id in the context objects instead of the deprecated tenant_id. [1] https://docs.openstack.org/keystone/latest/admin/tokens-overview.html#authorization-scopes [2] https://docs.openstack.org/keystone/latest/admin/service-api-protection.html Depends-On: https://review.opendev.org/c/openstack/designate-tempest-plugin/+/821632 Change-Id: I43bb76dc4dc1d167d86fd5ea139a50f95f3b0b4a
This commit is contained in:
parent
aa798fc006
commit
5f87d207b4
20
.zuul.yaml
20
.zuul.yaml
@ -54,6 +54,24 @@
|
||||
Functional testing for a FIPS enabled Centos 8 stream system
|
||||
pre-run: playbooks/enable-fips.yaml
|
||||
|
||||
- job:
|
||||
name: designate-bind9-scoped-tokens
|
||||
post-run: playbooks/designate-bind9/post.yaml
|
||||
parent: designate-base
|
||||
vars:
|
||||
devstack_local_conf:
|
||||
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
|
||||
|
||||
- job:
|
||||
name: designate-pdns4
|
||||
post-run: playbooks/designate-pdns4/post.yaml
|
||||
@ -136,6 +154,7 @@
|
||||
- designate-bind9
|
||||
- designate-bind9-centos8stream-fips:
|
||||
voting: false
|
||||
- designate-bind9-scoped-tokens
|
||||
- designate-pdns4
|
||||
- designate-grenade-pdns4
|
||||
- designate-ipv6-only-pdns4
|
||||
@ -145,6 +164,7 @@
|
||||
queue: designate
|
||||
jobs:
|
||||
- designate-bind9
|
||||
- designate-bind9-scoped-tokens
|
||||
- designate-pdns4
|
||||
- designate-grenade-pdns4
|
||||
- designate-ipv6-only-pdns4
|
||||
|
@ -128,14 +128,13 @@ class KeystoneContextMiddleware(ContextMiddleware):
|
||||
pass
|
||||
|
||||
tenant_id = headers.get('X-Tenant-ID')
|
||||
if tenant_id is None:
|
||||
return flask.Response(status=401)
|
||||
|
||||
catalog = None
|
||||
if headers.get('X-Service-Catalog'):
|
||||
catalog = jsonutils.loads(headers.get('X-Service-Catalog'))
|
||||
|
||||
roles = headers.get('X-Roles').split(',')
|
||||
system_scope = headers.get('Openstack-System-Scope')
|
||||
|
||||
try:
|
||||
self.make_context(
|
||||
@ -144,7 +143,8 @@ class KeystoneContextMiddleware(ContextMiddleware):
|
||||
user_id=headers.get('X-User-ID'),
|
||||
project_id=tenant_id,
|
||||
roles=roles,
|
||||
service_catalog=catalog
|
||||
service_catalog=catalog,
|
||||
system_scope=system_scope
|
||||
)
|
||||
except exceptions.Forbidden:
|
||||
return flask.Response(status=403)
|
||||
|
@ -17,6 +17,7 @@ from oslo_log import log as logging
|
||||
import pecan
|
||||
|
||||
from designate.api.v2.controllers import rest
|
||||
from designate.common import constants
|
||||
from designate import exceptions
|
||||
from designate.objects.adapters import DesignateAdapter
|
||||
from designate import policy
|
||||
@ -31,7 +32,11 @@ class ZoneExportController(rest.RestController):
|
||||
@utils.validate_uuid('export_id')
|
||||
def get_all(self, export_id):
|
||||
context = pecan.request.environ['context']
|
||||
target = {'tenant_id': context.project_id}
|
||||
if policy.enforce_new_defaults():
|
||||
target = {constants.RBAC_PROJECT_ID: context.project_id}
|
||||
else:
|
||||
target = {'tenant_id': context.project_id}
|
||||
|
||||
policy.check('zone_export', context, target)
|
||||
|
||||
export = self.central_api.get_zone_export(context, export_id)
|
||||
|
File diff suppressed because it is too large
Load Diff
17
designate/common/constants.py
Normal file
17
designate/common/constants.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright 2021 Red Hat
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# RBAC related constants
|
||||
RBAC_PROJECT_ID = 'project_id'
|
||||
RBAC_TARGET_PROJECT_ID = 'target_project_id'
|
@ -12,17 +12,14 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from oslo_log import versionutils
|
||||
from oslo_policy import policy
|
||||
|
||||
|
||||
RULE_ADMIN_OR_OWNER = 'rule:admin_or_owner'
|
||||
RULE_ADMIN = 'rule:admin'
|
||||
RULE_ZONE_PRIMARY_OR_ADMIN = \
|
||||
"('PRIMARY':%(zone_type)s and rule:admin_or_owner) "\
|
||||
"OR ('SECONDARY':%(zone_type)s AND is_admin:True)"
|
||||
RULE_ZONE_TRANSFER = "rule:admin_or_owner OR tenant:%(target_tenant_id)s " \
|
||||
"OR None:%(target_tenant_id)s"
|
||||
DEPRECATED_REASON = """
|
||||
The designate API now supports system scope and default roles.
|
||||
"""
|
||||
|
||||
RULE_ANY = "@"
|
||||
|
||||
# Generic policy check string for system administrators. These are the people
|
||||
@ -59,37 +56,56 @@ SYSTEM_OR_PROJECT_READER = (
|
||||
'(' + SYSTEM_READER + ') or (' + PROJECT_READER + ')'
|
||||
)
|
||||
|
||||
# Designate specific "secure RBAC" rules
|
||||
ALL_TENANTS = 'True:%(all_tenants)s'
|
||||
|
||||
ALL_TENANTS_READER = ALL_TENANTS + ' and role:reader'
|
||||
|
||||
SYSTEM_OR_PROJECT_READER_OR_ALL_TENANTS_READER = (
|
||||
'(' + SYSTEM_READER + ') or (' + PROJECT_READER + ') or (' +
|
||||
ALL_TENANTS_READER + ')'
|
||||
)
|
||||
|
||||
RULE_ZONE_TRANSFER = (
|
||||
'(' + SYSTEM_ADMIN_OR_PROJECT_MEMBER + ') or '
|
||||
'project_id:%(target_project_id)s or '
|
||||
'None:%(target_project_id)s')
|
||||
|
||||
|
||||
# Deprecated in Wallaby as part of the "secure RBAC" work.
|
||||
# TODO(johnsom) remove when the deprecated RBAC rules are removed.
|
||||
RULE_ADMIN = 'rule:admin'
|
||||
RULE_ADMIN_OR_OWNER = 'rule:admin_or_owner'
|
||||
LEGACY_RULE_ZONE_TRANSFER = "rule:admin_or_owner OR " \
|
||||
"tenant:%(target_tenant_id)s " \
|
||||
"OR None:%(target_tenant_id)s"
|
||||
|
||||
deprecated_default = policy.DeprecatedRule(
|
||||
name="default",
|
||||
check_str=RULE_ADMIN_OR_OWNER,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
|
||||
rules = [
|
||||
# TODO(johnsom) remove when the deprecated RBAC rules are removed.
|
||||
policy.RuleDefault(
|
||||
name="admin",
|
||||
check_str="role:admin or is_admin:True"),
|
||||
policy.RuleDefault(
|
||||
name="primary_zone",
|
||||
check_str="target.zone_type:SECONDARY"),
|
||||
# TODO(johnsom) remove when the deprecated RBAC rules are removed.
|
||||
policy.RuleDefault(
|
||||
name="owner",
|
||||
check_str="tenant:%(tenant_id)s"),
|
||||
# TODO(johnsom) remove when the deprecated RBAC rules are removed.
|
||||
policy.RuleDefault(
|
||||
name="admin_or_owner",
|
||||
check_str="rule:admin or rule:owner"),
|
||||
|
||||
# Default policy
|
||||
policy.RuleDefault(
|
||||
name="default",
|
||||
check_str="rule:admin_or_owner"),
|
||||
policy.RuleDefault(
|
||||
name="target",
|
||||
check_str="tenant:%(target_tenant_id)s"),
|
||||
policy.RuleDefault(
|
||||
name="owner_or_target",
|
||||
check_str="rule:target or rule:owner"),
|
||||
policy.RuleDefault(
|
||||
name="admin_or_owner_or_target",
|
||||
check_str="rule:owner_or_target or rule:admin"),
|
||||
policy.RuleDefault(
|
||||
name="admin_or_target",
|
||||
check_str="rule:admin or rule:target"),
|
||||
policy.RuleDefault(
|
||||
name="zone_primary_or_admin",
|
||||
check_str=RULE_ZONE_PRIMARY_OR_ADMIN)
|
||||
check_str=SYSTEM_ADMIN_OR_PROJECT_MEMBER,
|
||||
deprecated_rule=deprecated_default),
|
||||
]
|
||||
|
||||
|
||||
|
@ -13,28 +13,62 @@
|
||||
# under the License.
|
||||
|
||||
|
||||
from oslo_log import versionutils
|
||||
from oslo_policy import policy
|
||||
|
||||
from designate.common.policies import base
|
||||
|
||||
|
||||
deprecated_all_tenants = policy.DeprecatedRule(
|
||||
name="all_tenants",
|
||||
check_str=base.RULE_ADMIN,
|
||||
deprecated_reason=base.DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_edit_managed_records = policy.DeprecatedRule(
|
||||
name="edit_managed_records",
|
||||
check_str=base.RULE_ADMIN,
|
||||
deprecated_reason=base.DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_use_low_ttl = policy.DeprecatedRule(
|
||||
name="use_low_ttl",
|
||||
check_str=base.RULE_ADMIN,
|
||||
deprecated_reason=base.DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_use_sudo = policy.DeprecatedRule(
|
||||
name="use_sudo",
|
||||
check_str=base.RULE_ADMIN,
|
||||
deprecated_reason=base.DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
|
||||
rules = [
|
||||
policy.RuleDefault(
|
||||
name="all_tenants",
|
||||
check_str=base.RULE_ADMIN,
|
||||
description='Action on all tenants.'),
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Action on all tenants.',
|
||||
deprecated_rule=deprecated_all_tenants),
|
||||
policy.RuleDefault(
|
||||
name="edit_managed_records",
|
||||
check_str=base.RULE_ADMIN,
|
||||
description='Edit managed records.'),
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Edit managed records.',
|
||||
deprecated_rule=deprecated_edit_managed_records),
|
||||
policy.RuleDefault(
|
||||
name="use_low_ttl",
|
||||
check_str=base.RULE_ADMIN,
|
||||
description='Use low TTL.'),
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Use low TTL.',
|
||||
deprecated_rule=deprecated_use_low_ttl),
|
||||
policy.RuleDefault(
|
||||
name="use_sudo",
|
||||
check_str=base.RULE_ADMIN,
|
||||
description='Accept sudo from user to tenant.')
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Accept sudo from user to tenant.',
|
||||
deprecated_rule=deprecated_use_sudo)
|
||||
]
|
||||
|
||||
|
||||
|
@ -12,29 +12,62 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from oslo_log import versionutils
|
||||
from oslo_policy import policy
|
||||
|
||||
from designate.common.policies import base
|
||||
|
||||
|
||||
deprecated_diagnostics_ping = policy.DeprecatedRule(
|
||||
name="diagnostics_ping",
|
||||
check_str=base.RULE_ADMIN,
|
||||
deprecated_reason=base.DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_diagnostics_sync_zones = policy.DeprecatedRule(
|
||||
name="diagnostics_sync_zones",
|
||||
check_str=base.RULE_ADMIN,
|
||||
deprecated_reason=base.DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_diagnostics_sync_zone = policy.DeprecatedRule(
|
||||
name="diagnostics_sync_zone",
|
||||
check_str=base.RULE_ADMIN,
|
||||
deprecated_reason=base.DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_diagnostics_sync_record = policy.DeprecatedRule(
|
||||
name="diagnostics_sync_record",
|
||||
check_str=base.RULE_ADMIN,
|
||||
deprecated_reason=base.DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
|
||||
rules = [
|
||||
policy.RuleDefault(
|
||||
name="diagnostics_ping",
|
||||
check_str=base.RULE_ADMIN,
|
||||
description='Diagnose ping.'),
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Diagnose ping.',
|
||||
deprecated_rule=deprecated_diagnostics_ping),
|
||||
policy.RuleDefault(
|
||||
name="diagnostics_sync_zones",
|
||||
check_str=base.RULE_ADMIN,
|
||||
description='Diagnose sync zones.'),
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Diagnose sync zones.',
|
||||
deprecated_rule=deprecated_diagnostics_sync_zones),
|
||||
policy.RuleDefault(
|
||||
name="diagnostics_sync_zone",
|
||||
check_str=base.RULE_ADMIN,
|
||||
description='Diagnose sync zone.'),
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Diagnose sync zone.',
|
||||
deprecated_rule=deprecated_diagnostics_sync_zone),
|
||||
policy.RuleDefault(
|
||||
name="diagnostics_sync_record",
|
||||
check_str=base.RULE_ADMIN,
|
||||
description='Diagnose sync record.')
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Diagnose sync record.',
|
||||
deprecated_rule=deprecated_diagnostics_sync_record)
|
||||
]
|
||||
|
||||
|
||||
|
@ -50,7 +50,7 @@ deprecated_reset_quotas = policy.DeprecatedRule(
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name="get_quotas",
|
||||
check_str=base.SYSTEM_OR_PROJECT_READER,
|
||||
check_str=base.SYSTEM_OR_PROJECT_READER_OR_ALL_TENANTS_READER,
|
||||
scope_types=['system', 'project'],
|
||||
description="View Current Project's Quotas.",
|
||||
operations=[
|
||||
|
@ -22,9 +22,15 @@ DEPRECATED_REASON = """
|
||||
The record set API now supports system scope and default roles.
|
||||
"""
|
||||
|
||||
# Deprecated in Wallaby as part of the "secure RBAC" work.
|
||||
# TODO(johnsom) remove when the deprecated RBAC rules are removed.
|
||||
RULE_ZONE_PRIMARY_OR_ADMIN = (
|
||||
"('PRIMARY':%(zone_type)s and rule:admin_or_owner) "
|
||||
"OR ('SECONDARY':%(zone_type)s AND is_admin:True)")
|
||||
|
||||
deprecated_create_recordset = policy.DeprecatedRule(
|
||||
name="create_recordset",
|
||||
check_str=base.RULE_ZONE_PRIMARY_OR_ADMIN,
|
||||
check_str=RULE_ZONE_PRIMARY_OR_ADMIN,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
@ -40,15 +46,27 @@ deprecated_get_recordset = policy.DeprecatedRule(
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_find_recordset = policy.DeprecatedRule(
|
||||
name="find_recordset",
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_find_recordsets = policy.DeprecatedRule(
|
||||
name="find_recordsets",
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_update_recordset = policy.DeprecatedRule(
|
||||
name="update_recordset",
|
||||
check_str=base.RULE_ZONE_PRIMARY_OR_ADMIN,
|
||||
check_str=RULE_ZONE_PRIMARY_OR_ADMIN,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_delete_recordset = policy.DeprecatedRule(
|
||||
name="delete_recordset",
|
||||
check_str=base.RULE_ZONE_PRIMARY_OR_ADMIN,
|
||||
check_str=RULE_ZONE_PRIMARY_OR_ADMIN,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
@ -69,7 +87,7 @@ SYSTEM_ADMIN_AND_SECONDARY_ZONE = (
|
||||
'(' + base.SYSTEM_ADMIN + ') and (\'SECONDARY\':%(zone_type)s)'
|
||||
)
|
||||
|
||||
SYSTEM_ADMIN_OR_PROJECT_MEMBER = ''.join(
|
||||
SYSTEM_ADMIN_OR_PROJECT_MEMBER_ZONE_TYPE = ' or '.join(
|
||||
[PROJECT_MEMBER_AND_PRIMARY_ZONE,
|
||||
SYSTEM_ADMIN_AND_PRIMARY_ZONE,
|
||||
SYSTEM_ADMIN_AND_SECONDARY_ZONE]
|
||||
@ -79,16 +97,13 @@ SYSTEM_ADMIN_OR_PROJECT_MEMBER = ''.join(
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name="create_recordset",
|
||||
check_str=SYSTEM_ADMIN_AND_SECONDARY_ZONE,
|
||||
check_str=SYSTEM_ADMIN_OR_PROJECT_MEMBER_ZONE_TYPE,
|
||||
scope_types=['system', 'project'],
|
||||
description="Create Recordset",
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/zones/{zone_id}/recordsets',
|
||||
'method': 'POST'
|
||||
}, {
|
||||
'path': '/v2/reverse/floatingips/{region}:{floatingip_id}',
|
||||
'method': 'PATCH'
|
||||
}
|
||||
],
|
||||
deprecated_rule=deprecated_create_recordset
|
||||
@ -108,35 +123,46 @@ rules = [
|
||||
{
|
||||
'path': '/v2/zones/{zone_id}/recordsets/{recordset_id}',
|
||||
'method': 'GET'
|
||||
}, {
|
||||
'path': '/v2/zones/{zone_id}/recordsets/{recordset_id}',
|
||||
'method': 'DELETE'
|
||||
}, {
|
||||
'path': '/v2/zones/{zone_id}/recordsets/{recordset_id}',
|
||||
'method': 'PUT'
|
||||
}
|
||||
],
|
||||
deprecated_rule=deprecated_get_recordset
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name="find_recordset",
|
||||
check_str=base.SYSTEM_OR_PROJECT_READER,
|
||||
scope_types=['system', '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'],
|
||||
description="List Recordsets in a Zone",
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/zones/{zone_id}/recordsets',
|
||||
'method': 'GET'
|
||||
},
|
||||
],
|
||||
deprecated_rule=deprecated_find_recordsets
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name="update_recordset",
|
||||
check_str=SYSTEM_ADMIN_AND_SECONDARY_ZONE,
|
||||
check_str=SYSTEM_ADMIN_OR_PROJECT_MEMBER_ZONE_TYPE,
|
||||
scope_types=['system', 'project'],
|
||||
description="Update recordset",
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/zones/{zone_id}/recordsets/{recordset_id}',
|
||||
'method': 'PUT'
|
||||
}, {
|
||||
'path': '/v2/reverse/floatingips/{region}:{floatingip_id}',
|
||||
'method': 'PATCH'
|
||||
}
|
||||
],
|
||||
deprecated_rule=deprecated_update_recordset
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name="delete_recordset",
|
||||
check_str=SYSTEM_ADMIN_AND_SECONDARY_ZONE,
|
||||
check_str=SYSTEM_ADMIN_OR_PROJECT_MEMBER_ZONE_TYPE,
|
||||
scope_types=['system', 'project'],
|
||||
description="Delete RecordSet",
|
||||
operations=[
|
||||
|
@ -88,9 +88,6 @@ rules = [
|
||||
description="Show a Tsigkey",
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/tsigkeys/{tsigkey_id}',
|
||||
'method': 'PATCH'
|
||||
}, {
|
||||
'path': '/v2/tsigkeys/{tsigkey_id}',
|
||||
'method': 'GET'
|
||||
}
|
||||
|
@ -46,6 +46,12 @@ deprecated_get_zone_servers = policy.DeprecatedRule(
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_get_zone_ns_records = policy.DeprecatedRule(
|
||||
name="get_zone_ns_records",
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_find_zones = policy.DeprecatedRule(
|
||||
name="find_zones",
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
@ -131,12 +137,6 @@ rules = [
|
||||
{
|
||||
'path': '/v2/zones/{zone_id}',
|
||||
'method': 'GET'
|
||||
}, {
|
||||
'path': '/v2/zones/{zone_id}',
|
||||
'method': 'PATCH'
|
||||
}, {
|
||||
'path': '/v2/zones/{zone_id}/recordsets/{recordset_id}',
|
||||
'method': 'PUT'
|
||||
}
|
||||
],
|
||||
deprecated_rule=deprecated_get_zone
|
||||
@ -147,6 +147,19 @@ rules = [
|
||||
scope_types=['system', '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'],
|
||||
description="Get the Name Servers for a Zone",
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/zones/{zone_id}/nameservers',
|
||||
'method': 'GET'
|
||||
}
|
||||
],
|
||||
deprecated_rule=deprecated_get_zone_ns_records
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name="find_zones",
|
||||
check_str=base.SYSTEM_OR_PROJECT_READER,
|
||||
|
@ -52,6 +52,12 @@ deprecated_update_zone_export = policy.DeprecatedRule(
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_delete_zone_export = policy.DeprecatedRule(
|
||||
name="delete_zone_export",
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
|
||||
|
||||
rules = [
|
||||
@ -103,9 +109,6 @@ rules = [
|
||||
{
|
||||
'path': '/v2/zones/tasks/exports/{zone_export_id}',
|
||||
'method': 'GET'
|
||||
}, {
|
||||
'path': '/v2/zones/tasks/exports/{zone_export_id}/export',
|
||||
'method': 'GET'
|
||||
}
|
||||
],
|
||||
deprecated_rule=deprecated_get_zone_export
|
||||
@ -122,7 +125,20 @@ rules = [
|
||||
}
|
||||
],
|
||||
deprecated_rule=deprecated_update_zone_export
|
||||
)
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name="delete_zone_export",
|
||||
check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER,
|
||||
scope_types=['system', 'project'],
|
||||
description="Delete a zone export",
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/zones/tasks/exports/{zone_export_id}',
|
||||
'method': 'DELETE'
|
||||
}
|
||||
],
|
||||
deprecated_rule=deprecated_delete_zone_export
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
@ -115,7 +115,7 @@ rules = [
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/zones/tasks/imports/{zone_import_id}',
|
||||
'method': 'GET'
|
||||
'method': 'DELETE'
|
||||
}
|
||||
],
|
||||
deprecated_rule=deprecated_delete_zone_import
|
||||
|
@ -24,7 +24,7 @@ The zone transfer accept API now supports system scope and default roles.
|
||||
|
||||
deprecated_create_zone_transfer_accept = policy.DeprecatedRule(
|
||||
name="create_zone_transfer_accept",
|
||||
check_str=base.RULE_ZONE_TRANSFER,
|
||||
check_str=base.LEGACY_RULE_ZONE_TRANSFER,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
@ -64,13 +64,15 @@ rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name="create_zone_transfer_accept",
|
||||
check_str=base.RULE_ZONE_TRANSFER,
|
||||
scope_types=['system', 'project'],
|
||||
description="Create Zone Transfer Accept",
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/zones/tasks/transfer_accepts',
|
||||
'method': 'POST'
|
||||
}
|
||||
]
|
||||
],
|
||||
deprecated_rule=deprecated_create_zone_transfer_accept
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name="get_zone_transfer_accept",
|
||||
|
@ -23,14 +23,14 @@ The zone transfer request API now supports system scope and default roles.
|
||||
"""
|
||||
|
||||
deprecated_create_zone_transfer_request = policy.DeprecatedRule(
|
||||
name="create_zone_transfer_request",
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
name="create_zone_transfer_request",
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_get_zone_transfer_request = policy.DeprecatedRule(
|
||||
name="get_zone_transfer_request",
|
||||
check_str=base.RULE_ZONE_TRANSFER,
|
||||
check_str=base.LEGACY_RULE_ZONE_TRANSFER,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
@ -40,12 +40,6 @@ deprecated_get_zone_transfer_request_detailed = policy.DeprecatedRule(
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_find_zone_transfer_requests = policy.DeprecatedRule(
|
||||
name="find_zone_transfer_requests",
|
||||
check_str=base.RULE_ANY,
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY
|
||||
)
|
||||
deprecated_update_zone_transfer_request = policy.DeprecatedRule(
|
||||
name="update_zone_transfer_request",
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
@ -77,16 +71,15 @@ rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name="get_zone_transfer_request",
|
||||
check_str=base.RULE_ZONE_TRANSFER,
|
||||
scope_types=['system', 'project'],
|
||||
description="Show a Zone Transfer Request",
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/zones/tasks/transfer_requests/{zone_transfer_request_id}', # noqa
|
||||
'method': 'GET'
|
||||
}, {
|
||||
'path': '/v2/zones/tasks/transfer_requests/{zone_transfer_request_id}', # noqa
|
||||
'method': 'PATCH'
|
||||
}
|
||||
]
|
||||
],
|
||||
deprecated_rule=deprecated_get_zone_transfer_request
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name="get_zone_transfer_request_detailed",
|
||||
@ -103,7 +96,7 @@ rules = [
|
||||
'path': '/v2/zones/tasks/transfer_requests',
|
||||
'method': 'GET'
|
||||
}
|
||||
]
|
||||
],
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name="find_zone_transfer_request",
|
||||
|
@ -107,6 +107,8 @@ class DesignateContext(context.RequestContext):
|
||||
|
||||
# NOTE(kiall): Ugly - required to match http://tinyurl.com/o3y8qmw
|
||||
context.roles.append('admin')
|
||||
if policy.enforce_new_defaults():
|
||||
context.system_scope = 'all'
|
||||
|
||||
if show_deleted is not None:
|
||||
context.show_deleted = show_deleted
|
||||
@ -132,7 +134,8 @@ class DesignateContext(context.RequestContext):
|
||||
def get_admin_context(cls, **kwargs):
|
||||
# TODO(kiall): Remove Me
|
||||
kwargs['is_admin'] = True
|
||||
kwargs['roles'] = ['admin']
|
||||
kwargs['roles'] = ['admin', 'reader']
|
||||
kwargs['system_scope'] = 'all'
|
||||
|
||||
return cls(None, **kwargs)
|
||||
|
||||
|
@ -256,6 +256,10 @@ class IncorrectZoneTransferKey(Forbidden):
|
||||
error_type = 'invalid_key'
|
||||
|
||||
|
||||
class InvalidTokenScope(Forbidden):
|
||||
error_type = 'invalid_token_scope'
|
||||
|
||||
|
||||
class Duplicate(DesignateException):
|
||||
expected = True
|
||||
error_code = 409
|
||||
@ -473,3 +477,12 @@ class LastServerDeleteNotAllowed(BadRequest):
|
||||
class ResourceNotFound(NotFound):
|
||||
# TODO(kiall): Should this be extending NotFound??
|
||||
pass
|
||||
|
||||
|
||||
class MissingProjectID(BadRequest):
|
||||
# Note: This should be 400, but is 401 for compatibility with
|
||||
# previous versions of the API.
|
||||
# https://github.com/openstack/designate/blob/stable/wallaby/ \
|
||||
# designate/api/middleware.py#L132
|
||||
error_code = 401
|
||||
error_type = 'missing_project_id'
|
||||
|
@ -11,6 +11,7 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from designate.common import constants
|
||||
from designate import exceptions
|
||||
from designate import objects
|
||||
from designate.objects.adapters.api_v2 import base
|
||||
@ -65,9 +66,10 @@ class ZoneTransferRequestAPIv2Adapter(base.APIv2Adapter):
|
||||
object, *args, **kwargs)
|
||||
|
||||
try:
|
||||
target = {
|
||||
'tenant_id': object.tenant_id,
|
||||
}
|
||||
if policy.enforce_new_defaults():
|
||||
target = {constants.RBAC_PROJECT_ID: object.tenant_id}
|
||||
else:
|
||||
target = {'tenant_id': object.tenant_id}
|
||||
|
||||
policy.check(
|
||||
'get_zone_transfer_request_detailed',
|
||||
|
@ -73,10 +73,17 @@ def init(default_rule=None, policy_file=None):
|
||||
|
||||
|
||||
def check(rule, ctxt, target=None, do_raise=True, exc=exceptions.Forbidden):
|
||||
creds = ctxt.to_dict()
|
||||
if enforce_new_defaults():
|
||||
creds = ctxt.to_policy_values()
|
||||
else:
|
||||
creds = ctxt.to_dict()
|
||||
target = target or {}
|
||||
try:
|
||||
result = _ENFORCER.enforce(rule, target, creds, do_raise, exc)
|
||||
except policy.InvalidScope:
|
||||
result = False
|
||||
if do_raise:
|
||||
raise exceptions.InvalidTokenScope
|
||||
except Exception:
|
||||
result = False
|
||||
raise
|
||||
@ -93,3 +100,9 @@ def check(rule, ctxt, target=None, do_raise=True, exc=exceptions.Forbidden):
|
||||
LOG.info("Policy check failed for rule '%(rule)s' "
|
||||
"on target %(target)s",
|
||||
{'rule': rule, 'target': repr(target)}, extra=extra)
|
||||
|
||||
|
||||
def enforce_new_defaults():
|
||||
if CONF.get('oslo_policy'):
|
||||
return CONF['oslo_policy'].get('enforce_new_defaults', False)
|
||||
return False
|
||||
|
@ -1488,6 +1488,12 @@ class SQLAlchemyStorage(sqlalchemy_base.SQLAlchemy, storage_base.Storage):
|
||||
).select_from(ljoin)
|
||||
|
||||
if not context.all_tenants:
|
||||
# If we have a system scoped token with no project_id and
|
||||
# all_tenants was not used, we don't know what records to return,
|
||||
# so return an empty list.
|
||||
if not context.project_id:
|
||||
return objects.ZoneTransferRequestList()
|
||||
|
||||
query = query.where(or_(
|
||||
table.c.tenant_id == context.project_id,
|
||||
table.c.target_tenant_id == context.project_id))
|
||||
@ -1498,7 +1504,8 @@ class SQLAlchemyStorage(sqlalchemy_base.SQLAlchemy, storage_base.Storage):
|
||||
exceptions.ZoneTransferRequestNotFound,
|
||||
criterion,
|
||||
one=one, marker=marker, limit=limit, sort_dir=sort_dir,
|
||||
sort_key=sort_key, query=query, apply_tenant_criteria=False
|
||||
sort_key=sort_key, query=query,
|
||||
apply_tenant_criteria=False
|
||||
)
|
||||
|
||||
def create_zone_transfer_request(self, context, zone_transfer_request):
|
||||
|
@ -387,6 +387,8 @@ class TestCase(base.BaseTestCase):
|
||||
self.central_service = self.start_service('central')
|
||||
|
||||
self.admin_context = self.get_admin_context()
|
||||
self.admin_context_all_tenants = self.get_admin_context(
|
||||
all_tenants=True)
|
||||
storage_driver = CONF['service:central'].storage_driver
|
||||
self.storage = storage.get_storage(storage_driver)
|
||||
|
||||
@ -436,10 +438,11 @@ class TestCase(base.BaseTestCase):
|
||||
def get_context(self, **kwargs):
|
||||
return DesignateContext(**kwargs)
|
||||
|
||||
def get_admin_context(self):
|
||||
def get_admin_context(self, **kwargs):
|
||||
return DesignateContext.get_admin_context(
|
||||
project_id=utils.generate_uuid(),
|
||||
user_id=utils.generate_uuid())
|
||||
user_id=utils.generate_uuid(),
|
||||
**kwargs)
|
||||
|
||||
# Fixture methods
|
||||
def get_quota_fixture(self, fixture=0, values=None):
|
||||
@ -794,7 +797,7 @@ class TestCase(base.BaseTestCase):
|
||||
|
||||
# Retrieve it, and ensure it's the same
|
||||
zone_import = self.central_service.get_zone_import(
|
||||
self.admin_context, zone_import_id)
|
||||
self.admin_context_all_tenants, zone_import_id)
|
||||
|
||||
# If the import is done, we're done
|
||||
if zone_import.status == 'COMPLETE':
|
||||
|
@ -102,7 +102,8 @@ class KeystoneContextMiddlewareTest(ApiTestCase):
|
||||
# Process the request
|
||||
response = app(request)
|
||||
|
||||
self.assertEqual(401, response.status_code)
|
||||
# Ensure request was not blocked
|
||||
self.assertEqual(response, 'FakeResponse')
|
||||
|
||||
|
||||
class NoAuthContextMiddlewareTest(ApiTestCase):
|
||||
|
@ -36,6 +36,7 @@ from designate import objects
|
||||
from designate.storage.impl_sqlalchemy import tables
|
||||
from designate.tests import fixtures
|
||||
from designate.tests.test_central import CentralTestCase
|
||||
from designate import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -3537,7 +3538,7 @@ class CentralServiceTest(CentralTestCase):
|
||||
# Zone Import Tests
|
||||
def test_create_zone_import(self):
|
||||
# Create a Zone Import
|
||||
context = self.get_context()
|
||||
context = self.get_context(project_id=utils.generate_uuid())
|
||||
request_body = self.get_zonefile_fixture()
|
||||
zone_import = self.central_service.create_zone_import(context,
|
||||
request_body)
|
||||
@ -3551,7 +3552,7 @@ class CentralServiceTest(CentralTestCase):
|
||||
self.wait_for_import(zone_import.id)
|
||||
|
||||
def test_find_zone_imports(self):
|
||||
context = self.get_context()
|
||||
context = self.get_context(project_id=utils.generate_uuid())
|
||||
|
||||
# Ensure we have no zone_imports to start with.
|
||||
zone_imports = self.central_service.find_zone_imports(
|
||||
@ -3568,7 +3569,7 @@ class CentralServiceTest(CentralTestCase):
|
||||
|
||||
# Ensure we can retrieve the newly created zone_import
|
||||
zone_imports = self.central_service.find_zone_imports(
|
||||
self.admin_context)
|
||||
self.admin_context_all_tenants)
|
||||
self.assertEqual(1, len(zone_imports))
|
||||
|
||||
# Create a second zone_import
|
||||
@ -3581,14 +3582,14 @@ class CentralServiceTest(CentralTestCase):
|
||||
|
||||
# Ensure we can retrieve both zone_imports
|
||||
zone_imports = self.central_service.find_zone_imports(
|
||||
self.admin_context)
|
||||
self.admin_context_all_tenants)
|
||||
self.assertEqual(2, len(zone_imports))
|
||||
self.assertEqual('COMPLETE', zone_imports[0].status)
|
||||
self.assertEqual('COMPLETE', zone_imports[1].status)
|
||||
|
||||
def test_get_zone_import(self):
|
||||
# Create a Zone Import
|
||||
context = self.get_context()
|
||||
context = self.get_context(project_id=utils.generate_uuid())
|
||||
request_body = self.get_zonefile_fixture()
|
||||
zone_import = self.central_service.create_zone_import(
|
||||
context, request_body)
|
||||
@ -3598,7 +3599,7 @@ class CentralServiceTest(CentralTestCase):
|
||||
|
||||
# Retrieve it, and ensure it's the same
|
||||
zone_import = self.central_service.get_zone_import(
|
||||
self.admin_context, zone_import.id)
|
||||
self.admin_context_all_tenants, zone_import.id)
|
||||
|
||||
self.assertEqual(zone_import.id, zone_import['id'])
|
||||
self.assertEqual(zone_import.status, zone_import['status'])
|
||||
@ -3606,7 +3607,7 @@ class CentralServiceTest(CentralTestCase):
|
||||
|
||||
def test_update_zone_import(self):
|
||||
# Create a Zone Import
|
||||
context = self.get_context()
|
||||
context = self.get_context(project_id=utils.generate_uuid())
|
||||
request_body = self.get_zonefile_fixture()
|
||||
zone_import = self.central_service.create_zone_import(
|
||||
context, request_body)
|
||||
@ -3618,7 +3619,7 @@ class CentralServiceTest(CentralTestCase):
|
||||
|
||||
# Perform the update
|
||||
zone_import = self.central_service.update_zone_import(
|
||||
self.admin_context, zone_import)
|
||||
self.admin_context_all_tenants, zone_import)
|
||||
|
||||
# Fetch the zone_import again
|
||||
zone_import = self.central_service.get_zone_import(context,
|
||||
@ -3629,7 +3630,7 @@ class CentralServiceTest(CentralTestCase):
|
||||
|
||||
def test_delete_zone_import(self):
|
||||
# Create a Zone Import
|
||||
context = self.get_context()
|
||||
context = self.get_context(project_id=utils.generate_uuid())
|
||||
request_body = self.get_zonefile_fixture()
|
||||
zone_import = self.central_service.create_zone_import(
|
||||
context, request_body)
|
||||
|
@ -256,6 +256,7 @@ class CentralBasic(TestCase):
|
||||
'set_rules',
|
||||
'init',
|
||||
'check',
|
||||
'enforce_new_defaults',
|
||||
])
|
||||
|
||||
designate.central.service.quota = mock.NonCallableMock(spec_set=[
|
||||
@ -932,7 +933,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
n, ctx, target = designate.central.service.policy.check.call_args[0]
|
||||
self.assertEqual(CentralZoneTestCase.zone__id, target['zone_id'])
|
||||
self.assertEqual('foo', target['zone_name'])
|
||||
self.assertEqual('2', target['tenant_id'])
|
||||
self.assertEqual('2', target['project_id'])
|
||||
|
||||
def test_get_zone_servers(self):
|
||||
self.service.storage.get_zone.return_value = RoObject(
|
||||
@ -995,6 +996,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
'set_rules',
|
||||
'init',
|
||||
'check',
|
||||
'enforce_new_defaults',
|
||||
])
|
||||
self.context.abandon = True
|
||||
self.service.storage.count_zones.return_value = 0
|
||||
@ -1187,7 +1189,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
'zone_id': CentralZoneTestCase.zone__id_2,
|
||||
'zone_name': 'example.org.',
|
||||
'recordset_id': CentralZoneTestCase.recordset__id,
|
||||
'tenant_id': '2'}, target)
|
||||
'project_id': '2'}, target)
|
||||
|
||||
def test_find_recordsets(self):
|
||||
self.context = mock.Mock()
|
||||
@ -1196,7 +1198,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
self.assertTrue(self.service.storage.find_recordsets.called)
|
||||
n, ctx, target = designate.central.service.policy.check.call_args[0]
|
||||
self.assertEqual('find_recordsets', n)
|
||||
self.assertEqual({'tenant_id': 't'}, target)
|
||||
self.assertEqual({'project_id': 't'}, target)
|
||||
|
||||
def test_find_recordset(self):
|
||||
self.context = mock.Mock()
|
||||
@ -1205,7 +1207,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
self.assertTrue(self.service.storage.find_recordset.called)
|
||||
n, ctx, target = designate.central.service.policy.check.call_args[0]
|
||||
self.assertEqual('find_recordset', n)
|
||||
self.assertEqual({'tenant_id': 't'}, target)
|
||||
self.assertEqual({'project_id': 't'}, target)
|
||||
|
||||
def test_update_recordset_fail_on_changes(self):
|
||||
self.service.storage.get_zone.return_value = RoObject()
|
||||
@ -1298,7 +1300,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
'zone_name': 'example.org.',
|
||||
'zone_type': 'foo',
|
||||
'recordset_id': '9c85d9b0-1e9d-4e99-aede-a06664f1af2e',
|
||||
'tenant_id': '2'}, target)
|
||||
'project_id': '2'}, target)
|
||||
|
||||
def test__update_recordset_in_storage(self):
|
||||
recordset = mock.Mock()
|
||||
@ -1532,7 +1534,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
self.service.count_recordsets(self.context)
|
||||
n, ctx, target = designate.central.service.policy.check.call_args[0]
|
||||
self.assertEqual('count_recordsets', n)
|
||||
self.assertEqual({'tenant_id': None}, target)
|
||||
self.assertEqual({'project_id': None}, target)
|
||||
self.assertEqual(
|
||||
{},
|
||||
self.service.storage.count_recordsets.call_args[0][1]
|
||||
@ -1587,7 +1589,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
'zone_type': 'foo',
|
||||
'recordset_id': CentralZoneTestCase.recordset__id,
|
||||
'recordset_name': 'rs',
|
||||
'tenant_id': '2'}, target)
|
||||
'project_id': '2'}, target)
|
||||
|
||||
def test_create_record_worker(self):
|
||||
self._test_create_record()
|
||||
@ -1689,7 +1691,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
'record_id': CentralZoneTestCase.record__id,
|
||||
'recordset_id': CentralZoneTestCase.recordset__id_2,
|
||||
'recordset_name': 'foo',
|
||||
'tenant_id': 2}, target)
|
||||
'project_id': 2}, target)
|
||||
|
||||
def test_update_record_fail_on_changes(self):
|
||||
self.service.storage.get_zone.return_value = RoObject(
|
||||
@ -1789,7 +1791,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
'record_id': 'abc12a-1e9d-4e99-aede-a06664f1af2e',
|
||||
'recordset_id': 'abc12a-1e9d-4e99-aede-a06664f1af2e',
|
||||
'recordset_name': 'rsn',
|
||||
'tenant_id': 'tid'}, target)
|
||||
'project_id': 'tid'}, target)
|
||||
|
||||
def test__update_record_in_storage(self):
|
||||
self.service._update_zone_in_storage = mock.Mock()
|
||||
@ -1893,7 +1895,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
'record_id': CentralZoneTestCase.record__id_2,
|
||||
'recordset_id': CentralZoneTestCase.recordset__id_2,
|
||||
'recordset_name': 'rsn',
|
||||
'tenant_id': 'tid'}, target)
|
||||
'project_id': 'tid'}, target)
|
||||
|
||||
def test_delete_record_in_storage(self):
|
||||
self.service._delete_record_in_storage(
|
||||
@ -1911,7 +1913,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
self.service.count_records(self.context)
|
||||
t, ctx, target = designate.central.service.policy.check.call_args[0]
|
||||
self.assertEqual('count_records', t)
|
||||
self.assertEqual({'tenant_id': None}, target)
|
||||
self.assertEqual({'project_id': None}, target)
|
||||
|
||||
def test_sync_zones(self):
|
||||
self.service._sync_zone = mock.Mock()
|
||||
@ -1938,7 +1940,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
|
||||
t, ctx, target = designate.central.service.policy.check.call_args[0]
|
||||
self.assertEqual('diagnostics_sync_zone', t)
|
||||
self.assertEqual({'tenant_id': 'tid',
|
||||
self.assertEqual({'project_id': 'tid',
|
||||
'zone_id': CentralZoneTestCase.zone__id,
|
||||
'zone_name': 'n'}, target)
|
||||
|
||||
@ -1965,7 +1967,7 @@ class CentralZoneTestCase(CentralBasic):
|
||||
'record_id': CentralZoneTestCase.record__id,
|
||||
'recordset_id': CentralZoneTestCase.recordset__id,
|
||||
'recordset_name': 'n',
|
||||
'tenant_id': 'tid'}, target)
|
||||
'project_id': 'tid'}, target)
|
||||
|
||||
def test_ping(self):
|
||||
self.service.storage.ping.return_value = True
|
||||
@ -2118,7 +2120,7 @@ class CentralZoneExportTests(CentralBasic):
|
||||
n, ctx, target = designate.central.service.policy.check.call_args[0]
|
||||
|
||||
# Check arguments to policy
|
||||
self.assertEqual('t', target['tenant_id'])
|
||||
self.assertEqual('t', target['project_id'])
|
||||
|
||||
# Check output
|
||||
self.assertEqual(CentralZoneTestCase.zone__id, out.zone_id)
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support for keystone default roles and scoped tokens.
|
Loading…
Reference in New Issue
Block a user