From d3ae72dd00f20acf8971723c4dc81d38caaa6246 Mon Sep 17 00:00:00 2001 From: Lance Bragstad Date: Tue, 3 Oct 2017 16:03:23 +0000 Subject: [PATCH] Register default policies in code This commit attempts to move default policies from a policy.json file into oslo.policy objects. This is an effort to make policy easier to maintain for operators and is a community-wide goal for the Queens release. For more information on this initiative, please see: https://governance.openstack.org/tc/goals/queens/policy-in-code.html Co-authored-By: Hieu LE bp policy-and-docs-in-code Change-Id: I8ce4fc45447b41930736d6fcf85e6d35cfbe9d56 --- .gitignore | 1 + devstack/plugin.sh | 4 -- doc/source/install/install-rdo.rst | 3 - etc/vitrage/policy.json | 17 ------ etc/vitrage/vitrage-policy-generator.conf | 3 + setup.cfg | 3 + tox.ini | 3 + vitrage/api/hooks.py | 5 ++ vitrage/common/policies/__init__.py | 31 ++++++++++ vitrage/common/policies/alarms.py | 69 +++++++++++++++++++++++ vitrage/common/policies/base.py | 14 +++++ vitrage/common/policies/event.py | 34 +++++++++++ vitrage/common/policies/rca.py | 45 +++++++++++++++ vitrage/common/policies/resource.py | 58 +++++++++++++++++++ vitrage/common/policies/template.py | 57 +++++++++++++++++++ vitrage/common/policies/topology.py | 49 ++++++++++++++++ vitrage/tests/functional/api/__init__.py | 5 -- 17 files changed, 372 insertions(+), 29 deletions(-) delete mode 100755 etc/vitrage/policy.json create mode 100644 etc/vitrage/vitrage-policy-generator.conf create mode 100644 vitrage/common/policies/__init__.py create mode 100644 vitrage/common/policies/alarms.py create mode 100644 vitrage/common/policies/base.py create mode 100644 vitrage/common/policies/event.py create mode 100644 vitrage/common/policies/rca.py create mode 100644 vitrage/common/policies/resource.py create mode 100644 vitrage/common/policies/template.py create mode 100644 vitrage/common/policies/topology.py diff --git a/.gitignore b/.gitignore index 6ef2e124e..bbdd751b4 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ ChangeLog .coverage cover etc/vitrage/vitrage.conf +etc/vitrage/policy.yaml.sample doc/source/_static/ *.db diff --git a/devstack/plugin.sh b/devstack/plugin.sh index acba89e81..eca694198 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -158,10 +158,6 @@ function configure_vitrage { setup_colorized_logging $VITRAGE_CONF DEFAULT fi - # Install the policy file for the API server - cp $VITRAGE_DIR/etc/vitrage/policy.json $VITRAGE_CONF_DIR - iniset $VITRAGE_CONF oslo_policy policy_file $VITRAGE_CONF_DIR/policy.json - cp $VITRAGE_DIR/etc/vitrage/api-paste.ini $VITRAGE_CONF_DIR # Service credentials - openstack clients using keystone diff --git a/doc/source/install/install-rdo.rst b/doc/source/install/install-rdo.rst index 52124afdf..4363e292e 100644 --- a/doc/source/install/install-rdo.rst +++ b/doc/source/install/install-rdo.rst @@ -61,8 +61,6 @@ Create the Vitrage folders $ sudo mkdir /var/log/vitrage $ sudo chmod 755 /var/log/vitrage -Copy `policy.json`_ to /etc/vitrage/ - Copy `api-paste.ini`_ to /etc/vitrage/ Copy the `datasources_values`_ folder with its content @@ -73,7 +71,6 @@ is vitrage.yaml -.. _policy.json: http://git.openstack.org/cgit/openstack/vitrage/tree/etc/vitrage/policy.json .. _api-paste.ini: http://git.openstack.org/cgit/openstack/vitrage/tree/etc/vitrage/api-paste.ini .. _datasources_values: http://git.openstack.org/cgit/openstack/vitrage/tree/etc/vitrage/datasources_values diff --git a/etc/vitrage/policy.json b/etc/vitrage/policy.json deleted file mode 100755 index aca84ee1e..000000000 --- a/etc/vitrage/policy.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "get topology": "", - "get topology:all_tenants": "role:admin", - "get resource": "", - "list resources": "", - "list resources:all_tenants": "role:admin", - "list alarms": "", - "list alarms:all_tenants": "role:admin", - "get alarms count": "", - "get alarms count:all_tenants": "role:admin", - "get rca": "", - "get rca:all_tenants": "role:admin", - "template validate": "", - "template list": "", - "template show": "", - "event post": "" -} \ No newline at end of file diff --git a/etc/vitrage/vitrage-policy-generator.conf b/etc/vitrage/vitrage-policy-generator.conf new file mode 100644 index 000000000..c305d7741 --- /dev/null +++ b/etc/vitrage/vitrage-policy-generator.conf @@ -0,0 +1,3 @@ +[DEFAULT] +output_file = etc/vitrage/policy.yaml.sample +namespace = vitrage diff --git a/setup.cfg b/setup.cfg index f4a478be1..a0d409aaa 100644 --- a/setup.cfg +++ b/setup.cfg @@ -39,6 +39,9 @@ oslo.config.opts = vitrage = vitrage.opts:list_opts datasources = vitrage.opts:datasources_opts +oslo.policy.policies = + vitrage = vitrage.common.policies:list_rules + tempest.test_plugins = vitrage_tests = vitrage_tempest_tests.plugin:VitrageTempestPlugin diff --git a/tox.ini b/tox.ini index 29975e9f8..1d91ce16f 100644 --- a/tox.ini +++ b/tox.ini @@ -23,6 +23,9 @@ commands = flake8 [testenv:genconfig] commands = oslo-config-generator --config-file=etc/vitrage/vitrage-config-generator.conf +[testenv:genpolicy] +commands = oslopolicy-sample-generator --config-file=etc/vitrage/vitrage-policy-generator.conf + [testenv:venv] commands = {posargs} diff --git a/vitrage/api/hooks.py b/vitrage/api/hooks.py index 224ebe7e2..c8a6c9d48 100644 --- a/vitrage/api/hooks.py +++ b/vitrage/api/hooks.py @@ -16,6 +16,7 @@ from oslo_context import context from oslo_policy import policy from pecan import hooks +from vitrage.common import policies from vitrage import messaging from vitrage import rpc as vitrage_rpc from vitrage import storage @@ -27,6 +28,10 @@ class ConfigHook(hooks.PecanHook): def __init__(self, conf): self.conf = conf self.enforcer = policy.Enforcer(conf) + self._register_rules() + + def _register_rules(self): + self.enforcer.register_defaults(policies.list_rules()) def before(self, state): state.request.cfg = self.conf diff --git a/vitrage/common/policies/__init__.py b/vitrage/common/policies/__init__.py new file mode 100644 index 000000000..98b29bab1 --- /dev/null +++ b/vitrage/common/policies/__init__.py @@ -0,0 +1,31 @@ +# 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 vitrage.common.policies import alarms +from vitrage.common.policies import event +from vitrage.common.policies import rca +from vitrage.common.policies import resource +from vitrage.common.policies import template +from vitrage.common.policies import topology + + +def list_rules(): + return itertools.chain( + alarms.list_rules(), + event.list_rules(), + rca.list_rules(), + template.list_rules(), + topology.list_rules(), + resource.list_rules() + ) diff --git a/vitrage/common/policies/alarms.py b/vitrage/common/policies/alarms.py new file mode 100644 index 000000000..48bd3579e --- /dev/null +++ b/vitrage/common/policies/alarms.py @@ -0,0 +1,69 @@ +# 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 vitrage.common.policies import base + +rules = [ + policy.DocumentedRuleDefault( + name='list alarms', + check_str=base.UNPROTECTED, + description='List the alarms on a resource, or all alarms', + operations=[ + { + 'path': '/alarm', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name='list alarms:all_tenants', + check_str=base.ROLE_ADMIN, + description='List alarms of all tenants ' + '(if the user has the permissions)', + operations=[ + { + 'path': '/alarm', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name='list alarms count', + check_str=base.UNPROTECTED, + description='Show how many alarms of each operations severity exist', + operations=[ + { + 'path': '/alarm/count', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name='list alarms count:all_tenants', + check_str=base.ROLE_ADMIN, + description='Show how many alarms of each operation severity exist. ' + 'Consider the alarms of all tenants (if the user has the ' + 'permissions)', + operations=[ + { + 'path': '/alarm/count', + 'method': 'GET' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/vitrage/common/policies/base.py b/vitrage/common/policies/base.py new file mode 100644 index 000000000..4302b4cc1 --- /dev/null +++ b/vitrage/common/policies/base.py @@ -0,0 +1,14 @@ +# 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. + +UNPROTECTED = '' +ROLE_ADMIN = 'role:admin' diff --git a/vitrage/common/policies/event.py b/vitrage/common/policies/event.py new file mode 100644 index 000000000..5605b4495 --- /dev/null +++ b/vitrage/common/policies/event.py @@ -0,0 +1,34 @@ +# 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 vitrage.common.policies import base + +rules = [ + policy.DocumentedRuleDefault( + name='event post', + check_str=base.UNPROTECTED, + description='Post an event to Vitrage message queue, to be consumed by' + ' a datasource driver.', + operations=[ + { + 'path': '/event', + 'method': 'POST' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/vitrage/common/policies/rca.py b/vitrage/common/policies/rca.py new file mode 100644 index 000000000..bfef7445d --- /dev/null +++ b/vitrage/common/policies/rca.py @@ -0,0 +1,45 @@ +# 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 vitrage.common.policies import base + +rules = [ + policy.DocumentedRuleDefault( + name='get rca', + check_str=base.UNPROTECTED, + description='Show the root cause analysis on an alarm', + operations=[ + { + 'path': '/rca', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name='get rca:all_tenants', + check_str=base.ROLE_ADMIN, + description='Show the root cause analysis on an alarm. Include alarms' + ' of all tenants (if the user has the permisions)', + operations=[ + { + 'path': '/rca', + 'method': 'GET' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/vitrage/common/policies/resource.py b/vitrage/common/policies/resource.py new file mode 100644 index 000000000..9f0a037ed --- /dev/null +++ b/vitrage/common/policies/resource.py @@ -0,0 +1,58 @@ +# 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 vitrage.common.policies import base + +rules = [ + policy.DocumentedRuleDefault( + name='get resource', + check_str=base.UNPROTECTED, + description='Show the details of specified resource', + operations=[ + { + 'path': '/resources', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name='list resources', + check_str=base.UNPROTECTED, + description='List the resources with the specified type, or all the ' + 'resources', + operations=[ + { + 'path': '/resources', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name='list resources:all_tenants', + check_str=base.ROLE_ADMIN, + description='List the resources with the specified type, or all the ' + 'resources. Include resources of all tenants (if the user' + ' has the permissions)', + operations=[ + { + 'path': '/resources', + 'method': 'GET' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/vitrage/common/policies/template.py b/vitrage/common/policies/template.py new file mode 100644 index 000000000..fd5e19ac6 --- /dev/null +++ b/vitrage/common/policies/template.py @@ -0,0 +1,57 @@ +# 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 vitrage.common.policies import base + +TEMPLATE = 'template %s' + +rules = [ + policy.DocumentedRuleDefault( + name=TEMPLATE % 'validate', + check_str=base.UNPROTECTED, + description='Validate a template, or all templates in a folder', + operations=[ + { + 'path': '/template', + 'method': 'POST' + } + ] + ), + policy.DocumentedRuleDefault( + name=TEMPLATE % 'list', + check_str=base.UNPROTECTED, + description='List all templates', + operations=[ + { + 'path': '/template', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=TEMPLATE % 'show', + check_str=base.UNPROTECTED, + description='Show the template body for given template ID', + operations=[ + { + 'path': '/template/{template_uuid}', + 'method': 'GET' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/vitrage/common/policies/topology.py b/vitrage/common/policies/topology.py new file mode 100644 index 000000000..92dc87ae4 --- /dev/null +++ b/vitrage/common/policies/topology.py @@ -0,0 +1,49 @@ +# 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 vitrage.common.policies import base + +TOPOLOGY = 'get topology' + +rules = [ + policy.DocumentedRuleDefault( + name=TOPOLOGY, + check_str=base.UNPROTECTED, + description='Get the topology for the OpenStack cluster with optional ' + 'query parameters', + operations=[ + { + 'path': '/topology', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=TOPOLOGY + ':all_tenants', + check_str=base.ROLE_ADMIN, + description='Get the topology for the OpenStack cluster with optional ' + 'query parameters. Return resources of all tenants (if the' + ' user has the permissions).', + operations=[ + { + 'path': '/topology', + 'method': 'GET' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/vitrage/tests/functional/api/__init__.py b/vitrage/tests/functional/api/__init__.py index ba16fa551..59bd894d8 100644 --- a/vitrage/tests/functional/api/__init__.py +++ b/vitrage/tests/functional/api/__init__.py @@ -47,11 +47,6 @@ class FunctionalTest(base.BaseTest): vitrage_root = os.path.abspath( os.path.join(os.path.dirname(vitrage_init_file), '..', )) - self.CONF.set_override('policy_file', os.path.join(vitrage_root, - 'etc', 'vitrage', - 'policy.json'), - group='oslo_policy') - self.CONF.set_override('paste_config', os.path.join(vitrage_root, 'etc', 'vitrage', 'api-paste.ini'),