Implement policy in code
* Added policy in code as per community goals [1] for vnf packages. * Modified tox to generate policy sample json file. [1]: https://governance.openstack.org/tc/goals/queens/policy-in-code.html Partial-Implements: blueprint tosca-csar-mgmt-driver Co-Author: Neha Alhat <neha.alhat@nttdata.com> Co-Author: Bhagyashri Shewale <bhagyashri.shewale@nttdata.com> Change-Id: I7cedbca4abe41223e3f8d6211a74b4347299e9e5
This commit is contained in:
parent
354da78e0c
commit
34b661ad08
2
.gitignore
vendored
2
.gitignore
vendored
@ -28,7 +28,9 @@ subunit.log
|
|||||||
.eggs/
|
.eggs/
|
||||||
.stestr/
|
.stestr/
|
||||||
SP1_res.yaml
|
SP1_res.yaml
|
||||||
|
etc/tacker/policy.yaml.sample
|
||||||
|
|
||||||
releasenotes/build
|
releasenotes/build
|
||||||
etc/tacker/tacker.conf.sample
|
etc/tacker/tacker.conf.sample
|
||||||
doc/source/contributor/api
|
doc/source/contributor/api
|
||||||
|
doc/source/_static/tacker.policy.yaml.sample
|
||||||
|
@ -200,16 +200,10 @@ function configure_tacker {
|
|||||||
|
|
||||||
# server
|
# server
|
||||||
TACKER_API_PASTE_FILE=$TACKER_CONF_DIR/api-paste.ini
|
TACKER_API_PASTE_FILE=$TACKER_CONF_DIR/api-paste.ini
|
||||||
TACKER_POLICY_FILE=$TACKER_CONF_DIR/policy.json
|
|
||||||
|
|
||||||
cp $TACKER_DIR/etc/tacker/api-paste.ini $TACKER_API_PASTE_FILE
|
cp $TACKER_DIR/etc/tacker/api-paste.ini $TACKER_API_PASTE_FILE
|
||||||
cp $TACKER_DIR/etc/tacker/policy.json $TACKER_POLICY_FILE
|
|
||||||
|
|
||||||
# allow tacker user to administer tacker to match tacker account
|
|
||||||
sed -i 's/"context_is_admin": "role:admin"/"context_is_admin": "role:admin or user_name:tacker"/g' $TACKER_POLICY_FILE
|
|
||||||
|
|
||||||
iniset $TACKER_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
|
iniset $TACKER_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
|
||||||
iniset $TACKER_CONF DEFAULT policy_file $TACKER_POLICY_FILE
|
|
||||||
|
|
||||||
iniset $TACKER_CONF DEFAULT auth_strategy $TACKER_AUTH_STRATEGY
|
iniset $TACKER_CONF DEFAULT auth_strategy $TACKER_AUTH_STRATEGY
|
||||||
_tacker_setup_keystone $TACKER_CONF keystone_authtoken
|
_tacker_setup_keystone $TACKER_CONF keystone_authtoken
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
auth_strategy = keystone
|
auth_strategy = keystone
|
||||||
policy_file = /etc/tacker/policy.json
|
|
||||||
debug = True
|
debug = True
|
||||||
logging_exception_prefix = %(color)s%(asctime)s.%(msecs)03d TRACE %(name)s [01;35m%(instance)s[00m
|
logging_exception_prefix = %(color)s%(asctime)s.%(msecs)03d TRACE %(name)s [01;35m%(instance)s[00m
|
||||||
logging_debug_format_suffix = [00;33mfrom (pid=%(process)d) %(funcName)s %(pathname)s:%(lineno)d[00m
|
logging_debug_format_suffix = [00;33mfrom (pid=%(process)d) %(funcName)s %(pathname)s:%(lineno)d[00m
|
||||||
|
@ -23,8 +23,15 @@ extensions = [
|
|||||||
'sphinxcontrib.apidoc',
|
'sphinxcontrib.apidoc',
|
||||||
'stevedore.sphinxext',
|
'stevedore.sphinxext',
|
||||||
'openstackdocstheme',
|
'openstackdocstheme',
|
||||||
|
'oslo_policy.sphinxext',
|
||||||
|
'oslo_policy.sphinxpolicygen',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
policy_generator_config_file = [
|
||||||
|
('../../etc/tacker-policy-generator.conf', '_static/tacker'),
|
||||||
|
]
|
||||||
|
sample_policy_basename = '_static/tacker'
|
||||||
|
|
||||||
# sphinxcontrib.apidoc options
|
# sphinxcontrib.apidoc options
|
||||||
apidoc_module_dir = '../../tacker'
|
apidoc_module_dir = '../../tacker'
|
||||||
apidoc_output_dir = 'contributor/api'
|
apidoc_output_dir = 'contributor/api'
|
||||||
|
@ -31,3 +31,24 @@ The sample configuration can also be viewed in :download:`file form
|
|||||||
version of this documentation.
|
version of this documentation.
|
||||||
|
|
||||||
.. literalinclude:: /_extra/tacker.conf.sample
|
.. literalinclude:: /_extra/tacker.conf.sample
|
||||||
|
|
||||||
|
Policy
|
||||||
|
------
|
||||||
|
|
||||||
|
Tacker, like most OpenStack projects, uses a policy language to restrict
|
||||||
|
permissions on REST API actions.
|
||||||
|
|
||||||
|
* :doc:`Policy Reference <policy>`: A complete reference of all
|
||||||
|
policy points in tacker and what they impact.
|
||||||
|
|
||||||
|
* :doc:`Sample Policy File <sample_policy>`: A sample tacker
|
||||||
|
policy file with inline documentation.
|
||||||
|
|
||||||
|
.. # NOTE(bhagyashris): This is the section where we hide things that we don't
|
||||||
|
# actually want in the table of contents but sphinx build would fail if
|
||||||
|
# they aren't in the toctree somewhere.
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
policy
|
||||||
|
sample_policy
|
||||||
|
9
doc/source/configuration/policy.rst
Normal file
9
doc/source/configuration/policy.rst
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
===============
|
||||||
|
Tacker Policies
|
||||||
|
===============
|
||||||
|
|
||||||
|
The following is an overview of all available policies in Tacker.
|
||||||
|
For a sample configuration file, refer to :doc:`/configuration/sample_policy`.
|
||||||
|
|
||||||
|
.. show-policy::
|
||||||
|
:config-file: etc/tacker-policy-generator.conf
|
16
doc/source/configuration/sample_policy.rst
Normal file
16
doc/source/configuration/sample_policy.rst
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
=========================
|
||||||
|
Sample Tacker Policy File
|
||||||
|
=========================
|
||||||
|
|
||||||
|
The following is a sample tacker policy file for adaptation and use.
|
||||||
|
|
||||||
|
The sample policy can also be viewed in :download:`file form
|
||||||
|
</_static/tacker.policy.yaml.sample>`.
|
||||||
|
|
||||||
|
.. important::
|
||||||
|
|
||||||
|
The sample policy file is auto-generated from tacker when this documentation
|
||||||
|
is built. You must ensure your version of tacker matches the version of this
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
.. literalinclude:: /_static/tacker.policy.yaml.sample
|
3
etc/tacker-policy-generator.conf
Normal file
3
etc/tacker-policy-generator.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
output_file = etc/tacker/policy.yaml.sample
|
||||||
|
namespace = tacker
|
7
etc/tacker/README-policy-yaml.txt
Normal file
7
etc/tacker/README-policy-yaml.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Tacker
|
||||||
|
======
|
||||||
|
|
||||||
|
To generate the sample tacker policy.yaml file, run the following command from
|
||||||
|
the top level of the tacker directory:
|
||||||
|
|
||||||
|
tox -egenpolicy
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"context_is_admin": "role:admin",
|
|
||||||
"admin_or_owner": "rule:context_is_admin or tenant_id:%(tenant_id)s",
|
|
||||||
"admin_only": "rule:context_is_admin",
|
|
||||||
"regular_user": "",
|
|
||||||
"shared": "field:vims:shared=True",
|
|
||||||
"default": "rule:admin_or_owner",
|
|
||||||
|
|
||||||
"get_vim": "rule:admin_or_owner or rule:shared"
|
|
||||||
}
|
|
10
setup.cfg
10
setup.cfg
@ -25,7 +25,6 @@ packages =
|
|||||||
data_files =
|
data_files =
|
||||||
etc/tacker =
|
etc/tacker =
|
||||||
etc/tacker/api-paste.ini
|
etc/tacker/api-paste.ini
|
||||||
etc/tacker/policy.json
|
|
||||||
etc/tacker/rootwrap.conf
|
etc/tacker/rootwrap.conf
|
||||||
etc/rootwrap.d =
|
etc/rootwrap.d =
|
||||||
etc/tacker/rootwrap.d/tacker.filters
|
etc/tacker/rootwrap.d/tacker.filters
|
||||||
@ -96,6 +95,15 @@ oslo.config.opts =
|
|||||||
mistral.actions =
|
mistral.actions =
|
||||||
tacker.vim_ping_action = tacker.nfvo.workflows.vim_monitor.vim_ping_action:PingVimAction
|
tacker.vim_ping_action = tacker.nfvo.workflows.vim_monitor.vim_ping_action:PingVimAction
|
||||||
|
|
||||||
|
oslo.policy.enforcer =
|
||||||
|
tacker = tacker.policy:get_enforcer
|
||||||
|
|
||||||
|
oslo.policy.policies =
|
||||||
|
# The sample policies will be ordered by entry point and then by list
|
||||||
|
# returned from that entry point. If more control is desired split out each
|
||||||
|
# list_rules method into a separate entry point rather than using the
|
||||||
|
# aggregate method.
|
||||||
|
tacker = tacker.policies:list_rules
|
||||||
|
|
||||||
[build_releasenotes]
|
[build_releasenotes]
|
||||||
all_files = 1
|
all_files = 1
|
||||||
|
@ -43,8 +43,6 @@ core_opts = [
|
|||||||
help=_("The path for API extensions")),
|
help=_("The path for API extensions")),
|
||||||
cfg.ListOpt('service_plugins', default=['nfvo', 'vnfm'],
|
cfg.ListOpt('service_plugins', default=['nfvo', 'vnfm'],
|
||||||
help=_("The service plugins Tacker will use")),
|
help=_("The service plugins Tacker will use")),
|
||||||
cfg.StrOpt('policy_file', default="policy.json",
|
|
||||||
help=_("The policy file to use")),
|
|
||||||
cfg.StrOpt('auth_strategy', default='keystone',
|
cfg.StrOpt('auth_strategy', default='keystone',
|
||||||
help=_("The type of authentication to use")),
|
help=_("The type of authentication to use")),
|
||||||
cfg.BoolOpt('allow_bulk', default=True,
|
cfg.BoolOpt('allow_bulk', default=True,
|
||||||
|
@ -23,6 +23,7 @@ from oslo_config import cfg
|
|||||||
from oslo_context import context as oslo_context
|
from oslo_context import context as oslo_context
|
||||||
from oslo_db.sqlalchemy import enginefacade
|
from oslo_db.sqlalchemy import enginefacade
|
||||||
|
|
||||||
|
from tacker.common import exceptions
|
||||||
from tacker.db import api as db_api
|
from tacker.db import api as db_api
|
||||||
from tacker import policy
|
from tacker import policy
|
||||||
|
|
||||||
@ -142,6 +143,34 @@ class ContextBase(oslo_context.RequestContext):
|
|||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def can(self, action, target=None, fatal=True):
|
||||||
|
"""Verifies that the given action is valid on the target in this context.
|
||||||
|
|
||||||
|
:param action: string representing the action to be checked.
|
||||||
|
:param target: dictionary representing the object of the action
|
||||||
|
for object creation this should be a dictionary representing the
|
||||||
|
location of the object e.g. ``{'project_id': context.project_id}``.
|
||||||
|
If None, then this default target will be considered:
|
||||||
|
{'project_id': self.project_id, 'user_id': self.user_id}
|
||||||
|
:param fatal: if False, will return False when an exception.Forbidden
|
||||||
|
occurs.
|
||||||
|
|
||||||
|
:raises tacker.exception.Forbidden: if verification fails and fatal
|
||||||
|
is True.
|
||||||
|
|
||||||
|
:return: returns a non-False value (not necessarily "True") if
|
||||||
|
authorized and False if not authorized and fatal is False.
|
||||||
|
"""
|
||||||
|
if target is None:
|
||||||
|
target = {'tenant_id': self.tenant_id,
|
||||||
|
'user_id': self.user_id}
|
||||||
|
try:
|
||||||
|
return policy.authorize(self, action, target)
|
||||||
|
except exceptions.Forbidden:
|
||||||
|
if fatal:
|
||||||
|
raise
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
@enginefacade.transaction_context_provider
|
@enginefacade.transaction_context_provider
|
||||||
class ContextBaseWithSession(ContextBase):
|
class ContextBaseWithSession(ContextBase):
|
||||||
|
27
tacker/policies/__init__.py
Normal file
27
tacker/policies/__init__.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Copyright (C) 2019 NTT DATA
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
from tacker.policies import base
|
||||||
|
from tacker.policies import vnf_package
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return itertools.chain(
|
||||||
|
base.list_rules(),
|
||||||
|
vnf_package.list_rules(),
|
||||||
|
)
|
49
tacker/policies/base.py
Normal file
49
tacker/policies/base.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Copyright (C) 2019 NTT DATA
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
TACKER_API = 'os_nfv_orchestration_api'
|
||||||
|
|
||||||
|
RULE_ADMIN_OR_OWNER = 'rule:admin_or_owner'
|
||||||
|
RULE_ADMIN_API = 'rule:admin_only'
|
||||||
|
RULE_ANY = '@'
|
||||||
|
|
||||||
|
rules = [
|
||||||
|
policy.RuleDefault(
|
||||||
|
"context_is_admin",
|
||||||
|
"role:admin",
|
||||||
|
"Decides what is required for the 'is_admin:True' check to succeed."),
|
||||||
|
policy.RuleDefault(
|
||||||
|
"admin_or_owner",
|
||||||
|
"is_admin:True or tenant_id:%(tenant_id)s",
|
||||||
|
"Default rule for most non-Admin APIs."),
|
||||||
|
policy.RuleDefault(
|
||||||
|
"admin_only",
|
||||||
|
"is_admin:True",
|
||||||
|
"Default rule for most Admin APIs."),
|
||||||
|
policy.RuleDefault(
|
||||||
|
"shared",
|
||||||
|
"field:vims:shared=True",
|
||||||
|
"Default rule for sharing vims."),
|
||||||
|
policy.RuleDefault(
|
||||||
|
"default",
|
||||||
|
"rule:admin_or_owner",
|
||||||
|
"Default rule for most non-Admin APIs.")
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return rules
|
91
tacker/policies/vnf_package.py
Normal file
91
tacker/policies/vnf_package.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# Copyright (C) 2019 NTT DATA
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from tacker.policies import base
|
||||||
|
|
||||||
|
|
||||||
|
VNFPKGM = 'os_nfv_orchestration_api:vnf_packages:%s'
|
||||||
|
|
||||||
|
rules = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=VNFPKGM % 'create',
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="Creates a vnf package.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'POST',
|
||||||
|
'path': '/vnf_packages'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=VNFPKGM % 'show',
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="Show a vnf package.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/vnf_packages/{vnf_package_id}'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=VNFPKGM % 'index',
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="List all vnf packages.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/vnf_packages/'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=VNFPKGM % 'delete',
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="Delete a vnf package.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'DELETE',
|
||||||
|
'path': '/vnf_packages/{vnf_package_id}'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=VNFPKGM % 'upload_package_content',
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="upload a vnf package content.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'PUT',
|
||||||
|
'path': '/vnf_packages/{vnf_package_id}/'
|
||||||
|
'package_content'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=VNFPKGM % 'upload_from_uri',
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="upload a vnf package content from uri.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'POST',
|
||||||
|
'path': '/vnf_packages/{vnf_package_id}/package_content/'
|
||||||
|
'upload_from_uri'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return rules
|
@ -28,6 +28,7 @@ import six
|
|||||||
from tacker._i18n import _
|
from tacker._i18n import _
|
||||||
from tacker.api.v1 import attributes
|
from tacker.api.v1 import attributes
|
||||||
from tacker.common import exceptions
|
from tacker.common import exceptions
|
||||||
|
from tacker import policies
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -36,18 +37,6 @@ _ENFORCER = None
|
|||||||
ADMIN_CTX_POLICY = 'context_is_admin'
|
ADMIN_CTX_POLICY = 'context_is_admin'
|
||||||
|
|
||||||
|
|
||||||
_BASE_RULES = [
|
|
||||||
policy.RuleDefault(
|
|
||||||
ADMIN_CTX_POLICY,
|
|
||||||
'role:admin',
|
|
||||||
description='Rule for cloud admin access'),
|
|
||||||
# policy.RuleDefault(
|
|
||||||
# _ADVSVC_CTX_POLICY,
|
|
||||||
# 'role:advsvc',
|
|
||||||
# description='Rule for advanced service role access'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def reset():
|
def reset():
|
||||||
global _ENFORCER
|
global _ENFORCER
|
||||||
if _ENFORCER:
|
if _ENFORCER:
|
||||||
@ -61,8 +50,29 @@ def init(conf=cfg.CONF, policy_file=None):
|
|||||||
global _ENFORCER
|
global _ENFORCER
|
||||||
if not _ENFORCER:
|
if not _ENFORCER:
|
||||||
_ENFORCER = policy.Enforcer(conf, policy_file=policy_file)
|
_ENFORCER = policy.Enforcer(conf, policy_file=policy_file)
|
||||||
_ENFORCER.register_defaults(_BASE_RULES)
|
register_rules(_ENFORCER)
|
||||||
_ENFORCER.load_rules(True)
|
_ENFORCER.load_rules()
|
||||||
|
|
||||||
|
|
||||||
|
def authorize(context, action, target, do_raise=True, exc=None):
|
||||||
|
|
||||||
|
init()
|
||||||
|
credentials = context.to_policy_values()
|
||||||
|
if not exc:
|
||||||
|
exc = exceptions.PolicyNotAuthorized
|
||||||
|
try:
|
||||||
|
result = _ENFORCER.authorize(action, target, credentials,
|
||||||
|
do_raise=do_raise, exc=exc, action=action)
|
||||||
|
except policy.PolicyNotRegistered:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
LOG.debug('Policy not registered')
|
||||||
|
except Exception:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
LOG.debug('Policy check for %(action)s failed with credentials '
|
||||||
|
'%(credentials)s',
|
||||||
|
{'action': action, 'credentials': credentials})
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def refresh(policy_file=None):
|
def refresh(policy_file=None):
|
||||||
@ -427,6 +437,10 @@ def check_is_admin(context):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def register_rules(enforcer):
|
||||||
|
enforcer.register_defaults(policies.list_rules())
|
||||||
|
|
||||||
|
|
||||||
def get_enforcer():
|
def get_enforcer():
|
||||||
# NOTE(amotoki): This was borrowed from nova/policy.py.
|
# NOTE(amotoki): This was borrowed from nova/policy.py.
|
||||||
# This method is for use by oslo.policy CLI scripts. Those scripts need the
|
# This method is for use by oslo.policy CLI scripts. Those scripts need the
|
||||||
|
@ -29,7 +29,6 @@ class ConfigurationTest(base.BaseTestCase):
|
|||||||
self.assertEqual(9890, cfg.CONF.bind_port)
|
self.assertEqual(9890, cfg.CONF.bind_port)
|
||||||
self.assertEqual('api-paste.ini.test', cfg.CONF.api_paste_config)
|
self.assertEqual('api-paste.ini.test', cfg.CONF.api_paste_config)
|
||||||
self.assertEqual('unit/extensions', cfg.CONF.api_extensions_path)
|
self.assertEqual('unit/extensions', cfg.CONF.api_extensions_path)
|
||||||
self.assertEqual('policy.json', cfg.CONF.policy_file)
|
|
||||||
self.assertEqual('keystone', cfg.CONF.auth_strategy)
|
self.assertEqual('keystone', cfg.CONF.auth_strategy)
|
||||||
self.assertTrue(cfg.CONF.allow_bulk)
|
self.assertTrue(cfg.CONF.allow_bulk)
|
||||||
self.assertFalse(cfg.CONF.allow_pagination)
|
self.assertFalse(cfg.CONF.allow_pagination)
|
||||||
|
5
tox.ini
5
tox.ini
@ -60,6 +60,7 @@ commands = python ./tools/check_i18n.py ./tacker
|
|||||||
deps = -r{toxinidir}/doc/requirements.txt
|
deps = -r{toxinidir}/doc/requirements.txt
|
||||||
commands =
|
commands =
|
||||||
sphinx-build -W -b html doc/source doc/build/html
|
sphinx-build -W -b html doc/source doc/build/html
|
||||||
|
oslopolicy-sample-generator --config-file=etc/tacker-policy-generator.conf
|
||||||
|
|
||||||
[testenv:api-ref]
|
[testenv:api-ref]
|
||||||
deps = -r{toxinidir}/doc/requirements.txt
|
deps = -r{toxinidir}/doc/requirements.txt
|
||||||
@ -101,6 +102,10 @@ local-check-factory = tacker.hacking.checks.factory
|
|||||||
commands =
|
commands =
|
||||||
oslo-config-generator --config-file=etc/config-generator.conf
|
oslo-config-generator --config-file=etc/config-generator.conf
|
||||||
|
|
||||||
|
[testenv:genpolicy]
|
||||||
|
commands =
|
||||||
|
oslopolicy-sample-generator --config-file=etc/tacker-policy-generator.conf
|
||||||
|
|
||||||
[testenv:lower-constraints]
|
[testenv:lower-constraints]
|
||||||
deps =
|
deps =
|
||||||
-c{toxinidir}/lower-constraints.txt
|
-c{toxinidir}/lower-constraints.txt
|
||||||
|
Loading…
x
Reference in New Issue
Block a user