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:
parent
6a52b59c29
commit
4d8c573b1d
@ -9,11 +9,22 @@
|
|||||||
"compute:create:attach_network": "",
|
"compute:create:attach_network": "",
|
||||||
"compute:create:attach_volume": "",
|
"compute:create:attach_volume": "",
|
||||||
"compute:create:forced_host": "is_admin:True",
|
"compute:create:forced_host": "is_admin:True",
|
||||||
|
"compute:delete": "rule:default",
|
||||||
"compute:get_all": "",
|
"compute:get_all": "",
|
||||||
"compute:get_all_tenants": "",
|
"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:unlock_override": "rule:admin_api",
|
||||||
"compute:attach_volume" : "rule:default",
|
"compute:attach_volume" : "rule:default",
|
||||||
"compute:detach_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": "",
|
||||||
"compute:shelve_offload": "",
|
"compute:shelve_offload": "",
|
||||||
|
@ -37,6 +37,13 @@ class MigrateInstance(tables.BatchAction):
|
|||||||
data_type_singular = _("Instance")
|
data_type_singular = _("Instance")
|
||||||
data_type_plural = _("Instances")
|
data_type_plural = _("Instances")
|
||||||
classes = ("btn-migrate", "btn-danger")
|
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):
|
def allowed(self, request, instance):
|
||||||
return ((instance.status in project_tables.ACTIVE_STATES
|
return ((instance.status in project_tables.ACTIVE_STATES
|
||||||
@ -52,6 +59,14 @@ class LiveMigrateInstance(tables.LinkAction):
|
|||||||
verbose_name = _("Live Migrate Instance")
|
verbose_name = _("Live Migrate Instance")
|
||||||
url = "horizon:admin:instances:live_migrate"
|
url = "horizon:admin:instances:live_migrate"
|
||||||
classes = ("ajax-modal", "btn-migrate", "btn-danger")
|
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):
|
def allowed(self, request, instance):
|
||||||
return ((instance.status in project_tables.ACTIVE_STATES)
|
return ((instance.status in project_tables.ACTIVE_STATES)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from django.conf import settings # noqa
|
||||||
from django.core import urlresolvers
|
from django.core import urlresolvers
|
||||||
from django import shortcuts
|
from django import shortcuts
|
||||||
from django import template
|
from django import template
|
||||||
@ -77,6 +78,13 @@ class TerminateInstance(tables.BatchAction):
|
|||||||
data_type_singular = _("Instance")
|
data_type_singular = _("Instance")
|
||||||
data_type_plural = _("Instances")
|
data_type_plural = _("Instances")
|
||||||
classes = ('btn-danger', 'btn-terminate')
|
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):
|
def allowed(self, request, instance=None):
|
||||||
return True
|
return True
|
||||||
@ -92,6 +100,13 @@ class RebootInstance(tables.BatchAction):
|
|||||||
data_type_singular = _("Instance")
|
data_type_singular = _("Instance")
|
||||||
data_type_plural = _("Instances")
|
data_type_plural = _("Instances")
|
||||||
classes = ('btn-danger', 'btn-reboot')
|
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):
|
def allowed(self, request, instance=None):
|
||||||
if instance is not None:
|
if instance is not None:
|
||||||
@ -132,9 +147,19 @@ class TogglePause(tables.BatchAction):
|
|||||||
self.paused = instance.status == "PAUSED"
|
self.paused = instance.status == "PAUSED"
|
||||||
if self.paused:
|
if self.paused:
|
||||||
self.current_present_action = UNPAUSE
|
self.current_present_action = UNPAUSE
|
||||||
|
policy = (("compute", "compute_extension:admin_actions:unpause"),)
|
||||||
else:
|
else:
|
||||||
self.current_present_action = PAUSE
|
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))
|
and not is_deleting(instance))
|
||||||
|
|
||||||
def action(self, request, obj_id):
|
def action(self, request, obj_id):
|
||||||
@ -164,9 +189,19 @@ class ToggleSuspend(tables.BatchAction):
|
|||||||
self.suspended = instance.status == "SUSPENDED"
|
self.suspended = instance.status == "SUSPENDED"
|
||||||
if self.suspended:
|
if self.suspended:
|
||||||
self.current_present_action = RESUME
|
self.current_present_action = RESUME
|
||||||
|
policy = (("compute", "compute_extension:admin_actions:resume"),)
|
||||||
else:
|
else:
|
||||||
self.current_present_action = SUSPEND
|
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))
|
and not is_deleting(instance))
|
||||||
|
|
||||||
def action(self, request, obj_id):
|
def action(self, request, obj_id):
|
||||||
@ -183,6 +218,7 @@ class LaunchLink(tables.LinkAction):
|
|||||||
verbose_name = _("Launch Instance")
|
verbose_name = _("Launch Instance")
|
||||||
url = "horizon:project:instances:launch"
|
url = "horizon:project:instances:launch"
|
||||||
classes = ("btn-launch", "ajax-modal")
|
classes = ("btn-launch", "ajax-modal")
|
||||||
|
policy_rules = (("compute", "compute:create"),)
|
||||||
|
|
||||||
def allowed(self, request, datum):
|
def allowed(self, request, datum):
|
||||||
try:
|
try:
|
||||||
@ -217,6 +253,13 @@ class EditInstance(tables.LinkAction):
|
|||||||
verbose_name = _("Edit Instance")
|
verbose_name = _("Edit Instance")
|
||||||
url = "horizon:project:instances:update"
|
url = "horizon:project:instances:update"
|
||||||
classes = ("ajax-modal", "btn-edit")
|
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):
|
def get_link_url(self, project):
|
||||||
return self._get_link_url(project, 'instance_info')
|
return self._get_link_url(project, 'instance_info')
|
||||||
@ -248,6 +291,13 @@ class CreateSnapshot(tables.LinkAction):
|
|||||||
verbose_name = _("Create Snapshot")
|
verbose_name = _("Create Snapshot")
|
||||||
url = "horizon:project:images_and_snapshots:snapshots:create"
|
url = "horizon:project:images_and_snapshots:snapshots:create"
|
||||||
classes = ("ajax-modal", "btn-camera")
|
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):
|
def allowed(self, request, instance=None):
|
||||||
return instance.status in SNAPSHOT_READY_STATES \
|
return instance.status in SNAPSHOT_READY_STATES \
|
||||||
@ -259,6 +309,13 @@ class ConsoleLink(tables.LinkAction):
|
|||||||
verbose_name = _("Console")
|
verbose_name = _("Console")
|
||||||
url = "horizon:project:instances:detail"
|
url = "horizon:project:instances:detail"
|
||||||
classes = ("btn-console",)
|
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):
|
def allowed(self, request, instance=None):
|
||||||
return instance.status in ACTIVE_STATES and not is_deleting(instance)
|
return instance.status in ACTIVE_STATES and not is_deleting(instance)
|
||||||
@ -275,6 +332,13 @@ class LogLink(tables.LinkAction):
|
|||||||
verbose_name = _("View Log")
|
verbose_name = _("View Log")
|
||||||
url = "horizon:project:instances:detail"
|
url = "horizon:project:instances:detail"
|
||||||
classes = ("btn-log",)
|
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):
|
def allowed(self, request, instance=None):
|
||||||
return instance.status in ACTIVE_STATES and not is_deleting(instance)
|
return instance.status in ACTIVE_STATES and not is_deleting(instance)
|
||||||
@ -291,6 +355,13 @@ class ResizeLink(tables.LinkAction):
|
|||||||
verbose_name = _("Resize Instance")
|
verbose_name = _("Resize Instance")
|
||||||
url = "horizon:project:instances:resize"
|
url = "horizon:project:instances:resize"
|
||||||
classes = ("ajax-modal", "btn-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):
|
def get_link_url(self, project):
|
||||||
return self._get_link_url(project, 'flavor_choice')
|
return self._get_link_url(project, 'flavor_choice')
|
||||||
@ -310,6 +381,13 @@ class ConfirmResize(tables.Action):
|
|||||||
name = "confirm"
|
name = "confirm"
|
||||||
verbose_name = _("Confirm Resize/Migrate")
|
verbose_name = _("Confirm Resize/Migrate")
|
||||||
classes = ("btn-confirm", "btn-action-required")
|
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):
|
def allowed(self, request, instance):
|
||||||
return instance.status == 'VERIFY_RESIZE'
|
return instance.status == 'VERIFY_RESIZE'
|
||||||
@ -322,6 +400,13 @@ class RevertResize(tables.Action):
|
|||||||
name = "revert"
|
name = "revert"
|
||||||
verbose_name = _("Revert Resize/Migrate")
|
verbose_name = _("Revert Resize/Migrate")
|
||||||
classes = ("btn-revert", "btn-action-required")
|
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):
|
def allowed(self, request, instance):
|
||||||
return instance.status == 'VERIFY_RESIZE'
|
return instance.status == 'VERIFY_RESIZE'
|
||||||
@ -335,6 +420,13 @@ class RebuildInstance(tables.LinkAction):
|
|||||||
verbose_name = _("Rebuild Instance")
|
verbose_name = _("Rebuild Instance")
|
||||||
classes = ("btn-rebuild", "ajax-modal")
|
classes = ("btn-rebuild", "ajax-modal")
|
||||||
url = "horizon:project:instances:rebuild"
|
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):
|
def allowed(self, request, instance):
|
||||||
return ((instance.status in ACTIVE_STATES
|
return ((instance.status in ACTIVE_STATES
|
||||||
@ -351,6 +443,13 @@ class AssociateIP(tables.LinkAction):
|
|||||||
verbose_name = _("Associate Floating IP")
|
verbose_name = _("Associate Floating IP")
|
||||||
url = "horizon:project:access_and_security:floating_ips:associate"
|
url = "horizon:project:access_and_security:floating_ips:associate"
|
||||||
classes = ("ajax-modal", "btn-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):
|
def allowed(self, request, instance):
|
||||||
if api.network.floating_ip_simple_associate_supported(request):
|
if api.network.floating_ip_simple_associate_supported(request):
|
||||||
@ -370,6 +469,13 @@ class SimpleAssociateIP(tables.Action):
|
|||||||
name = "associate-simple"
|
name = "associate-simple"
|
||||||
verbose_name = _("Associate Floating IP")
|
verbose_name = _("Associate Floating IP")
|
||||||
classes = ("btn-associate-simple",)
|
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):
|
def allowed(self, request, instance):
|
||||||
if not api.network.floating_ip_simple_associate_supported(request):
|
if not api.network.floating_ip_simple_associate_supported(request):
|
||||||
@ -398,6 +504,13 @@ class SimpleDisassociateIP(tables.Action):
|
|||||||
name = "disassociate"
|
name = "disassociate"
|
||||||
verbose_name = _("Disassociate Floating IP")
|
verbose_name = _("Disassociate Floating IP")
|
||||||
classes = ("btn-danger", "btn-disassociate",)
|
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):
|
def allowed(self, request, instance):
|
||||||
if not conf.HORIZON_CONFIG["simple_ip_management"]:
|
if not conf.HORIZON_CONFIG["simple_ip_management"]:
|
||||||
@ -472,6 +585,13 @@ class StartInstance(tables.BatchAction):
|
|||||||
action_past = _("Started")
|
action_past = _("Started")
|
||||||
data_type_singular = _("Instance")
|
data_type_singular = _("Instance")
|
||||||
data_type_plural = _("Instances")
|
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):
|
def allowed(self, request, instance):
|
||||||
return instance.status in ("SHUTDOWN", "SHUTOFF", "CRASHED")
|
return instance.status in ("SHUTDOWN", "SHUTOFF", "CRASHED")
|
||||||
@ -487,6 +607,13 @@ class StopInstance(tables.BatchAction):
|
|||||||
data_type_singular = _("Instance")
|
data_type_singular = _("Instance")
|
||||||
data_type_plural = _("Instances")
|
data_type_plural = _("Instances")
|
||||||
classes = ('btn-danger',)
|
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):
|
def allowed(self, request, instance):
|
||||||
return ((get_power_state(instance)
|
return ((get_power_state(instance)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user