From 5ccab31a64dfd4a3cba70b1463a1d8242bdb30f8 Mon Sep 17 00:00:00 2001 From: zte-hanrong Date: Thu, 7 Jul 2016 23:33:42 +0800 Subject: [PATCH] Add policies for API access control to watcher-dashboard Co-Authored-By: David TARDIVEL Change-Id: I1babb96cbad71b74b6fd5e1ac5f1cfb7b263ba2c blueprint: watcher-policies --- README.rst | 16 ++++++++ devstack/plugin.sh | 2 + tools/register_plugin.sh | 6 +++ watcher_dashboard/api/watcher.py | 8 ++++ watcher_dashboard/conf/watcher_policy.json | 37 +++++++++++++++++++ .../content/action_plans/tables.py | 5 ++- watcher_dashboard/content/actions/tables.py | 1 + .../content/audit_templates/tables.py | 4 ++ watcher_dashboard/content/audits/tables.py | 5 ++- .../content/strategies/tables.py | 1 + 10 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 watcher_dashboard/conf/watcher_policy.json diff --git a/README.rst b/README.rst index f2c16dd..fd6fab8 100644 --- a/README.rst +++ b/README.rst @@ -109,6 +109,22 @@ Please note that these commands are also available via ``tox``. As of the Mitaka release, the dashboard for watcher is now maintained outside of the Horizon codebase, in this repository. + +Policies +-------- +You can enable policies on Watcher ``Optimization`` panel, by updating in the +``/openstack_dashboard/settings.py`` configuration file the +following parameters + + POLICY_FILES = { + ... + 'infra-optim': 'watcher_policy.json', +} + +You can also update the file ``/openstack_dashboard/conf/watcher_policy.conf`` +to customize your policies. + + Links ----- diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 505ee92..5520d2c 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -8,6 +8,7 @@ function install_watcher_dashboard { function configure_watcher_dashboard { cp -a ${WATCHER_DASHBOARD_DIR}/watcher_dashboard/enabled/* ${DEST}/horizon/openstack_dashboard/local/enabled/ + cp -a ${WATCHER_DASHBOARD_DIR}/watcher_dashboard/conf/* ${DEST}/horizon/openstack_dashboard/conf/ } function init_watcher_dashboard { @@ -42,6 +43,7 @@ if is_service_enabled watcher-dashboard; then if [[ "$1" == "unstack" ]]; then rm -f ${DEST}/horizon/openstack_dashboard/local/enabled/_310* + rm -f ${DEST}/horizon/openstack_dashboard/conf/watcher* fi diff --git a/tools/register_plugin.sh b/tools/register_plugin.sh index 7b24c8c..b155175 100755 --- a/tools/register_plugin.sh +++ b/tools/register_plugin.sh @@ -14,3 +14,9 @@ for filepath in $src_path/watcher_dashboard/enabled/*.py; do ln -s $src_filepath $dest_filepath fi done + +policy_file_name='watcher_policy.json' +src_policy_filepath=$src_path'/watcher_dashboard/conf/'$policy_file_name +dest_policy_file=$dest_path'/openstack_dashboard/conf/'$policy_file_name +echo "$src_policy_filepath --> $dest_policy_file" +ln -s $src_policy_filepath $dest_policy_file diff --git a/watcher_dashboard/api/watcher.py b/watcher_dashboard/api/watcher.py index a694735..d435fab 100644 --- a/watcher_dashboard/api/watcher.py +++ b/watcher_dashboard/api/watcher.py @@ -29,6 +29,8 @@ def watcherclient(request, password=None): api_version = "1" insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False) ca_file = getattr(settings, 'OPENSTACK_SSL_CACERT', None) + insert_watcher_policy_file() + endpoint = base.url_for(request, WATCHER_SERVICE) LOG.debug('watcherclient connection created using token "%s" and url "%s"' @@ -46,6 +48,12 @@ def watcherclient(request, password=None): return client +def insert_watcher_policy_file(): + policy_files = getattr(settings, 'POLICY_FILES', {}) + policy_files['infra-optim'] = 'watcher_policy.json' + setattr(settings, 'POLICY_FILES', policy_files) + + class Audit(base.APIDictWrapper): _attrs = ('uuid', 'created_at', 'modified_at', 'deleted_at', 'deadline', 'state', 'audit_type', 'audit_template_uuid', diff --git a/watcher_dashboard/conf/watcher_policy.json b/watcher_dashboard/conf/watcher_policy.json new file mode 100644 index 0000000..b3d5449 --- /dev/null +++ b/watcher_dashboard/conf/watcher_policy.json @@ -0,0 +1,37 @@ +{ + "admin_api": "role:admin or role:administrator", + "show_password": "!", + "default": "rule:admin_api", + + "action:detail": "rule:default", + "action:get": "rule:default", + "action:get_all": "rule:default", + + "action_plan:create": "rule:default", + "action_plan:detail": "rule:default", + "action_plan:get": "rule:default", + "action_plan:get_all": "rule:default", + "action_plan:update": "rule:default", + + "audit:create": "rule:default", + "audit:delete": "rule:default", + "audit:detail": "rule:default", + "audit:get": "rule:default", + "audit:get_all": "rule:default", + "audit:update": "rule:default", + + "audit_template:create": "rule:default", + "audit_template:delete": "rule:default", + "audit_template:detail": "rule:default", + "audit_template:get": "rule:default", + "audit_template:get_all": "rule:default", + "audit_template:update": "rule:default", + + "goal:detail": "rule:default", + "goal:get": "rule:default", + "goal:get_all": "rule:default", + + "strategy:detail": "rule:default", + "strategy:get": "rule:default", + "strategy:get_all": "rule:default" +} diff --git a/watcher_dashboard/content/action_plans/tables.py b/watcher_dashboard/content/action_plans/tables.py index 35ac703..0b712dc 100644 --- a/watcher_dashboard/content/action_plans/tables.py +++ b/watcher_dashboard/content/action_plans/tables.py @@ -46,11 +46,12 @@ class ActionPlansFilterAction(horizon.tables.FilterAction): filter_choices = ( ('audit', _("Audit ="), True), ) + policy_rules = (("infra-optim", "action_plan:detail"),) class ArchiveActionPlan(horizon.tables.BatchAction): name = "archive_action_plans" - # policy_rules = (("compute", "compute:delete"),) + policy_rules = (("infra-optim", "action_plan:delete"),) help_text = _("Archive an action plan.") @staticmethod @@ -76,7 +77,7 @@ class ArchiveActionPlan(horizon.tables.BatchAction): class StartActionPlan(horizon.tables.BatchAction): name = "start_action_plan" classes = ('btn-confirm',) - # policy_rules = (("compute", "compute:delete"),) + policy_rules = (("infra-optim", "action_plan:update"),) help_text = _("Execute an action plan.") @staticmethod diff --git a/watcher_dashboard/content/actions/tables.py b/watcher_dashboard/content/actions/tables.py index e48b1b2..d9c7882 100644 --- a/watcher_dashboard/content/actions/tables.py +++ b/watcher_dashboard/content/actions/tables.py @@ -58,6 +58,7 @@ class UpdateRow(horizon.tables.Row): class ActionsFilterAction(horizon.tables.FilterAction): filter_type = "server" filter_choices = (('action_plan', _("Action Plan ID ="), True),) + policy_rules = (("infra-optim", "action:detail"),) class ActionsTable(horizon.tables.DataTable): diff --git a/watcher_dashboard/content/audit_templates/tables.py b/watcher_dashboard/content/audit_templates/tables.py index a84dfaa..29b0161 100644 --- a/watcher_dashboard/content/audit_templates/tables.py +++ b/watcher_dashboard/content/audit_templates/tables.py @@ -30,6 +30,7 @@ class CreateAuditTemplates(horizon.tables.LinkAction): verbose_name = _("Create Template") url = "horizon:admin:audit_templates:create" classes = ("ajax-modal", "btn-launch") + policy_rules = (("infra-optim", "audit_templates:create"),) class AuditTemplatesFilterAction(horizon.tables.FilterAction): @@ -38,6 +39,7 @@ class AuditTemplatesFilterAction(horizon.tables.FilterAction): ('goal', _("Goal ="), True), ('strategy', _("Strategy ="), True), ) + policy_rules = (("infra-optim", "audit_templates:detail"),) class LaunchAudit(horizon.tables.BatchAction): @@ -46,6 +48,7 @@ class LaunchAudit(horizon.tables.BatchAction): data_type_singular = _("Launch Audit") data_type_plural = _("Launch Audits") success_url = "horizon:admin:audits:index" + policy_rules = (("infra-optim", "audit:create"),) @staticmethod def action_present(count): @@ -72,6 +75,7 @@ class LaunchAudit(horizon.tables.BatchAction): class DeleteAuditTemplates(horizon.tables.DeleteAction): verbose_name = _("Delete Templates") + policy_rules = (("infra-optim", "audit_template:delete"),) @staticmethod def action_present(count): diff --git a/watcher_dashboard/content/audits/tables.py b/watcher_dashboard/content/audits/tables.py index c2bd16d..4adefc1 100644 --- a/watcher_dashboard/content/audits/tables.py +++ b/watcher_dashboard/content/audits/tables.py @@ -47,6 +47,7 @@ class AuditsFilterAction(horizon.tables.FilterAction): filter_choices = ( ('audit_template', _("Audit Template ="), True), ) + policy_rules = (("infra-optim", "audit:detail"),) class CreateAudit(horizon.tables.LinkAction): @@ -54,13 +55,14 @@ class CreateAudit(horizon.tables.LinkAction): verbose_name = _("Launch Audit") url = "horizon:admin:audits:create" classes = ("ajax-modal", "btn-launch") - # policy_rules = (("compute", "compute:create"),) + policy_rules = (("infra-optim", "audit:create"),) class GoToActionPlan(horizon.tables.Action): name = "go_to_action_plan" verbose_name = _("Go to Action Plan") url = "horizon:admin:action_plans:detail" + policy_rules = (("infra-optim", "action_plan:detail"),) def allowed(self, request, audit): return audit or audit.state in ("SUCCEEEDED", ) @@ -85,6 +87,7 @@ class GoToAuditTemplate(horizon.tables.Action): name = "go_to_audit_template" verbose_name = _("Go to Audit Template") url = "horizon:admin:audit_templates:detail" + policy_rules = (("infra-optim", "audit:get_one"),) # classes = ("ajax-modal", "btn-launch") # icon = "send" diff --git a/watcher_dashboard/content/strategies/tables.py b/watcher_dashboard/content/strategies/tables.py index 0e31e1e..29ed530 100644 --- a/watcher_dashboard/content/strategies/tables.py +++ b/watcher_dashboard/content/strategies/tables.py @@ -26,6 +26,7 @@ class StrategiesFilterAction(horizon.tables.FilterAction): filter_choices = ( ('goal', _("Goal ="), True), ) + policy_rules = (("infra-optim", "strategy:detail"),) class StrategiesTable(horizon.tables.DataTable):