adding policy checks for nova instance actions

Adding policy rule checks for all Nova instance actions (on both the
project and admin dashboards).

Change-Id: Ibf419ecf6624cf3315ddb10daee0542f7d8d2c3e
Implements: blueprint compute-rbac
This commit is contained in:
Brian DeHamer 2014-01-07 15:09:52 -08:00
parent 6a52b59c29
commit 4d8c573b1d
3 changed files with 155 additions and 2 deletions

View File

@ -9,11 +9,22 @@
"compute:create:attach_network": "",
"compute:create:attach_volume": "",
"compute:create:forced_host": "is_admin:True",
"compute:delete": "rule:default",
"compute:get_all": "",
"compute:get_all_tenants": "",
"compute:reboot": "rule:default",
"compute:rebuild": "rule:default",
"compute:snapshot": "rule:default",
"compute:start": "rule:default",
"compute:stop": "rule:default",
"compute:unlock_override": "rule:admin_api",
"compute:attach_volume" : "rule:default",
"compute:detach_volume" : "rule:default",
"compute:update": "rule:default",
"compute:resize": "rule:default",
"compute:confirm_resize": "rule:default",
"compute:revert_resize": "rule:default",
"compute:shelve": "",
"compute:shelve_offload": "",

View File

@ -37,6 +37,13 @@ class MigrateInstance(tables.BatchAction):
data_type_singular = _("Instance")
data_type_plural = _("Instances")
classes = ("btn-migrate", "btn-danger")
policy_rules = (("compute", "compute_extension:admin_actions:migrate"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return ((instance.status in project_tables.ACTIVE_STATES
@ -52,6 +59,14 @@ class LiveMigrateInstance(tables.LinkAction):
verbose_name = _("Live Migrate Instance")
url = "horizon:admin:instances:live_migrate"
classes = ("ajax-modal", "btn-migrate", "btn-danger")
policy_rules = (
("compute", "compute_extension:admin_actions:migrateLive"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return ((instance.status in project_tables.ACTIVE_STATES)

View File

@ -17,6 +17,7 @@
import logging
from django.conf import settings # noqa
from django.core import urlresolvers
from django import shortcuts
from django import template
@ -77,6 +78,13 @@ class TerminateInstance(tables.BatchAction):
data_type_singular = _("Instance")
data_type_plural = _("Instances")
classes = ('btn-danger', 'btn-terminate')
policy_rules = (("compute", "compute:delete"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
return True
@ -92,6 +100,13 @@ class RebootInstance(tables.BatchAction):
data_type_singular = _("Instance")
data_type_plural = _("Instances")
classes = ('btn-danger', 'btn-reboot')
policy_rules = (("compute", "compute:reboot"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
if instance is not None:
@ -132,9 +147,19 @@ class TogglePause(tables.BatchAction):
self.paused = instance.status == "PAUSED"
if self.paused:
self.current_present_action = UNPAUSE
policy = (("compute", "compute_extension:admin_actions:unpause"),)
else:
self.current_present_action = PAUSE
return ((instance.status in ACTIVE_STATES or self.paused)
policy = (("compute", "compute_extension:admin_actions:pause"),)
has_permission = True
policy_check = getattr(settings, "POLICY_CHECK_FUNCTION", None)
if policy_check:
has_permission = policy_check(policy, request,
target={'project_id': getattr(instance, 'tenant_id', None)})
return (has_permission
and (instance.status in ACTIVE_STATES or self.paused)
and not is_deleting(instance))
def action(self, request, obj_id):
@ -164,9 +189,19 @@ class ToggleSuspend(tables.BatchAction):
self.suspended = instance.status == "SUSPENDED"
if self.suspended:
self.current_present_action = RESUME
policy = (("compute", "compute_extension:admin_actions:resume"),)
else:
self.current_present_action = SUSPEND
return ((instance.status in ACTIVE_STATES or self.suspended)
policy = (("compute", "compute_extension:admin_actions:suspend"),)
has_permission = True
policy_check = getattr(settings, "POLICY_CHECK_FUNCTION", None)
if policy_check:
has_permission = policy_check(policy, request,
target={'project_id': getattr(instance, 'tenant_id', None)})
return (has_permission
and (instance.status in ACTIVE_STATES or self.suspended)
and not is_deleting(instance))
def action(self, request, obj_id):
@ -183,6 +218,7 @@ class LaunchLink(tables.LinkAction):
verbose_name = _("Launch Instance")
url = "horizon:project:instances:launch"
classes = ("btn-launch", "ajax-modal")
policy_rules = (("compute", "compute:create"),)
def allowed(self, request, datum):
try:
@ -217,6 +253,13 @@ class EditInstance(tables.LinkAction):
verbose_name = _("Edit Instance")
url = "horizon:project:instances:update"
classes = ("ajax-modal", "btn-edit")
policy_rules = (("compute", "compute:update"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, project):
return self._get_link_url(project, 'instance_info')
@ -248,6 +291,13 @@ class CreateSnapshot(tables.LinkAction):
verbose_name = _("Create Snapshot")
url = "horizon:project:images_and_snapshots:snapshots:create"
classes = ("ajax-modal", "btn-camera")
policy_rules = (("compute", "compute:snapshot"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
return instance.status in SNAPSHOT_READY_STATES \
@ -259,6 +309,13 @@ class ConsoleLink(tables.LinkAction):
verbose_name = _("Console")
url = "horizon:project:instances:detail"
classes = ("btn-console",)
policy_rules = (("compute", "compute_extension:consoles"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
return instance.status in ACTIVE_STATES and not is_deleting(instance)
@ -275,6 +332,13 @@ class LogLink(tables.LinkAction):
verbose_name = _("View Log")
url = "horizon:project:instances:detail"
classes = ("btn-log",)
policy_rules = (("compute", "compute_extension:console_output"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
return instance.status in ACTIVE_STATES and not is_deleting(instance)
@ -291,6 +355,13 @@ class ResizeLink(tables.LinkAction):
verbose_name = _("Resize Instance")
url = "horizon:project:instances:resize"
classes = ("ajax-modal", "btn-resize")
policy_rules = (("compute", "compute:resize"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, project):
return self._get_link_url(project, 'flavor_choice')
@ -310,6 +381,13 @@ class ConfirmResize(tables.Action):
name = "confirm"
verbose_name = _("Confirm Resize/Migrate")
classes = ("btn-confirm", "btn-action-required")
policy_rules = (("compute", "compute:confirm_resize"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return instance.status == 'VERIFY_RESIZE'
@ -322,6 +400,13 @@ class RevertResize(tables.Action):
name = "revert"
verbose_name = _("Revert Resize/Migrate")
classes = ("btn-revert", "btn-action-required")
policy_rules = (("compute", "compute:revert_resize"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return instance.status == 'VERIFY_RESIZE'
@ -335,6 +420,13 @@ class RebuildInstance(tables.LinkAction):
verbose_name = _("Rebuild Instance")
classes = ("btn-rebuild", "ajax-modal")
url = "horizon:project:instances:rebuild"
policy_rules = (("compute", "compute:rebuild"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return ((instance.status in ACTIVE_STATES
@ -351,6 +443,13 @@ class AssociateIP(tables.LinkAction):
verbose_name = _("Associate Floating IP")
url = "horizon:project:access_and_security:floating_ips:associate"
classes = ("ajax-modal", "btn-associate")
policy_rules = (("compute", "network:associate_floating_ip"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
if api.network.floating_ip_simple_associate_supported(request):
@ -370,6 +469,13 @@ class SimpleAssociateIP(tables.Action):
name = "associate-simple"
verbose_name = _("Associate Floating IP")
classes = ("btn-associate-simple",)
policy_rules = (("compute", "network:associate_floating_ip"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
if not api.network.floating_ip_simple_associate_supported(request):
@ -398,6 +504,13 @@ class SimpleDisassociateIP(tables.Action):
name = "disassociate"
verbose_name = _("Disassociate Floating IP")
classes = ("btn-danger", "btn-disassociate",)
policy_rules = (("compute", "network:disassociate_floating_ip"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
if not conf.HORIZON_CONFIG["simple_ip_management"]:
@ -472,6 +585,13 @@ class StartInstance(tables.BatchAction):
action_past = _("Started")
data_type_singular = _("Instance")
data_type_plural = _("Instances")
policy_rules = (("compute", "compute:start"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return instance.status in ("SHUTDOWN", "SHUTOFF", "CRASHED")
@ -487,6 +607,13 @@ class StopInstance(tables.BatchAction):
data_type_singular = _("Instance")
data_type_plural = _("Instances")
classes = ('btn-danger',)
policy_rules = (("compute", "compute:stop"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return ((get_power_state(instance)