Support enables rbac policies new defaults
The Magnum service allow enables policies (RBAC) new defaults and scope by default. The Default value of config options ``[oslo_policy] enforce_scope`` and ``[oslo_policy] oslo_policy.enforce_new_defaults`` are both to ``False``, but will change to ``True`` in following cycles. To enable them then modify the below config options value in ``magnum.conf`` file:: [oslo_policy] enforce_new_defaults=True enforce_scope=True reference tc goal for more detail: https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html Related blueprint secure-rbac Change-Id: I249942a355577c4f1ef51b3988f0cc4979959d0b
This commit is contained in:
parent
fda54620ad
commit
5971243169
@ -153,6 +153,14 @@ function create_magnum_conf {
|
||||
|
||||
iniset $MAGNUM_CONF oslo_policy policy_file $MAGNUM_POLICY
|
||||
|
||||
if [[ "$MAGNUM_ENFORCE_SCOPE" == True ]] ; then
|
||||
iniset $MAGNUM_CONF oslo_policy enforce_scope true
|
||||
iniset $MAGNUM_CONF oslo_policy enforce_new_defaults true
|
||||
else
|
||||
iniset $MAGNUM_CONF oslo_policy enforce_scope false
|
||||
iniset $MAGNUM_CONF oslo_policy enforce_new_defaults false
|
||||
fi
|
||||
|
||||
iniset $MAGNUM_CONF keystone_auth auth_type password
|
||||
iniset $MAGNUM_CONF keystone_auth username magnum
|
||||
iniset $MAGNUM_CONF keystone_auth password $SERVICE_PASSWORD
|
||||
|
@ -14,6 +14,10 @@
|
||||
# PHYSICAL_NETWORK=public
|
||||
# OVS_PHYSICAL_BRIDGE=br-ex
|
||||
|
||||
# This option controls whether or not to enforce scope when evaluating policies. Learn more:
|
||||
# https://docs.openstack.org/oslo.policy/latest/configuration/index.html#oslo_policy.enforce_scope
|
||||
MAGNUM_ENFORCE_SCOPE=$(trueorfalse False MAGNUM_ENFORCE_SCOPE)
|
||||
|
||||
# Enable Magnum services
|
||||
enable_service magnum-api
|
||||
enable_service magnum-cond
|
||||
|
@ -52,8 +52,8 @@ class ContextHook(hooks.PecanHook):
|
||||
user_id = headers.get('X-User-Id')
|
||||
project = headers.get('X-Project-Name')
|
||||
project_id = headers.get('X-Project-Id')
|
||||
domain_id = headers.get('X-User-Domain-Id')
|
||||
domain_name = headers.get('X-User-Domain-Name')
|
||||
user_domain_id = headers.get('X-User-Domain-Id')
|
||||
user_domain_name = headers.get('X-User-Domain-Name')
|
||||
auth_token = headers.get('X-Auth-Token')
|
||||
roles = headers.get('X-Roles', '').split(',')
|
||||
auth_token_info = state.request.environ.get('keystone.token_info')
|
||||
@ -72,8 +72,8 @@ class ContextHook(hooks.PecanHook):
|
||||
user_id=user_id,
|
||||
project_name=project,
|
||||
project_id=project_id,
|
||||
domain_id=domain_id,
|
||||
domain_name=domain_name,
|
||||
user_domain_id=user_domain_id,
|
||||
user_domain_name=user_domain_name,
|
||||
roles=roles)
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@ class RequestContext(context.RequestContext):
|
||||
"""
|
||||
super(RequestContext, self).__init__(auth_token=auth_token,
|
||||
user_id=user_name,
|
||||
project_id=project_name,
|
||||
project_id=project_id,
|
||||
is_admin=is_admin,
|
||||
read_only=read_only,
|
||||
show_deleted=show_deleted,
|
||||
@ -53,8 +53,6 @@ class RequestContext(context.RequestContext):
|
||||
self.user_id = user_id
|
||||
self.project_name = project_name
|
||||
self.project_id = project_id
|
||||
self.domain_id = domain_id
|
||||
self.domain_name = domain_name
|
||||
self.user_domain_id = user_domain_id
|
||||
self.user_domain_name = user_domain_name
|
||||
self.auth_url = auth_url
|
||||
@ -71,8 +69,6 @@ class RequestContext(context.RequestContext):
|
||||
value = super(RequestContext, self).to_dict()
|
||||
value.update({'auth_token': self.auth_token,
|
||||
'auth_url': self.auth_url,
|
||||
'domain_id': self.domain_id,
|
||||
'domain_name': self.domain_name,
|
||||
'user_domain_id': self.user_domain_id,
|
||||
'user_domain_name': self.user_domain_name,
|
||||
'user_name': self.user_name,
|
||||
|
@ -13,12 +13,79 @@
|
||||
# under the License.
|
||||
from oslo_policy import policy
|
||||
|
||||
ROLE_ADMIN = 'rule:context_is_admin'
|
||||
|
||||
RULE_ADMIN_OR_OWNER = 'rule:admin_or_owner'
|
||||
RULE_ADMIN_API = 'rule:admin_api'
|
||||
RULE_ADMIN_API = 'rule:context_is_admin'
|
||||
RULE_ADMIN_OR_USER = 'rule:admin_or_user'
|
||||
RULE_CLUSTER_USER = 'rule:cluster_user'
|
||||
RULE_DENY_CLUSTER_USER = 'rule:deny_cluster_user'
|
||||
RULE_USER = "rule:is_user"
|
||||
# Generic check string for checking if a user is authorized on a particular
|
||||
# project, specifically with the member role.
|
||||
RULE_PROJECT_MEMBER = 'rule:project_member'
|
||||
# Generic check string for checking if a user is authorized on a particular
|
||||
# project but with read-only access. For example, this persona would be able to
|
||||
# list private images owned by a project but cannot make any writeable changes
|
||||
# to those images.
|
||||
RULE_PROJECT_READER = 'rule:project_reader'
|
||||
|
||||
RULE_USER_OR_CLUSTER_USER = (
|
||||
'rule:user_or_cluster_user')
|
||||
RULE_ADMIN_OR_PROJECT_READER = (
|
||||
'rule:admin_or_project_reader')
|
||||
RULE_ADMIN_OR_PROJECT_MEMBER = (
|
||||
'rule:admin_or_project_member')
|
||||
RULE_ADMIN_OR_PROJECT_MEMBER_USER = (
|
||||
'rule:admin_or_project_member_user')
|
||||
RULE_ADMIN_OR_PROJECT_MEMBER_USER_OR_CLUSTER_USER = (
|
||||
'rule:admin_or_project_member_user_or_cluster_user')
|
||||
RULE_PROJECT_MEMBER_DENY_CLUSTER_USER = (
|
||||
'rule:project_member_deny_cluster_user')
|
||||
RULE_ADMIN_OR_PROJECT_MEMBER_DENY_CLUSTER_USER = (
|
||||
'rule:admin_or_project_member_deny_cluster_user')
|
||||
RULE_PROJECT_READER_DENY_CLUSTER_USER = (
|
||||
'rule:project_reader_deny_cluster_user')
|
||||
RULE_ADMIN_OR_PROJECT_READER_DENY_CLUSTER_USER = (
|
||||
'rule:admin_or_project_reader_deny_cluster_user')
|
||||
RULE_ADMIN_OR_PROJECT_READER_USER_OR_CLUSTER_USER = (
|
||||
'rule:admin_or_project_reader_user_or_cluster_user')
|
||||
|
||||
# ==========================================================
|
||||
# Deprecated Since OpenStack 2023.2(Magnum 17.0.0) and should be removed in
|
||||
# The following cycle.
|
||||
|
||||
DEPRECATED_REASON = """
|
||||
The Magnum API now enforces scoped tokens and default reader and member roles.
|
||||
"""
|
||||
|
||||
DEPRECATED_SINCE = 'OpenStack 2023.2(Magnum 17.0.0)'
|
||||
|
||||
|
||||
DEPRECATED_DENY_CLUSTER_USER = policy.DeprecatedRule(
|
||||
name=RULE_DENY_CLUSTER_USER,
|
||||
check_str='not domain_id:%(trustee_domain_id)s',
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=DEPRECATED_SINCE
|
||||
)
|
||||
|
||||
DEPRECATED_RULE_ADMIN_OR_OWNER = policy.DeprecatedRule(
|
||||
name=RULE_ADMIN_OR_OWNER,
|
||||
check_str='is_admin:True or project_id:%(project_id)s',
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=DEPRECATED_SINCE
|
||||
)
|
||||
|
||||
# Only used for DEPRECATED_RULE_ADMIN_OR_USER_OR_CLUSTER_USER
|
||||
RULE_ADMIN_OR_USER_OR_CLUSTER_USER = (
|
||||
'rule:admin_or_user_or_cluster_user')
|
||||
|
||||
DEPRECATED_RULE_ADMIN_OR_USER_OR_CLUSTER_USER = policy.DeprecatedRule(
|
||||
name=RULE_ADMIN_OR_USER_OR_CLUSTER_USER,
|
||||
check_str=f"(({RULE_ADMIN_API}) or ({RULE_USER_OR_CLUSTER_USER}))",
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=DEPRECATED_SINCE
|
||||
)
|
||||
# ==========================================================
|
||||
|
||||
rules = [
|
||||
policy.RuleDefault(
|
||||
@ -29,14 +96,14 @@ rules = [
|
||||
name='admin_or_owner',
|
||||
check_str='is_admin:True or project_id:%(project_id)s'
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_api',
|
||||
check_str='rule:context_is_admin'
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_user',
|
||||
check_str='is_admin:True or user_id:%(user_id)s'
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='is_user',
|
||||
check_str='user_id:%(user_id)s'
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='cluster_user',
|
||||
check_str='user_id:%(trustee_user_id)s'
|
||||
@ -44,7 +111,93 @@ rules = [
|
||||
policy.RuleDefault(
|
||||
name='deny_cluster_user',
|
||||
check_str='not domain_id:%(trustee_domain_id)s'
|
||||
)
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='project_member',
|
||||
check_str='role:member and project_id:%(project_id)s'
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='project_reader',
|
||||
check_str='role:reader and project_id:%(project_id)s'
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_project_reader',
|
||||
check_str=f"({RULE_ADMIN_API}) or ({RULE_PROJECT_READER})",
|
||||
deprecated_rule=DEPRECATED_RULE_ADMIN_OR_OWNER
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_project_member',
|
||||
check_str=f"({RULE_ADMIN_API}) or ({RULE_PROJECT_MEMBER})",
|
||||
deprecated_rule=DEPRECATED_RULE_ADMIN_OR_OWNER
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_project_member_user',
|
||||
check_str=(
|
||||
f"({RULE_ADMIN_API}) or (({RULE_PROJECT_MEMBER}) and "
|
||||
f"({RULE_USER}))"
|
||||
)
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='user_or_cluster_user',
|
||||
check_str=(
|
||||
f"(({RULE_USER}) or ({RULE_CLUSTER_USER}))"
|
||||
)
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_user_or_cluster_user',
|
||||
check_str=(
|
||||
f"(({RULE_ADMIN_API}) or ({RULE_USER_OR_CLUSTER_USER}))"
|
||||
)
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_project_member_cluster_user',
|
||||
check_str=(
|
||||
f"({RULE_ADMIN_API}) or (({RULE_PROJECT_MEMBER}) "
|
||||
f"and ({RULE_CLUSTER_USER}))"
|
||||
)
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_project_member_user_or_cluster_user',
|
||||
check_str=(
|
||||
f"({RULE_ADMIN_API}) or (({RULE_PROJECT_MEMBER}) and "
|
||||
f"({RULE_USER_OR_CLUSTER_USER}))"
|
||||
),
|
||||
deprecated_rule=DEPRECATED_RULE_ADMIN_OR_USER_OR_CLUSTER_USER
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='project_member_deny_cluster_user',
|
||||
check_str=(
|
||||
f"(({RULE_PROJECT_MEMBER}) and ({RULE_DENY_CLUSTER_USER}))"
|
||||
),
|
||||
deprecated_rule=DEPRECATED_DENY_CLUSTER_USER
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_project_member_deny_cluster_user',
|
||||
check_str=(
|
||||
f"({RULE_ADMIN_API}) or ({RULE_PROJECT_MEMBER_DENY_CLUSTER_USER})"
|
||||
)
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='project_reader_deny_cluster_user',
|
||||
check_str=(
|
||||
f"(({RULE_PROJECT_READER}) and ({RULE_DENY_CLUSTER_USER}))"
|
||||
),
|
||||
deprecated_rule=DEPRECATED_DENY_CLUSTER_USER
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_project_reader_deny_cluster_user',
|
||||
check_str=(
|
||||
f"({RULE_ADMIN_API}) or ({RULE_PROJECT_READER_DENY_CLUSTER_USER})"
|
||||
)
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name='admin_or_project_reader_user_or_cluster_user',
|
||||
check_str=(
|
||||
f"({RULE_ADMIN_API}) or (({RULE_PROJECT_READER}) and "
|
||||
f"({RULE_USER_OR_CLUSTER_USER}))"
|
||||
),
|
||||
deprecated_rule=DEPRECATED_RULE_ADMIN_OR_USER_OR_CLUSTER_USER
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
@ -16,13 +16,12 @@ from oslo_policy import policy
|
||||
from magnum.common.policies import base
|
||||
|
||||
CERTIFICATE = 'certificate:%s'
|
||||
RULE_ADMIN_OR_USER_OR_CLUSTER_USER = base.RULE_ADMIN_OR_USER + " or " + \
|
||||
base.RULE_CLUSTER_USER
|
||||
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CERTIFICATE % 'create',
|
||||
check_str=RULE_ADMIN_OR_USER_OR_CLUSTER_USER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_MEMBER_USER_OR_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Sign a new certificate by the CA.',
|
||||
operations=[
|
||||
{
|
||||
@ -33,7 +32,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CERTIFICATE % 'get',
|
||||
check_str=RULE_ADMIN_OR_USER_OR_CLUSTER_USER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_READER_USER_OR_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve CA information about the given cluster.',
|
||||
operations=[
|
||||
{
|
||||
@ -44,7 +44,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CERTIFICATE % 'rotate_ca',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_MEMBER,
|
||||
scope_types=["project"],
|
||||
description='Rotate the CA certificate on the given cluster.',
|
||||
operations=[
|
||||
{
|
||||
|
@ -20,7 +20,8 @@ CLUSTER = 'cluster:%s'
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER % 'create',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_MEMBER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Create a new cluster.',
|
||||
operations=[
|
||||
{
|
||||
@ -31,7 +32,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER % 'delete',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_MEMBER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Delete a cluster.',
|
||||
operations=[
|
||||
{
|
||||
@ -53,7 +55,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER % 'detail',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_READER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve a list of clusters with detail.',
|
||||
operations=[
|
||||
{
|
||||
@ -75,7 +78,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER % 'get',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_READER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve information about the given cluster.',
|
||||
operations=[
|
||||
{
|
||||
@ -98,7 +102,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER % 'get_all',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_READER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve a list of clusters.',
|
||||
operations=[
|
||||
{
|
||||
@ -120,7 +125,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER % 'update',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_MEMBER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Update an existing cluster.',
|
||||
operations=[
|
||||
{
|
||||
@ -131,7 +137,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER % 'update_health_status',
|
||||
check_str=base.RULE_ADMIN_OR_USER + " or " + base.RULE_CLUSTER_USER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_MEMBER_USER_OR_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Update the health status of an existing cluster.',
|
||||
operations=[
|
||||
{
|
||||
@ -153,7 +160,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER % 'resize',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_MEMBER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Resize an existing cluster.',
|
||||
operations=[
|
||||
{
|
||||
@ -164,7 +172,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER % 'upgrade',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_MEMBER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Upgrade an existing cluster.',
|
||||
operations=[
|
||||
{
|
||||
|
@ -20,18 +20,20 @@ CLUSTER_TEMPLATE = 'clustertemplate:%s'
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER_TEMPLATE % 'create',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_MEMBER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Create a new cluster template.',
|
||||
operations=[
|
||||
{
|
||||
'path': '/v1/clustertemplates',
|
||||
'method': 'POST'
|
||||
}
|
||||
]
|
||||
],
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER_TEMPLATE % 'delete',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_MEMBER,
|
||||
scope_types=["project"],
|
||||
description='Delete a cluster template.',
|
||||
operations=[
|
||||
{
|
||||
@ -65,7 +67,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER_TEMPLATE % 'detail',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_READER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve a list of cluster templates with detail.',
|
||||
operations=[
|
||||
{
|
||||
@ -76,7 +79,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER_TEMPLATE % 'get',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_READER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve information about the given cluster template.',
|
||||
operations=[
|
||||
{
|
||||
@ -99,7 +103,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER_TEMPLATE % 'get_all',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_READER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve a list of cluster templates.',
|
||||
operations=[
|
||||
{
|
||||
@ -121,7 +126,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CLUSTER_TEMPLATE % 'update',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_MEMBER,
|
||||
scope_types=["project"],
|
||||
description='Update an existing cluster template.',
|
||||
operations=[
|
||||
{
|
||||
|
@ -20,7 +20,8 @@ FEDERATION = 'federation:%s'
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=FEDERATION % 'create',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_MEMBER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Create a new federation.',
|
||||
operations=[
|
||||
{
|
||||
@ -31,7 +32,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=FEDERATION % 'delete',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_MEMBER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Delete a federation.',
|
||||
operations=[
|
||||
{
|
||||
@ -42,7 +44,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=FEDERATION % 'detail',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_READER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve a list of federations with detail.',
|
||||
operations=[
|
||||
{
|
||||
@ -53,7 +56,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=FEDERATION % 'get',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_READER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve information about the given federation.',
|
||||
operations=[
|
||||
{
|
||||
@ -64,7 +68,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=FEDERATION % 'get_all',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_READER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve a list of federations.',
|
||||
operations=[
|
||||
{
|
||||
@ -75,7 +80,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=FEDERATION % 'update',
|
||||
check_str=base.RULE_DENY_CLUSTER_USER,
|
||||
check_str=base.RULE_PROJECT_MEMBER_DENY_CLUSTER_USER,
|
||||
scope_types=["project"],
|
||||
description='Update an existing federation.',
|
||||
operations=[
|
||||
{
|
||||
|
@ -24,7 +24,8 @@ NODEGROUP = 'nodegroup:%s'
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=NODEGROUP % 'get',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_READER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve information about the given nodegroup.',
|
||||
operations=[
|
||||
{
|
||||
@ -35,7 +36,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=NODEGROUP % 'get_all',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_READER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve a list of nodegroups that belong to a cluster.',
|
||||
operations=[
|
||||
{
|
||||
@ -68,7 +70,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=NODEGROUP % 'create',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_MEMBER,
|
||||
scope_types=["project"],
|
||||
description='Create a new nodegroup.',
|
||||
operations=[
|
||||
{
|
||||
@ -79,7 +82,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=NODEGROUP % 'delete',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_MEMBER,
|
||||
scope_types=["project"],
|
||||
description='Delete a nodegroup.',
|
||||
operations=[
|
||||
{
|
||||
@ -90,7 +94,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=NODEGROUP % 'update',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_MEMBER,
|
||||
scope_types=["project"],
|
||||
description='Update an existing nodegroup.',
|
||||
operations=[
|
||||
{
|
||||
|
@ -42,7 +42,8 @@ rules = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=QUOTA % 'get',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_READER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve Quota information for the given project_id.',
|
||||
operations=[
|
||||
{
|
||||
|
@ -20,7 +20,8 @@ STATS = 'stats:%s'
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=STATS % 'get_all',
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
check_str=base.RULE_ADMIN_OR_PROJECT_READER,
|
||||
scope_types=["project"],
|
||||
description='Retrieve magnum stats.',
|
||||
operations=[
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
import decorator
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_policy import opts
|
||||
from oslo_policy import policy
|
||||
from oslo_utils import importutils
|
||||
@ -27,6 +28,7 @@ from magnum.common import exception
|
||||
from magnum.common import policies
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ENFORCER = None
|
||||
CONF = cfg.CONF
|
||||
|
||||
@ -105,8 +107,14 @@ def enforce(context, rule=None, target=None,
|
||||
target = {'project_id': context.project_id,
|
||||
'user_id': context.user_id}
|
||||
add_policy_attributes(target)
|
||||
return enforcer.enforce(rule, target, credentials,
|
||||
do_raise=do_raise, exc=exc, *args, **kwargs)
|
||||
|
||||
try:
|
||||
result = enforcer.enforce(rule, target, credentials,
|
||||
do_raise=do_raise, exc=exc, *args, **kwargs)
|
||||
except policy.InvalidScope as ex:
|
||||
LOG.debug(f"Invalid scope while enforce policy :{str(ex)}")
|
||||
raise exc(action=rule)
|
||||
return result
|
||||
|
||||
|
||||
def add_policy_attributes(target):
|
||||
|
@ -25,7 +25,7 @@ fakeAuthTokenHeaders = {'X-User-Id': u'773a902f022949619b5c2f32cd89d419',
|
||||
'X-Roles': 'role1,role2',
|
||||
'X-Auth-Url': 'fake_auth_url',
|
||||
'X-Identity-Status': 'Confirmed',
|
||||
'X-User-Domain-Name': 'domain',
|
||||
'X-User-Domain-Name': 'user_domain_name',
|
||||
'X-Project-Domain-Id': 'project_domain_id',
|
||||
'X-User-Domain-Id': 'user_domain_id',
|
||||
'OpenStack-API-Version': 'container-infra 1.0'
|
||||
|
@ -128,6 +128,9 @@ class FunctionalTest(base.DbTestCase):
|
||||
with the request
|
||||
:param status: expected status code of response
|
||||
"""
|
||||
# Provide member role for put request
|
||||
if not headers:
|
||||
headers = {"X-Roles": "member"}
|
||||
return self._request_json(path=path, params=params,
|
||||
expect_errors=expect_errors,
|
||||
headers=headers, extra_environ=extra_environ,
|
||||
@ -146,6 +149,9 @@ class FunctionalTest(base.DbTestCase):
|
||||
with the request
|
||||
:param status: expected status code of response
|
||||
"""
|
||||
# Provide member role for post request
|
||||
if not headers:
|
||||
headers = {"X-Roles": "member"}
|
||||
return self._request_json(path=path, params=params,
|
||||
expect_errors=expect_errors,
|
||||
headers=headers, extra_environ=extra_environ,
|
||||
@ -164,6 +170,9 @@ class FunctionalTest(base.DbTestCase):
|
||||
with the request
|
||||
:param status: expected status code of response
|
||||
"""
|
||||
# Provide member role for patch request
|
||||
if not headers:
|
||||
headers = {"X-Roles": "member"}
|
||||
return self._request_json(path=path, params=params,
|
||||
expect_errors=expect_errors,
|
||||
headers=headers, extra_environ=extra_environ,
|
||||
@ -184,6 +193,9 @@ class FunctionalTest(base.DbTestCase):
|
||||
"""
|
||||
full_path = path_prefix + path
|
||||
print('DELETE: %s' % (full_path))
|
||||
# Provide member role for delete request
|
||||
if not headers:
|
||||
headers = {"X-Roles": "member"}
|
||||
response = self.app.delete(str(full_path),
|
||||
headers=headers,
|
||||
status=status,
|
||||
@ -215,6 +227,10 @@ class FunctionalTest(base.DbTestCase):
|
||||
'q.value': [],
|
||||
'q.op': [],
|
||||
}
|
||||
|
||||
# Provide reader role for get request
|
||||
if not headers:
|
||||
headers = {"X-Roles": "reader"}
|
||||
for query in q:
|
||||
for name in ['field', 'op', 'value']:
|
||||
query_params['q.%s' % name].append(query.get(name, ''))
|
||||
|
@ -132,7 +132,9 @@ class TestRootController(api_base.FunctionalTest):
|
||||
response = app.get('/v1/')
|
||||
self.assertEqual(self.v1_expected, response.json)
|
||||
|
||||
response = app.get('/v1/clustertemplates')
|
||||
response = app.get('/v1/clustertemplates',
|
||||
headers={"X-Roles": "reader"}
|
||||
)
|
||||
self.assertEqual(200, response.status_int)
|
||||
|
||||
def test_auth_with_no_public_routes(self):
|
||||
|
@ -21,7 +21,14 @@ from magnum.tests.unit.api import utils as api_utils
|
||||
from magnum.tests.unit.objects import utils as obj_utils
|
||||
|
||||
|
||||
HEADERS = {'OpenStack-API-Version': 'container-infra latest'}
|
||||
READER_HEADERS = {
|
||||
'OpenStack-API-Version': 'container-infra latest',
|
||||
"X-Roles": "reader"
|
||||
}
|
||||
HEADERS = {
|
||||
'OpenStack-API-Version': 'container-infra latest',
|
||||
"X-Roles": "member"
|
||||
}
|
||||
|
||||
|
||||
class TestCertObject(base.TestCase):
|
||||
@ -59,7 +66,7 @@ class TestGetCaCertificate(api_base.FunctionalTest):
|
||||
self.conductor_api.get_ca_certificate.return_value = mock_cert
|
||||
|
||||
response = self.get_json('/certificates/%s' % self.cluster.uuid,
|
||||
headers=HEADERS)
|
||||
headers=READER_HEADERS)
|
||||
|
||||
self.assertEqual(self.cluster.uuid, response['cluster_uuid'])
|
||||
self.assertEqual(fake_cert['csr'], response['csr'])
|
||||
@ -72,7 +79,7 @@ class TestGetCaCertificate(api_base.FunctionalTest):
|
||||
self.conductor_api.get_ca_certificate.return_value = mock_cert
|
||||
|
||||
response = self.get_json('/certificates/%s' % self.cluster.name,
|
||||
headers=HEADERS)
|
||||
headers=READER_HEADERS)
|
||||
|
||||
self.assertEqual(self.cluster.uuid, response['cluster_uuid'])
|
||||
self.assertEqual(fake_cert['csr'], response['csr'])
|
||||
@ -80,7 +87,8 @@ class TestGetCaCertificate(api_base.FunctionalTest):
|
||||
|
||||
def test_get_one_by_name_not_found(self):
|
||||
response = self.get_json('/certificates/not_found',
|
||||
expect_errors=True, headers=HEADERS)
|
||||
expect_errors=True,
|
||||
headers=READER_HEADERS)
|
||||
|
||||
self.assertEqual(404, response.status_int)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
@ -93,7 +101,8 @@ class TestGetCaCertificate(api_base.FunctionalTest):
|
||||
uuid=uuidutils.generate_uuid())
|
||||
|
||||
response = self.get_json('/certificates/test_cluster',
|
||||
expect_errors=True, headers=HEADERS)
|
||||
expect_errors=True,
|
||||
headers=READER_HEADERS)
|
||||
|
||||
self.assertEqual(409, response.status_int)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
@ -106,7 +115,7 @@ class TestGetCaCertificate(api_base.FunctionalTest):
|
||||
self.conductor_api.get_ca_certificate.return_value = mock_cert
|
||||
|
||||
response = self.get_json('/certificates/%s' % self.cluster.uuid,
|
||||
headers=HEADERS)
|
||||
headers=READER_HEADERS)
|
||||
|
||||
self.assertIn('links', response.keys())
|
||||
self.assertEqual(2, len(response['links']))
|
||||
@ -244,7 +253,7 @@ class TestCertPolicyEnforcement(api_base.FunctionalTest):
|
||||
self._common_policy_check(
|
||||
"certificate:get", self.get_json,
|
||||
'/certificates/%s' % cluster.uuid,
|
||||
expect_errors=True, headers=HEADERS)
|
||||
expect_errors=True, headers=READER_HEADERS)
|
||||
|
||||
def test_policy_disallow_create(self):
|
||||
cluster = obj_utils.create_test_cluster(self.context)
|
||||
|
@ -494,7 +494,9 @@ class TestPatch(api_base.FunctionalTest):
|
||||
'/clusters/%s/?rollback=True' % self.cluster_obj.uuid,
|
||||
[{'path': '/node_count', 'value': node_count,
|
||||
'op': 'replace'}],
|
||||
headers={'OpenStack-API-Version': 'container-infra 1.3'})
|
||||
headers={'OpenStack-API-Version': 'container-infra 1.3',
|
||||
"X-Roles": "member"
|
||||
})
|
||||
|
||||
self.mock_cluster_update.assert_called_once_with(
|
||||
mock.ANY, node_count, self.cluster_obj.health_status,
|
||||
@ -507,7 +509,9 @@ class TestPatch(api_base.FunctionalTest):
|
||||
'/clusters/%s/?rollback=False' % self.cluster_obj.uuid,
|
||||
[{'path': '/node_count', 'value': node_count,
|
||||
'op': 'replace'}],
|
||||
headers={'OpenStack-API-Version': 'container-infra 1.3'})
|
||||
headers={'OpenStack-API-Version': 'container-infra 1.3',
|
||||
"X-Roles": "member"
|
||||
})
|
||||
|
||||
self.mock_cluster_update.assert_called_once_with(
|
||||
mock.ANY, node_count, self.cluster_obj.health_status,
|
||||
@ -520,7 +524,9 @@ class TestPatch(api_base.FunctionalTest):
|
||||
'/clusters/%s' % self.cluster_obj.uuid,
|
||||
[{'path': '/node_count', 'value': node_count,
|
||||
'op': 'replace'}],
|
||||
headers={'OpenStack-API-Version': 'container-infra 1.9'},
|
||||
headers={'OpenStack-API-Version': 'container-infra 1.9',
|
||||
"X-Roles": "member"
|
||||
},
|
||||
expect_errors=True)
|
||||
|
||||
self.assertEqual(400, response.status_code)
|
||||
@ -531,7 +537,9 @@ class TestPatch(api_base.FunctionalTest):
|
||||
'/clusters/%s' % self.cluster_obj.uuid,
|
||||
[{'path': '/node_count', 'value': node_count,
|
||||
'op': 'replace'}],
|
||||
headers={'OpenStack-API-Version': 'container-infra 1.10'})
|
||||
headers={'OpenStack-API-Version': 'container-infra 1.10',
|
||||
"X-Roles": "member"
|
||||
})
|
||||
|
||||
self.mock_cluster_update.assert_called_once_with(
|
||||
mock.ANY, node_count, self.cluster_obj.health_status,
|
||||
@ -708,18 +716,24 @@ class TestPost(api_base.FunctionalTest):
|
||||
def test_create_cluster_with_zero_node_count_fail(self):
|
||||
bdict = apiutils.cluster_post_data()
|
||||
bdict['node_count'] = 0
|
||||
response = self.post_json('/clusters', bdict, expect_errors=True,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"})
|
||||
response = self.post_json(
|
||||
'/clusters', bdict, expect_errors=True,
|
||||
headers={
|
||||
"Openstack-Api-Version": "container-infra 1.9",
|
||||
"X-Roles": "member"
|
||||
})
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
def test_create_cluster_with_zero_node_count(self):
|
||||
bdict = apiutils.cluster_post_data()
|
||||
bdict['node_count'] = 0
|
||||
response = self.post_json('/clusters', bdict,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.10"})
|
||||
response = self.post_json(
|
||||
'/clusters', bdict,
|
||||
headers={
|
||||
"Openstack-Api-Version": "container-infra 1.10",
|
||||
"X-Roles": "member"
|
||||
})
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
self.assertEqual(202, response.status_int)
|
||||
|
||||
|
@ -46,7 +46,8 @@ class TestClusterResize(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
{"node_count": new_node_count},
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.7"})
|
||||
"container-infra 1.7",
|
||||
"X-Roles": "member"})
|
||||
self.assertEqual(202, response.status_code)
|
||||
|
||||
response = self.get_json('/clusters/%s' % self.cluster_obj.uuid)
|
||||
@ -69,7 +70,8 @@ class TestClusterResize(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_resize_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"})
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"})
|
||||
self.assertEqual(202, response.status_code)
|
||||
|
||||
response = self.get_json('/clusters/%s' % self.cluster_obj.uuid)
|
||||
@ -89,7 +91,8 @@ class TestClusterResize(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_resize_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"},
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"},
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_code)
|
||||
|
||||
@ -106,7 +109,8 @@ class TestClusterResize(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_resize_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"},
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"},
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_code)
|
||||
|
||||
@ -123,7 +127,8 @@ class TestClusterResize(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_resize_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"},
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"},
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_code)
|
||||
|
||||
@ -140,7 +145,8 @@ class TestClusterResize(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_resize_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"},
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"},
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_code)
|
||||
|
||||
@ -157,7 +163,8 @@ class TestClusterResize(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_resize_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.10"})
|
||||
"container-infra 1.10",
|
||||
"X-Roles": "member"})
|
||||
self.assertEqual(202, response.status_code)
|
||||
|
||||
|
||||
@ -195,7 +202,8 @@ class TestClusterUpgrade(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_upgrade_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.8"})
|
||||
"container-infra 1.8",
|
||||
"X-Roles": "member"})
|
||||
self.assertEqual(202, response.status_code)
|
||||
|
||||
def test_upgrade_cluster_as_admin(self):
|
||||
@ -226,7 +234,8 @@ class TestClusterUpgrade(api_base.FunctionalTest):
|
||||
'/clusters/%s/actions/upgrade' %
|
||||
cluster_uuid,
|
||||
cluster_upgrade_req,
|
||||
headers={"Openstack-Api-Version": "container-infra 1.8"})
|
||||
headers={"Openstack-Api-Version": "container-infra 1.8",
|
||||
"X-Roles": "member"})
|
||||
|
||||
self.assertEqual(202, response.status_int)
|
||||
|
||||
@ -239,7 +248,8 @@ class TestClusterUpgrade(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_upgrade_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"})
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"})
|
||||
self.assertEqual(202, response.status_code)
|
||||
|
||||
def test_upgrade_default_master(self):
|
||||
@ -251,7 +261,8 @@ class TestClusterUpgrade(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_upgrade_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"})
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"})
|
||||
self.assertEqual(202, response.status_code)
|
||||
|
||||
def test_upgrade_non_default_ng(self):
|
||||
@ -263,7 +274,8 @@ class TestClusterUpgrade(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_upgrade_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"})
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"})
|
||||
self.assertEqual(202, response.status_code)
|
||||
|
||||
def test_upgrade_cluster_not_found(self):
|
||||
@ -273,7 +285,8 @@ class TestClusterUpgrade(api_base.FunctionalTest):
|
||||
response = self.post_json('/clusters/not_there/actions/upgrade',
|
||||
cluster_upgrade_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.8"},
|
||||
"container-infra 1.8",
|
||||
"X-Roles": "member"},
|
||||
expect_errors=True)
|
||||
self.assertEqual(404, response.status_code)
|
||||
|
||||
@ -285,7 +298,8 @@ class TestClusterUpgrade(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_upgrade_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.8"},
|
||||
"container-infra 1.8",
|
||||
"X-Roles": "member"},
|
||||
expect_errors=True)
|
||||
self.assertEqual(404, response.status_code)
|
||||
|
||||
@ -298,7 +312,8 @@ class TestClusterUpgrade(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_upgrade_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"},
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"},
|
||||
expect_errors=True)
|
||||
self.assertEqual(404, response.status_code)
|
||||
|
||||
@ -311,6 +326,7 @@ class TestClusterUpgrade(api_base.FunctionalTest):
|
||||
self.cluster_obj.uuid,
|
||||
cluster_upgrade_req,
|
||||
headers={"Openstack-Api-Version":
|
||||
"container-infra 1.9"},
|
||||
"container-infra 1.9",
|
||||
"X-Roles": "member"},
|
||||
expect_errors=True)
|
||||
self.assertEqual(409, response.status_code)
|
||||
|
@ -47,24 +47,26 @@ class TestNodegroupObject(base.TestCase):
|
||||
class NodeGroupControllerTest(api_base.FunctionalTest):
|
||||
headers = {"Openstack-Api-Version": "container-infra latest"}
|
||||
|
||||
def _add_headers(self, kwargs):
|
||||
def _add_headers(self, kwargs, roles=None):
|
||||
if 'headers' not in kwargs:
|
||||
kwargs['headers'] = self.headers
|
||||
if roles:
|
||||
kwargs['headers']['X-Roles'] = ",".join(roles)
|
||||
|
||||
def get_json(self, *args, **kwargs):
|
||||
self._add_headers(kwargs)
|
||||
self._add_headers(kwargs, roles=['reader'])
|
||||
return super(NodeGroupControllerTest, self).get_json(*args, **kwargs)
|
||||
|
||||
def post_json(self, *args, **kwargs):
|
||||
self._add_headers(kwargs)
|
||||
self._add_headers(kwargs, roles=['member'])
|
||||
return super(NodeGroupControllerTest, self).post_json(*args, **kwargs)
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
self._add_headers(kwargs)
|
||||
self._add_headers(kwargs, roles=['member'])
|
||||
return super(NodeGroupControllerTest, self).delete(*args, **kwargs)
|
||||
|
||||
def patch_json(self, *args, **kwargs):
|
||||
self._add_headers(kwargs)
|
||||
self._add_headers(kwargs, roles=['member'])
|
||||
return super(NodeGroupControllerTest, self).patch_json(*args, **kwargs)
|
||||
|
||||
|
||||
|
@ -207,7 +207,7 @@ class TestQuota(api_base.FunctionalTest):
|
||||
project_id="proj-id-"+str(i))
|
||||
quota_list.append(quota)
|
||||
|
||||
headers = {'X-Project-Id': 'proj-id-2'}
|
||||
headers = {'X-Project-Id': 'proj-id-2', "X-Roles": "member"}
|
||||
response = self.get_json('/quotas', headers=headers)
|
||||
self.assertEqual(1, len(response['quotas']))
|
||||
self.assertEqual('proj-id-2', response['quotas'][0]['project_id'])
|
||||
|
@ -21,7 +21,14 @@ from magnum.tests.unit.objects import utils as obj_utils
|
||||
class TestStatsController(api_base.FunctionalTest):
|
||||
|
||||
def setUp(self):
|
||||
self.base_headers = {'OpenStack-API-Version': 'container-infra 1.4'}
|
||||
self.base_headers = {
|
||||
"X-Roles": "reader",
|
||||
"OpenStack-API-Version": "container-infra 1.4"
|
||||
}
|
||||
self.base_admin_headers = {
|
||||
"X-Roles": "admin",
|
||||
"OpenStack-API-Version": "container-infra 1.4"
|
||||
}
|
||||
super(TestStatsController, self).setUp()
|
||||
obj_utils.create_test_cluster_template(self.context)
|
||||
|
||||
@ -39,7 +46,7 @@ class TestStatsController(api_base.FunctionalTest):
|
||||
obj_utils.create_test_cluster(self.context,
|
||||
project_id=234,
|
||||
uuid='uuid2')
|
||||
response = self.get_json('/stats', headers=self.base_headers)
|
||||
response = self.get_json('/stats', headers=self.base_admin_headers)
|
||||
expected = {u'clusters': 2, u'nodes': 12}
|
||||
self.assertEqual(expected, response)
|
||||
|
||||
@ -54,7 +61,7 @@ class TestStatsController(api_base.FunctionalTest):
|
||||
uuid='uuid2')
|
||||
self.context.is_admin = True
|
||||
response = self.get_json('/stats?project_id=234',
|
||||
headers=self.base_headers)
|
||||
headers=self.base_admin_headers)
|
||||
expected = {u'clusters': 1, u'nodes': 6}
|
||||
self.assertEqual(expected, response)
|
||||
|
||||
@ -69,7 +76,7 @@ class TestStatsController(api_base.FunctionalTest):
|
||||
uuid='uuid2')
|
||||
self.context.is_admin = True
|
||||
response = self.get_json('/stats?project_id=34',
|
||||
headers=self.base_headers)
|
||||
headers=self.base_admin_headers)
|
||||
expected = {u'clusters': 0, u'nodes': 0}
|
||||
self.assertEqual(expected, response)
|
||||
|
||||
|
@ -34,7 +34,8 @@ class TestContextHook(base.BaseTestCase):
|
||||
super(TestContextHook, self).setUp()
|
||||
self.app = fakes.FakeApp()
|
||||
|
||||
def test_context_hook_before_method(self):
|
||||
@mock.patch("magnum.common.policy.check_is_admin")
|
||||
def test_context_hook_before_method(self, m_c):
|
||||
state = mock.Mock(request=fakes.FakePecanRequest())
|
||||
hook = hooks.ContextHook()
|
||||
hook.before(state)
|
||||
@ -51,12 +52,13 @@ class TestContextHook(base.BaseTestCase):
|
||||
self.assertEqual(fakes.fakeAuthTokenHeaders['X-Roles'],
|
||||
','.join(ctx.roles))
|
||||
self.assertEqual(fakes.fakeAuthTokenHeaders['X-User-Domain-Name'],
|
||||
ctx.domain_name)
|
||||
ctx.user_domain_name)
|
||||
self.assertEqual(fakes.fakeAuthTokenHeaders['X-User-Domain-Id'],
|
||||
ctx.domain_id)
|
||||
ctx.user_domain_id)
|
||||
self.assertIsNone(ctx.auth_token_info)
|
||||
|
||||
def test_context_hook_before_method_auth_info(self):
|
||||
@mock.patch("magnum.common.policy.check_is_admin")
|
||||
def test_context_hook_before_method_auth_info(self, c_m):
|
||||
state = mock.Mock(request=fakes.FakePecanRequest())
|
||||
state.request.environ['keystone.token_info'] = 'assert_this'
|
||||
hook = hooks.ContextHook()
|
||||
|
@ -19,29 +19,30 @@ from magnum.tests import base
|
||||
class ContextTestCase(base.TestCase):
|
||||
|
||||
def _create_context(self, roles=None):
|
||||
return magnum_context.RequestContext(auth_token='auth_token1',
|
||||
auth_url='auth_url1',
|
||||
domain_id='domain_id1',
|
||||
domain_name='domain_name1',
|
||||
user_name='user1',
|
||||
user_id='user-id1',
|
||||
project_name='tenant1',
|
||||
project_id='tenant-id1',
|
||||
roles=roles,
|
||||
is_admin=True,
|
||||
read_only=True,
|
||||
show_deleted=True,
|
||||
request_id='request_id1',
|
||||
trust_id='trust_id1',
|
||||
auth_token_info='token_info1')
|
||||
return magnum_context.RequestContext(
|
||||
auth_token='auth_token1',
|
||||
auth_url='auth_url1',
|
||||
user_domain_id='user_domain_id1',
|
||||
user_domain_name='user_domain_name1',
|
||||
user_name='user1',
|
||||
user_id='user-id1',
|
||||
project_name='tenant1',
|
||||
project_id='tenant-id1',
|
||||
roles=roles,
|
||||
is_admin=True,
|
||||
read_only=True,
|
||||
show_deleted=True,
|
||||
request_id='request_id1',
|
||||
trust_id='trust_id1',
|
||||
auth_token_info='token_info1')
|
||||
|
||||
def test_context(self):
|
||||
ctx = self._create_context()
|
||||
|
||||
self.assertEqual("auth_token1", ctx.auth_token)
|
||||
self.assertEqual("auth_url1", ctx.auth_url)
|
||||
self.assertEqual("domain_id1", ctx.domain_id)
|
||||
self.assertEqual("domain_name1", ctx.domain_name)
|
||||
self.assertEqual("user_domain_id1", ctx.user_domain_id)
|
||||
self.assertEqual("user_domain_name1", ctx.user_domain_name)
|
||||
self.assertEqual("user1", ctx.user_name)
|
||||
self.assertEqual("user-id1", ctx.user_id)
|
||||
self.assertEqual("tenant1", ctx.project_name)
|
||||
@ -59,8 +60,8 @@ class ContextTestCase(base.TestCase):
|
||||
|
||||
self.assertEqual("auth_token1", ctx.auth_token)
|
||||
self.assertEqual("auth_url1", ctx.auth_url)
|
||||
self.assertEqual("domain_id1", ctx.domain_id)
|
||||
self.assertEqual("domain_name1", ctx.domain_name)
|
||||
self.assertEqual("user_domain_id1", ctx.user_domain_id)
|
||||
self.assertEqual("user_domain_name1", ctx.user_domain_name)
|
||||
self.assertEqual("user1", ctx.user_name)
|
||||
self.assertEqual("user-id1", ctx.user_id)
|
||||
self.assertEqual("tenant1", ctx.project_name)
|
||||
@ -80,8 +81,8 @@ class ContextTestCase(base.TestCase):
|
||||
|
||||
self.assertEqual(ctx.auth_token, ctx2.auth_token)
|
||||
self.assertEqual(ctx.auth_url, ctx2.auth_url)
|
||||
self.assertEqual(ctx.domain_id, ctx2.domain_id)
|
||||
self.assertEqual(ctx.domain_name, ctx2.domain_name)
|
||||
self.assertEqual(ctx.user_domain_id, ctx2.user_domain_id)
|
||||
self.assertEqual(ctx.user_domain_name, ctx2.user_domain_name)
|
||||
self.assertEqual(ctx.user_name, ctx2.user_name)
|
||||
self.assertEqual(ctx.user_id, ctx2.user_id)
|
||||
self.assertEqual(ctx.project_id, ctx2.project_id)
|
||||
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
The Magnum service now allows enables policies (RBAC) new defaults
|
||||
and scope checks. These are controlled by the following (default) config
|
||||
options in ``magnum.conf`` file::
|
||||
|
||||
[oslo_policy]
|
||||
enforce_new_defaults=False
|
||||
enforce_scope=False
|
||||
|
||||
We will change the default to True in 2024.1 (Caracal) cycle.
|
||||
If you want to enable them then modify both values to True.
|
@ -28,10 +28,10 @@ oslo.config>=8.1.0 # Apache-2.0
|
||||
oslo.context>=3.1.0 # Apache-2.0
|
||||
oslo.db>=8.2.0 # Apache-2.0
|
||||
oslo.i18n>=5.0.0 # Apache-2.0
|
||||
oslo.log>=4.2.0 # Apache-2.0
|
||||
oslo.log>=4.8.0 # Apache-2.0
|
||||
oslo.messaging>=14.1.0 # Apache-2.0
|
||||
oslo.middleware>=4.1.0 # Apache-2.0
|
||||
oslo.policy>=3.6.0 # Apache-2.0
|
||||
oslo.policy>=3.11.0 # Apache-2.0
|
||||
oslo.reports>=2.1.0 # Apache-2.0
|
||||
oslo.serialization>=3.2.0 # Apache-2.0
|
||||
oslo.service>=2.2.0 # Apache-2.0
|
||||
|
Loading…
Reference in New Issue
Block a user