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:
lin-hua-cheng 2014-01-30 21:01:41 -08:00
parent 491caf0fa9
commit a300c605da
4 changed files with 72 additions and 6 deletions

View 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": ""
}

View File

@ -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".')

View File

@ -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)

View File

@ -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