Adding policy checks for glance
Additionally, added the missing policy checks on Image panel. Change-Id: Ia9fa2fcdfb12f97ff27150a69d964be47ab717cf Implements: blueprint image-rbac
This commit is contained in:
parent
491caf0fa9
commit
a300c605da
33
openstack_dashboard/conf/glance_policy.json
Normal file
33
openstack_dashboard/conf/glance_policy.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"context_is_admin": "role:admin",
|
||||
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
|
||||
"default": "rule:admin_or_owner",
|
||||
|
||||
"add_image": "",
|
||||
"delete_image": "rule:admin_or_owner",
|
||||
"get_image": "",
|
||||
"get_images": "",
|
||||
"modify_image": "rule:admin_or_owner",
|
||||
"publicize_image": "",
|
||||
"copy_from": "",
|
||||
|
||||
"download_image": "",
|
||||
"upload_image": "",
|
||||
|
||||
"delete_image_location": "",
|
||||
"get_image_location": "",
|
||||
"set_image_location": "",
|
||||
|
||||
"add_member": "",
|
||||
"delete_member": "",
|
||||
"get_member": "",
|
||||
"get_members": "",
|
||||
"modify_member": "",
|
||||
|
||||
"manage_image_cache": "role:admin",
|
||||
|
||||
"get_task": "",
|
||||
"get_tasks": "",
|
||||
"add_task": "",
|
||||
"modify_task": ""
|
||||
}
|
@ -31,6 +31,7 @@ from horizon import forms
|
||||
from horizon import messages
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard import policy
|
||||
|
||||
|
||||
IMAGE_BACKEND_SETTINGS = getattr(settings, 'OPENSTACK_IMAGE_BACKEND', {})
|
||||
@ -45,6 +46,7 @@ class CreateImageForm(forms.SelfHandlingForm):
|
||||
|
||||
source_type = forms.ChoiceField(
|
||||
label=_('Image Source'),
|
||||
required=False,
|
||||
choices=[('url', _('Image Location')),
|
||||
('file', _('Image File'))],
|
||||
widget=forms.Select(attrs={
|
||||
@ -91,10 +93,15 @@ class CreateImageForm(forms.SelfHandlingForm):
|
||||
is_public = forms.BooleanField(label=_("Public"), required=False)
|
||||
protected = forms.BooleanField(label=_("Protected"), required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CreateImageForm, self).__init__(*args, **kwargs)
|
||||
if not settings.HORIZON_IMAGES_ALLOW_UPLOAD:
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(CreateImageForm, self).__init__(request, *args, **kwargs)
|
||||
if (not settings.HORIZON_IMAGES_ALLOW_UPLOAD or
|
||||
not policy.check((("image", "upload_image"),), request)):
|
||||
self._hide_file_source_type()
|
||||
if not policy.check((("image", "set_image_location"),), request):
|
||||
self._hide_url_source_type()
|
||||
if not policy.check((("image", "publicize_image"),), request):
|
||||
self._hide_is_public()
|
||||
self.fields['disk_format'].choices = IMAGE_FORMAT_CHOICES
|
||||
|
||||
def _hide_file_source_type(self):
|
||||
@ -105,17 +112,30 @@ class CreateImageForm(forms.SelfHandlingForm):
|
||||
if len(source_type.choices) == 1:
|
||||
source_type.widget = HiddenInput()
|
||||
|
||||
def _hide_url_source_type(self):
|
||||
self.fields['copy_from'].widget = HiddenInput()
|
||||
source_type = self.fields['source_type']
|
||||
source_type.choices = [choice for choice in source_type.choices
|
||||
if choice[0] != 'url']
|
||||
if len(source_type.choices) == 1:
|
||||
source_type.widget = HiddenInput()
|
||||
|
||||
def _hide_is_public(self):
|
||||
self.fields['is_public'].widget = HiddenInput()
|
||||
self.fields['is_public'].initial = False
|
||||
|
||||
def clean(self):
|
||||
data = super(CreateImageForm, self).clean()
|
||||
|
||||
# The image_file key can be missing based on particular upload
|
||||
# conditions. Code defensively for it here...
|
||||
image_file = data.get('image_file', None)
|
||||
image_url = data.get('copy_from', None)
|
||||
|
||||
if not data['copy_from'] and not image_file:
|
||||
if not image_url and not image_file:
|
||||
raise ValidationError(
|
||||
_("A image or external image location must be specified."))
|
||||
elif data['copy_from'] and image_file:
|
||||
elif image_url and image_file:
|
||||
raise ValidationError(
|
||||
_("Can not specify both image and external image location."))
|
||||
else:
|
||||
@ -146,6 +166,7 @@ class CreateImageForm(forms.SelfHandlingForm):
|
||||
if data['architecture']:
|
||||
meta['properties']['architecture'] = data['architecture']
|
||||
if (settings.HORIZON_IMAGES_ALLOW_UPLOAD and
|
||||
policy.check((("image", "upload_image"),), request) and
|
||||
data.get('image_file', None)):
|
||||
meta['data'] = self.files['image_file']
|
||||
else:
|
||||
@ -188,6 +209,12 @@ class UpdateImageForm(forms.SelfHandlingForm):
|
||||
public = forms.BooleanField(label=_("Public"), required=False)
|
||||
protected = forms.BooleanField(label=_("Protected"), required=False)
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateImageForm, self).__init__(request, *args, **kwargs)
|
||||
if not policy.check((("image", "publicize_image"),), request):
|
||||
self.fields['public'].widget = forms.CheckboxInput(
|
||||
attrs={'readonly': 'readonly'})
|
||||
|
||||
def handle(self, request, data):
|
||||
image_id = data['image_id']
|
||||
error_updating = _('Unable to update image "%s".')
|
||||
|
@ -36,6 +36,7 @@ class LaunchImage(tables.LinkAction):
|
||||
verbose_name = _("Launch")
|
||||
url = "horizon:project:instances:launch"
|
||||
classes = ("btn-launch", "ajax-modal")
|
||||
policy_rules = (("compute", "compute:create"),)
|
||||
|
||||
def get_link_url(self, datum):
|
||||
base_url = reverse(self.url)
|
||||
@ -58,6 +59,7 @@ class LaunchImage(tables.LinkAction):
|
||||
class DeleteImage(tables.DeleteAction):
|
||||
data_type_singular = _("Image")
|
||||
data_type_plural = _("Images")
|
||||
policy_rules = (("image", "delete_image"),)
|
||||
|
||||
def allowed(self, request, image=None):
|
||||
# Protected images can not be deleted.
|
||||
@ -77,6 +79,7 @@ class CreateImage(tables.LinkAction):
|
||||
verbose_name = _("Create Image")
|
||||
url = "horizon:project:images_and_snapshots:images:create"
|
||||
classes = ("ajax-modal", "btn-create")
|
||||
policy_rules = (("image", "add_image"),)
|
||||
|
||||
|
||||
class EditImage(tables.LinkAction):
|
||||
@ -84,6 +87,7 @@ class EditImage(tables.LinkAction):
|
||||
verbose_name = _("Edit")
|
||||
url = "horizon:project:images_and_snapshots:images:update"
|
||||
classes = ("ajax-modal", "btn-edit")
|
||||
policy_rules = (("image", "modify_image"),)
|
||||
|
||||
def allowed(self, request, image=None):
|
||||
if image:
|
||||
@ -99,6 +103,7 @@ class CreateVolumeFromImage(tables.LinkAction):
|
||||
verbose_name = _("Create Volume")
|
||||
url = "horizon:project:volumes:create"
|
||||
classes = ("ajax-modal", "btn-camera")
|
||||
policy_rules = (("volume", "volume:create"),)
|
||||
|
||||
def get_link_url(self, datum):
|
||||
base_url = reverse(self.url)
|
||||
|
@ -209,7 +209,8 @@ POLICY_FILES_PATH = os.path.join(ROOT_PATH, "conf")
|
||||
POLICY_FILES = {
|
||||
'identity': 'keystone_policy.json',
|
||||
'compute': 'nova_policy.json',
|
||||
'volume': 'cinder_policy.json'
|
||||
'volume': 'cinder_policy.json',
|
||||
'image': 'glance_policy.json',
|
||||
}
|
||||
|
||||
SECRET_KEY = None
|
||||
|
Loading…
Reference in New Issue
Block a user