Commit 3ec83939 by Belákovics Ádám

Merge branch 'instance_auth' into 'DEV'

Instance auth

See merge request !17
parents c0d7f992 befe5fa1
Pipeline #862 passed with stage
in 1 minute 22 seconds
...@@ -17,6 +17,7 @@ django-cors-headers = "*" ...@@ -17,6 +17,7 @@ django-cors-headers = "*"
openstacksdk = "*" openstacksdk = "*"
python-novaclient = "*" python-novaclient = "*"
keystoneauth1 = "*" keystoneauth1 = "*"
django-guardian = "*"
djoser = "*" djoser = "*"
[requires] [requires]
......
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "8cb2efb1cfa79de96297c90953faf757011ca1f1ff4784ac05226a249001e1f5" "sha256": "dd7bfbb33d07cbcc96d1f3b1f838538dba41f3eb0bf5279381714b4b9abf90d7"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
...@@ -135,6 +135,14 @@ ...@@ -135,6 +135,14 @@
"index": "pypi", "index": "pypi",
"version": "==3.0.2" "version": "==3.0.2"
}, },
"django-guardian": {
"hashes": [
"sha256:965d3a1e20fb3639e0ab16b0e768611f694c02d762916f80d9f3f7520c16aa7b",
"sha256:e8c4556c4e145028a5dcfd7b2611d52e1ac104af562017ce17c3f67e47a62693"
],
"index": "pypi",
"version": "==2.0.0"
},
"django-templated-mail": { "django-templated-mail": {
"hashes": [ "hashes": [
"sha256:8db807effebb42a532622e2d142dfd453dafcd0d7794c4c3332acb90656315f9", "sha256:8db807effebb42a532622e2d142dfd453dafcd0d7794c4c3332acb90656315f9",
......
from django.contrib.auth.models import Permission
from django.contrib import admin
admin.site.register(Permission)
from django.apps import AppConfig
class AuthorizationConfig(AppConfig):
name = 'authorization'
from guardian.shortcuts import get_objects_for_user
import logging
logger = logging.getLogger(__name__)
class AuthorizationMixin():
authorization = {}
def get_objects_with_perms(self, user, method, instance):
auth_params = self.authorization[method]
if auth_params:
return get_objects_for_user(user, auth_params["filter"], instance)
else:
logger.error(f"Invalid method for authorization: {method}")
return False
def has_perms_for_object(self, user, method, instance):
auth_params = self.authorization[method]
if auth_params:
for perm in auth_params["object"]:
if not user.has_perm(perm, instance):
return False
return True
else:
logger.error(f"Invalid method for authorization: {method}")
return False
def has_perms_for_model(self, user, method):
auth_params = self.authorization[method]
if auth_params:
for perm in auth_params["model"]:
if not user.has_perm(perm):
return False
return True
else:
logger.error(f"Invalid method for authorization: {method}")
return False
...@@ -2,6 +2,13 @@ from django.contrib import admin ...@@ -2,6 +2,13 @@ from django.contrib import admin
from instance.models import Instance, Flavor, Lease from instance.models import Instance, Flavor, Lease
admin.site.register(Instance) from guardian.admin import GuardedModelAdmin
class InstanceAdmin(GuardedModelAdmin):
pass
admin.site.register(Instance, InstanceAdmin)
admin.site.register(Flavor) admin.site.register(Flavor)
admin.site.register(Lease) admin.site.register(Lease)
[{"model": "contenttypes.contenttype", "pk": 1, "fields": {"app_label": "admin", "model": "logentry"}}, {"model": "contenttypes.contenttype", "pk": 2, "fields": {"app_label": "auth", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 3, "fields": {"app_label": "auth", "model": "group"}}, {"model": "contenttypes.contenttype", "pk": 4, "fields": {"app_label": "auth", "model": "user"}}, {"model": "contenttypes.contenttype", "pk": 5, "fields": {"app_label": "contenttypes", "model": "contenttype"}}, {"model": "contenttypes.contenttype", "pk": 6, "fields": {"app_label": "sessions", "model": "session"}}, {"model": "contenttypes.contenttype", "pk": 7, "fields": {"app_label": "authtoken", "model": "token"}}, {"model": "contenttypes.contenttype", "pk": 8, "fields": {"app_label": "guardian", "model": "groupobjectpermission"}}, {"model": "contenttypes.contenttype", "pk": 9, "fields": {"app_label": "guardian", "model": "userobjectpermission"}}, {"model": "contenttypes.contenttype", "pk": 10, "fields": {"app_label": "image", "model": "disk"}}, {"model": "contenttypes.contenttype", "pk": 11, "fields": {"app_label": "image", "model": "image"}}, {"model": "contenttypes.contenttype", "pk": 12, "fields": {"app_label": "instance", "model": "instance"}}, {"model": "contenttypes.contenttype", "pk": 13, "fields": {"app_label": "instance", "model": "flavor"}}, {"model": "contenttypes.contenttype", "pk": 14, "fields": {"app_label": "instance", "model": "lease"}}, {"model": "contenttypes.contenttype", "pk": 15, "fields": {"app_label": "template", "model": "basetemplate"}}, {"model": "contenttypes.contenttype", "pk": 16, "fields": {"app_label": "template", "model": "disktemplate"}}, {"model": "contenttypes.contenttype", "pk": 17, "fields": {"app_label": "template", "model": "imagetemplate"}}, {"model": "sessions.session", "pk": "70jxjk2wd7gvxd4u8nnf1e1l3ie7u3os", "fields": {"session_data": "NjE4NzBkZjdiYWIwNzNkYjg0MmFjMjBkMzI3OWRmYzc5YmNiNzFjYzp7Il9hdXRoX3VzZXJfaWQiOiIyIiwiX2F1dGhfdXNlcl9iYWNrZW5kIjoiZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmQiLCJfYXV0aF91c2VyX2hhc2giOiJhNzg5YTA3MjkxZmI1ODU1MWM5YWFjNWVjZDhiZmViZjQ4NDkyOWE1In0=", "expire_date": "2019-08-22T11:39:55.803Z"}}, {"model": "sessions.session", "pk": "7akwvw78xjpvkoc1w6mhco170q7ohx81", "fields": {"session_data": "ZjhlY2Q2YzVjNzU3YWUwZjFiNDMzNzg2Mjg0Yjk5OThlYTVmMGNiNzp7Il9hdXRoX3VzZXJfaWQiOiI0IiwiX2F1dGhfdXNlcl9iYWNrZW5kIjoiZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmQiLCJfYXV0aF91c2VyX2hhc2giOiIyMjY4MmMzNzkxZWJjMjIzNjc5NjBhMzU3NmVlMWRhOGIzN2Y4ODkzIn0=", "expire_date": "2019-08-22T12:06:51.022Z"}}, {"model": "sessions.session", "pk": "8ckz81gn9rivtw3zdcqkfup4lznnh244", "fields": {"session_data": "NjE4NzBkZjdiYWIwNzNkYjg0MmFjMjBkMzI3OWRmYzc5YmNiNzFjYzp7Il9hdXRoX3VzZXJfaWQiOiIyIiwiX2F1dGhfdXNlcl9iYWNrZW5kIjoiZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmQiLCJfYXV0aF91c2VyX2hhc2giOiJhNzg5YTA3MjkxZmI1ODU1MWM5YWFjNWVjZDhiZmViZjQ4NDkyOWE1In0=", "expire_date": "2019-08-22T12:03:59.108Z"}}, {"model": "sessions.session", "pk": "jy21e8ygksos3pvb5t5dfilu1s94b0s2", "fields": {"session_data": "NjE4NzBkZjdiYWIwNzNkYjg0MmFjMjBkMzI3OWRmYzc5YmNiNzFjYzp7Il9hdXRoX3VzZXJfaWQiOiIyIiwiX2F1dGhfdXNlcl9iYWNrZW5kIjoiZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmQiLCJfYXV0aF91c2VyX2hhc2giOiJhNzg5YTA3MjkxZmI1ODU1MWM5YWFjNWVjZDhiZmViZjQ4NDkyOWE1In0=", "expire_date": "2019-08-22T12:01:49.707Z"}}, {"model": "sessions.session", "pk": "qtpmb6wp5qvslpv465tnm4n23963n6ig", "fields": {"session_data": "ZjhlY2Q2YzVjNzU3YWUwZjFiNDMzNzg2Mjg0Yjk5OThlYTVmMGNiNzp7Il9hdXRoX3VzZXJfaWQiOiI0IiwiX2F1dGhfdXNlcl9iYWNrZW5kIjoiZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmQiLCJfYXV0aF91c2VyX2hhc2giOiIyMjY4MmMzNzkxZWJjMjIzNjc5NjBhMzU3NmVlMWRhOGIzN2Y4ODkzIn0=", "expire_date": "2019-08-22T12:10:15.304Z"}}, {"model": "image.disk", "pk": 1, "fields": {"name": "Ubuntu 18.04", "remote_id": "bfc3fbdc-c4b8-46a5-8e71-feca9ba379f5"}}, {"model": "instance.lease", "pk": 1, "fields": {"name": "project", "description": "Project", "suspend_interval_in_sec": 50000, "delete_interval_in_sec": 50000}}, {"model": "instance.flavor", "pk": 1, "fields": {"name": "small", "description": "Small flavor", "remote_id": "d1", "ram": 512, "vcpu": 1, "initial_disk": 5, "priority": 1}}, {"model": "auth.permission", "pk": 1, "fields": {"name": "Can add log entry", "content_type": 1, "codename": "add_logentry"}}, {"model": "auth.permission", "pk": 2, "fields": {"name": "Can change log entry", "content_type": 1, "codename": "change_logentry"}}, {"model": "auth.permission", "pk": 3, "fields": {"name": "Can delete log entry", "content_type": 1, "codename": "delete_logentry"}}, {"model": "auth.permission", "pk": 4, "fields": {"name": "Can view log entry", "content_type": 1, "codename": "view_logentry"}}, {"model": "auth.permission", "pk": 5, "fields": {"name": "Can add permission", "content_type": 2, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 6, "fields": {"name": "Can change permission", "content_type": 2, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 7, "fields": {"name": "Can delete permission", "content_type": 2, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 8, "fields": {"name": "Can view permission", "content_type": 2, "codename": "view_permission"}}, {"model": "auth.permission", "pk": 9, "fields": {"name": "Can add group", "content_type": 3, "codename": "add_group"}}, {"model": "auth.permission", "pk": 10, "fields": {"name": "Can change group", "content_type": 3, "codename": "change_group"}}, {"model": "auth.permission", "pk": 11, "fields": {"name": "Can delete group", "content_type": 3, "codename": "delete_group"}}, {"model": "auth.permission", "pk": 12, "fields": {"name": "Can view group", "content_type": 3, "codename": "view_group"}}, {"model": "auth.permission", "pk": 13, "fields": {"name": "Can add user", "content_type": 4, "codename": "add_user"}}, {"model": "auth.permission", "pk": 14, "fields": {"name": "Can change user", "content_type": 4, "codename": "change_user"}}, {"model": "auth.permission", "pk": 15, "fields": {"name": "Can delete user", "content_type": 4, "codename": "delete_user"}}, {"model": "auth.permission", "pk": 16, "fields": {"name": "Can view user", "content_type": 4, "codename": "view_user"}}, {"model": "auth.permission", "pk": 17, "fields": {"name": "Can add content type", "content_type": 5, "codename": "add_contenttype"}}, {"model": "auth.permission", "pk": 18, "fields": {"name": "Can change content type", "content_type": 5, "codename": "change_contenttype"}}, {"model": "auth.permission", "pk": 19, "fields": {"name": "Can delete content type", "content_type": 5, "codename": "delete_contenttype"}}, {"model": "auth.permission", "pk": 20, "fields": {"name": "Can view content type", "content_type": 5, "codename": "view_contenttype"}}, {"model": "auth.permission", "pk": 21, "fields": {"name": "Can add session", "content_type": 6, "codename": "add_session"}}, {"model": "auth.permission", "pk": 22, "fields": {"name": "Can change session", "content_type": 6, "codename": "change_session"}}, {"model": "auth.permission", "pk": 23, "fields": {"name": "Can delete session", "content_type": 6, "codename": "delete_session"}}, {"model": "auth.permission", "pk": 24, "fields": {"name": "Can view session", "content_type": 6, "codename": "view_session"}}, {"model": "auth.permission", "pk": 25, "fields": {"name": "Can add Token", "content_type": 7, "codename": "add_token"}}, {"model": "auth.permission", "pk": 26, "fields": {"name": "Can change Token", "content_type": 7, "codename": "change_token"}}, {"model": "auth.permission", "pk": 27, "fields": {"name": "Can delete Token", "content_type": 7, "codename": "delete_token"}}, {"model": "auth.permission", "pk": 28, "fields": {"name": "Can view Token", "content_type": 7, "codename": "view_token"}}, {"model": "auth.permission", "pk": 29, "fields": {"name": "Can add group object permission", "content_type": 8, "codename": "add_groupobjectpermission"}}, {"model": "auth.permission", "pk": 30, "fields": {"name": "Can change group object permission", "content_type": 8, "codename": "change_groupobjectpermission"}}, {"model": "auth.permission", "pk": 31, "fields": {"name": "Can delete group object permission", "content_type": 8, "codename": "delete_groupobjectpermission"}}, {"model": "auth.permission", "pk": 32, "fields": {"name": "Can view group object permission", "content_type": 8, "codename": "view_groupobjectpermission"}}, {"model": "auth.permission", "pk": 33, "fields": {"name": "Can add user object permission", "content_type": 9, "codename": "add_userobjectpermission"}}, {"model": "auth.permission", "pk": 34, "fields": {"name": "Can change user object permission", "content_type": 9, "codename": "change_userobjectpermission"}}, {"model": "auth.permission", "pk": 35, "fields": {"name": "Can delete user object permission", "content_type": 9, "codename": "delete_userobjectpermission"}}, {"model": "auth.permission", "pk": 36, "fields": {"name": "Can view user object permission", "content_type": 9, "codename": "view_userobjectpermission"}}, {"model": "auth.permission", "pk": 37, "fields": {"name": "Can add disk", "content_type": 10, "codename": "add_disk"}}, {"model": "auth.permission", "pk": 38, "fields": {"name": "Can change disk", "content_type": 10, "codename": "change_disk"}}, {"model": "auth.permission", "pk": 39, "fields": {"name": "Can delete disk", "content_type": 10, "codename": "delete_disk"}}, {"model": "auth.permission", "pk": 40, "fields": {"name": "Can view disk", "content_type": 10, "codename": "view_disk"}}, {"model": "auth.permission", "pk": 41, "fields": {"name": "Can add image", "content_type": 11, "codename": "add_image"}}, {"model": "auth.permission", "pk": 42, "fields": {"name": "Can change image", "content_type": 11, "codename": "change_image"}}, {"model": "auth.permission", "pk": 43, "fields": {"name": "Can delete image", "content_type": 11, "codename": "delete_image"}}, {"model": "auth.permission", "pk": 44, "fields": {"name": "Can view image", "content_type": 11, "codename": "view_image"}}, {"model": "auth.permission", "pk": 45, "fields": {"name": "Can add instance", "content_type": 12, "codename": "add_instance"}}, {"model": "auth.permission", "pk": 46, "fields": {"name": "Can change instance", "content_type": 12, "codename": "change_instance"}}, {"model": "auth.permission", "pk": 47, "fields": {"name": "Can delete instance", "content_type": 12, "codename": "delete_instance"}}, {"model": "auth.permission", "pk": 48, "fields": {"name": "Can view instance", "content_type": 12, "codename": "view_instance"}}, {"model": "auth.permission", "pk": 49, "fields": {"name": "Can create a new VM.", "content_type": 12, "codename": "create_instance"}}, {"model": "auth.permission", "pk": 50, "fields": {"name": "Can access the VM connection info.", "content_type": 12, "codename": "use_instance"}}, {"model": "auth.permission", "pk": 51, "fields": {"name": "Can use basic lifecycle methods of the VM.", "content_type": 12, "codename": "operate_instance"}}, {"model": "auth.permission", "pk": 52, "fields": {"name": "Can delete VM.", "content_type": 12, "codename": "administer_instance"}}, {"model": "auth.permission", "pk": 53, "fields": {"name": "Can access the graphical console of a VM.", "content_type": 12, "codename": "access_console"}}, {"model": "auth.permission", "pk": 54, "fields": {"name": "Can change resources of a VM.", "content_type": 12, "codename": "change_resources"}}, {"model": "auth.permission", "pk": 55, "fields": {"name": "Can manage access rights for the VM.", "content_type": 12, "codename": "manage_access"}}, {"model": "auth.permission", "pk": 56, "fields": {"name": "Can configure port forwards.", "content_type": 12, "codename": "config_ports"}}, {"model": "auth.permission", "pk": 57, "fields": {"name": "Can add flavor", "content_type": 13, "codename": "add_flavor"}}, {"model": "auth.permission", "pk": 58, "fields": {"name": "Can change flavor", "content_type": 13, "codename": "change_flavor"}}, {"model": "auth.permission", "pk": 59, "fields": {"name": "Can delete flavor", "content_type": 13, "codename": "delete_flavor"}}, {"model": "auth.permission", "pk": 60, "fields": {"name": "Can view flavor", "content_type": 13, "codename": "view_flavor"}}, {"model": "auth.permission", "pk": 61, "fields": {"name": "Can add lease", "content_type": 14, "codename": "add_lease"}}, {"model": "auth.permission", "pk": 62, "fields": {"name": "Can change lease", "content_type": 14, "codename": "change_lease"}}, {"model": "auth.permission", "pk": 63, "fields": {"name": "Can delete lease", "content_type": 14, "codename": "delete_lease"}}, {"model": "auth.permission", "pk": 64, "fields": {"name": "Can view lease", "content_type": 14, "codename": "view_lease"}}, {"model": "auth.permission", "pk": 65, "fields": {"name": "Can add base template", "content_type": 15, "codename": "add_basetemplate"}}, {"model": "auth.permission", "pk": 66, "fields": {"name": "Can change base template", "content_type": 15, "codename": "change_basetemplate"}}, {"model": "auth.permission", "pk": 67, "fields": {"name": "Can delete base template", "content_type": 15, "codename": "delete_basetemplate"}}, {"model": "auth.permission", "pk": 68, "fields": {"name": "Can view base template", "content_type": 15, "codename": "view_basetemplate"}}, {"model": "auth.permission", "pk": 69, "fields": {"name": "Can add disk template", "content_type": 16, "codename": "add_disktemplate"}}, {"model": "auth.permission", "pk": 70, "fields": {"name": "Can change disk template", "content_type": 16, "codename": "change_disktemplate"}}, {"model": "auth.permission", "pk": 71, "fields": {"name": "Can delete disk template", "content_type": 16, "codename": "delete_disktemplate"}}, {"model": "auth.permission", "pk": 72, "fields": {"name": "Can view disk template", "content_type": 16, "codename": "view_disktemplate"}}, {"model": "auth.permission", "pk": 73, "fields": {"name": "Can add image template", "content_type": 17, "codename": "add_imagetemplate"}}, {"model": "auth.permission", "pk": 74, "fields": {"name": "Can change image template", "content_type": 17, "codename": "change_imagetemplate"}}, {"model": "auth.permission", "pk": 75, "fields": {"name": "Can delete image template", "content_type": 17, "codename": "delete_imagetemplate"}}, {"model": "auth.permission", "pk": 76, "fields": {"name": "Can view image template", "content_type": 17, "codename": "view_imagetemplate"}}, {"model": "auth.user", "pk": 1, "fields": {"password": "!BkKh1MBK4GmVoZLeBl2gweVrtiyarSrzocRHRQG8", "last_login": null, "is_superuser": false, "username": "AnonymousUser", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2019-08-07T12:48:40.789Z", "groups": [], "user_permissions": []}}, {"model": "auth.user", "pk": 4, "fields": {"password": "pbkdf2_sha256$150000$X00LpQFVuMGm$WaLxx98j+zyF4fG1b7YPCghE6eCDCyM+2NvkUEJbvIM=", "last_login": "2019-08-08T12:10:15.298Z", "is_superuser": true, "username": "admin", "first_name": "", "last_name": "", "email": "admin@recircle.bme.hu", "is_staff": true, "is_active": true, "date_joined": "2019-08-08T12:06:33.109Z", "groups": [], "user_permissions": []}}, {"model": "guardian.userobjectpermission", "pk": 1, "fields": {"permission": 47, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 2, "fields": {"permission": 54, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 3, "fields": {"permission": 56, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 4, "fields": {"permission": 46, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 5, "fields": {"permission": 51, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 6, "fields": {"permission": 50, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 7, "fields": {"permission": 55, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 8, "fields": {"permission": 53, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 9, "fields": {"permission": 48, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 10, "fields": {"permission": 52, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 11, "fields": {"permission": 45, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "guardian.userobjectpermission", "pk": 12, "fields": {"permission": 49, "content_type": 12, "object_pk": "1", "user": 4}}, {"model": "image.image", "pk": 1, "fields": {"name": "Ubuntu 18.04", "description": "", "remote_id": "9520a513-6e2d-4059-80c6-1afd1fbfe24d", "created_at": "2019-08-08T12:05:31.288Z", "uploaded_by_user": true, "created_by": 4}}, {"model": "instance.instance", "pk": 1, "fields": {"name": "Uborka", "remote_id": "92d7264a-1292-4c4e-a8d8-4dcef086d7c6", "description": "Uborka", "access_method": "ssh", "system": "ubuntu", "password": "12345", "time_of_suspend": "2019-08-09T02:04:12.768Z", "time_of_delete": "2019-08-09T02:04:12.768Z", "deleted": false, "template": 1, "owner": 4, "flavor": 1, "lease": 1, "disks": [1]}}, {"model": "template.basetemplate", "pk": 1, "fields": {"name": "Uborka template", "description": "", "created_at": "2019-08-08T12:09:20.290Z", "created_by": 4, "flavor": 1, "lease": 1, "network_id": null}}, {"model": "template.imagetemplate", "pk": 1, "fields": {"image": 1, "type": "U"}}, {"model": "admin.logentry", "pk": 5, "fields": {"action_time": "2019-08-08T12:07:02.809Z", "user": 4, "content_type": 4, "object_id": "2", "object_repr": "adam", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 6, "fields": {"action_time": "2019-08-08T12:07:02.815Z", "user": 4, "content_type": 4, "object_id": "3", "object_repr": "adam2", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 7, "fields": {"action_time": "2019-08-08T12:07:33.903Z", "user": 4, "content_type": 11, "object_id": "1", "object_repr": "Image object (1)", "action_flag": 2, "change_message": "[{\"changed\": {\"fields\": [\"created_by\"]}}]"}}, {"model": "admin.logentry", "pk": 8, "fields": {"action_time": "2019-08-08T12:07:57.845Z", "user": 4, "content_type": 4, "object_id": "2", "object_repr": "adam", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 9, "fields": {"action_time": "2019-08-08T12:07:57.852Z", "user": 4, "content_type": 4, "object_id": "3", "object_repr": "adam2", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 10, "fields": {"action_time": "2019-08-08T12:09:20.292Z", "user": 4, "content_type": 17, "object_id": "1", "object_repr": "ImageTemplate object (1)", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}, {"model": "admin.logentry", "pk": 11, "fields": {"action_time": "2019-08-08T12:10:52.773Z", "user": 4, "content_type": 12, "object_id": "1", "object_repr": "Instance object (1)", "action_flag": 1, "change_message": "[{\"added\": {}}]"}}]
\ No newline at end of file
# Generated by Django 2.2.4 on 2019-08-08 11:37
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('instance', '0010_instance_template'),
]
operations = [
migrations.AlterModelOptions(
name='instance',
options={'permissions': (('create_instance', 'Can create a new VM.'), ('use_instance', 'Can access the VM connection info.'), ('operate_instance', 'Can use basic lifecycle methods of the VM.'), ('administer_instance', 'Can delete VM.'), ('access_console', 'Can access the graphical console of a VM.'), ('change_resources', 'Can change resources of a VM.'), ('manage_access', 'Can manage access rights for the VM.'), ('config_ports', 'Can configure port forwards.'))},
),
]
# Generated by Django 2.2.4 on 2019-08-29 07:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('instance', '0011_auto_20190808_1137'),
]
operations = [
migrations.AlterModelOptions(
name='instance',
options={'default_permissions': (), 'permissions': (('create_instance', 'Can create a new VM.'), ('use_instance', 'Can access the VM connection info.'), ('operate_instance', 'Can use basic lifecycle methods of the VM.'), ('administer_instance', 'Can delete VM.'), ('access_console', 'Can access the graphical console of a VM.'), ('change_resources', 'Can change resources of a VM.'), ('manage_access', 'Can manage access rights for the VM.'), ('config_ports', 'Can configure port forwards.'))},
),
]
# Generated by Django 2.2.4 on 2019-08-30 12:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('instance', '0012_auto_20190829_0754'),
]
operations = [
migrations.AlterModelOptions(
name='instance',
options={'default_permissions': (), 'permissions': (('create_instance', 'Can create a new VM.'), ('create_template_from_instance', 'Can create template from instance.'), ('use_instance', 'Can access the VM connection info.'), ('operate_instance', 'Can use basic lifecycle methods of the VM.'), ('administer_instance', 'Can delete VM.'), ('access_console', 'Can access the graphical console of a VM.'), ('change_resources', 'Can change resources of a VM.'), ('manage_access', 'Can manage access rights for the VM.'), ('config_ports', 'Can configure port forwards.'))},
),
]
...@@ -6,7 +6,7 @@ from datetime import timedelta ...@@ -6,7 +6,7 @@ from datetime import timedelta
from image.models import Disk from image.models import Disk
from interface_openstack.implementation.vm.instance import ( from interface_openstack.implementation.vm.instance import (
OSVirtualMachineManager OSVirtualMachineManager
) )
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -82,6 +82,20 @@ class Instance(models.Model): ...@@ -82,6 +82,20 @@ class Instance(models.Model):
""" """
from template.models import ImageTemplate from template.models import ImageTemplate
class Meta:
default_permissions = ()
permissions = (
('create_instance', 'Can create a new VM.'),
('create_template_from_instance', 'Can create template from instance.'),
('use_instance', 'Can access the VM connection info.'),
('operate_instance', 'Can use basic lifecycle methods of the VM.'),
('administer_instance', 'Can delete VM.'),
('access_console', 'Can access the graphical console of a VM.'),
('change_resources', 'Can change resources of a VM.'),
('manage_access', 'Can manage access rights for the VM.'),
('config_ports', 'Can configure port forwards.'),
)
name = models.CharField(max_length=100, name = models.CharField(max_length=100,
help_text="Human readable name of instance") help_text="Human readable name of instance")
...@@ -172,6 +186,16 @@ class Instance(models.Model): ...@@ -172,6 +186,16 @@ class Instance(models.Model):
seconds=lease.delete_interval_in_sec) seconds=lease.delete_interval_in_sec)
) )
def renew(self, lease=None):
"""Renew virtual machine, if a new lease is provided it changes it as well.
"""
if lease is None:
lease = self.lease
else:
self.lease = lease
self.time_of_suspend, self.time_of_delete = self.get_renew_times(lease)
self.save()
def delete(self): def delete(self):
try: try:
interface.destroy_vm(self.remote_id) interface.destroy_vm(self.remote_id)
...@@ -194,3 +218,11 @@ class Instance(models.Model): ...@@ -194,3 +218,11 @@ class Instance(models.Model):
return User.objects.make_random_password( return User.objects.make_random_password(
allowed_chars='abcdefghijklmnopqrstuvwx' allowed_chars='abcdefghijklmnopqrstuvwx'
'ABCDEFGHIJKLMNOPQRSTUVWX123456789') 'ABCDEFGHIJKLMNOPQRSTUVWX123456789')
def change_name(self, new_name):
self.name = new_name
self.save()
def change_description(self, new_description):
self.description = new_description
self.save()
...@@ -9,9 +9,46 @@ from template.serializers import InstanceFromTemplateSerializer ...@@ -9,9 +9,46 @@ from template.serializers import InstanceFromTemplateSerializer
from instance.models import Instance, Flavor, Lease from instance.models import Instance, Flavor, Lease
from template.models import ImageTemplate from template.models import ImageTemplate
from template.serializers import ImageTemplateModelSerializer from template.serializers import ImageTemplateModelSerializer
from authorization.mixins import AuthorizationMixin
class InstanceViewSet(ViewSet):
authorization = {
"list": {"filter": ["use_instance"]},
"create": {"model": ["instance.create_instance"]},
"retrieve": {"object": ["use_instance"]},
"update": {"object": ["use_instance"]},
"destroy": {"object": ["administer_instance"]},
"template": {"model": ["create_template_from_instance"],
"object": ["use_instance"]},
"start": {"object": ["operate_instance"]},
"stop": {"object": ["operate_instance"]},
"suspend": {"object": ["operate_instance"]},
"wake_up": {"object": ["operate_instance"]},
"reset": {"object": ["operate_instance"]},
"reboot": {"object": ["operate_instance"]},
}
update_actions = [
"change_name",
"change_description",
"renew",
"change_lease",
"change_flavor",
"attach_disk",
"resize_disk",
"add_permission",
"remove_permission",
"open_port",
"close_port",
"add_network",
"remove_network",
"new_password",
]
class InstanceViewSet(AuthorizationMixin, ViewSet):
authorization = authorization
def get_object(self, pk): def get_object(self, pk):
try: try:
...@@ -20,10 +57,14 @@ class InstanceViewSet(ViewSet): ...@@ -20,10 +57,14 @@ class InstanceViewSet(ViewSet):
raise Http404 raise Http404
def list(self, request): def list(self, request):
instances = Instance.objects.all() instances = self.get_objects_with_perms(request.user, "list", Instance)
return Response(InstanceSerializer(instances, many=True).data) return Response(InstanceSerializer(instances, many=True).data)
def create(self, request): def create(self, request):
if not self.has_perms_for_model(request.user, 'create'):
return Response({"error": "No permission to create Virtual Machine."},
status=status.HTTP_401_UNAUTHORIZED)
data = request.data data = request.data
template = ImageTemplate.objects.get(pk=data["template"]) template = ImageTemplate.objects.get(pk=data["template"])
...@@ -50,6 +91,10 @@ class InstanceViewSet(ViewSet): ...@@ -50,6 +91,10 @@ class InstanceViewSet(ViewSet):
def retrieve(self, request, pk): def retrieve(self, request, pk):
instance = self.get_object(pk) instance = self.get_object(pk)
if not self.has_perms_for_object(request.user, 'retrieve', instance):
return Response({"error": "No permission to access the Virtual Machine."},
status=status.HTTP_401_UNAUTHORIZED)
instanceDict = InstanceSerializer(instance).data instanceDict = InstanceSerializer(instance).data
remoteInstance = instance.get_remote_instance() remoteInstance = instance.get_remote_instance()
remoteInstanceDict = remoteInstance.__dict__ remoteInstanceDict = remoteInstance.__dict__
...@@ -59,21 +104,67 @@ class InstanceViewSet(ViewSet): ...@@ -59,21 +104,67 @@ class InstanceViewSet(ViewSet):
return Response(merged_dict) return Response(merged_dict)
def update(self, request, pk, format=None): def update(self, request, pk, format=None):
if request.data["action"] in update_actions:
instance = self.get_object(pk) instance = self.get_object(pk)
serializer = InstanceSerializer(instance, data=request.data) if not self.has_perms_for_object(request.user, 'update', instance):
if serializer.is_valid(): return Response({"error": "No permission to access the Virtual Machine."},
serializer.save() status=status.HTTP_401_UNAUTHORIZED)
return Response(serializer.data) action = request.data["action"]
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) if action == "change_name":
instance.change_name(request.data["name"])
elif action == "change_description":
instance.change_description(request.data["description"])
elif action == "renew":
instance.renew()
elif action == "change_lease":
lease = Lease.objects.get(pk=request.data["lease"])
instance.renew(lease)
elif action == "change_flavor":
pass
elif action == "attach_disk":
pass
elif action == "resize_disk":
pass
elif action == "add_permission":
pass
elif action == "remove_permission":
pass
elif action == "open_port":
pass
elif action == "close_port":
pass
elif action == "add_network":
pass
elif action == "remove_network":
pass
elif action == "new_password":
pass
instanceDict = InstanceSerializer(instance).data
remoteInstance = instance.get_remote_instance()
remoteInstanceDict = remoteInstance.__dict__
merged_dict = {"db": instanceDict, "openstack": remoteInstanceDict}
return Response(merged_dict)
else:
return Response({"error": "Unknown update action."}, status=status.HTTP_400_BAD_REQUEST)
def destroy(self, request, pk, format=None): def destroy(self, request, pk, format=None):
instance = self.get_object(pk) instance = self.get_object(pk)
if not self.has_perms_for_object(request.user, 'destroy', instance):
return Response({"error": "No permission to destroy the Virtual Machine."},
status=status.HTTP_401_UNAUTHORIZED)
instance.delete() instance.delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
@action(detail=True, methods=["post"]) @action(detail=True, methods=["post"])
def template(self, request, pk): def template(self, request, pk):
instance = self.get_object(pk) instance = self.get_object(pk)
if not self.has_perms_for_model(request.user, 'template'):
return Response({"error": "No permission to create template from instance."},
status=status.HTTP_401_UNAUTHORIZED)
if not self.has_perms_for_object(request.user, 'template', instance):
return Response({"error": "No permission to access the Virtual Machine."},
status=status.HTTP_401_UNAUTHORIZED)
serializer = InstanceFromTemplateSerializer(data=request.data) serializer = InstanceFromTemplateSerializer(data=request.data)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
data = serializer.validated_data data = serializer.validated_data
...@@ -87,8 +178,10 @@ class InstanceViewSet(ViewSet): ...@@ -87,8 +178,10 @@ class InstanceViewSet(ViewSet):
@action(detail=True, methods=["POST"]) @action(detail=True, methods=["POST"])
def actions(self, request, pk): def actions(self, request, pk):
instance = self.get_object(pk) instance = self.get_object(pk)
if not self.has_perms_for_object(request.user, request.data["action"], instance):
return Response({"error": "No permission to use this action on the VM."},
status=status.HTTP_401_UNAUTHORIZED)
success = instance.execute_common_action(action=request.data["action"]) success = instance.execute_common_action(action=request.data["action"])
return Response(success) return Response(success)
......
...@@ -41,6 +41,7 @@ INSTALLED_APPS = [ ...@@ -41,6 +41,7 @@ INSTALLED_APPS = [
"djoser", "djoser",
"rest_framework_swagger", "rest_framework_swagger",
"corsheaders", "corsheaders",
"guardian",
"django_nose", "django_nose",
] ]
...@@ -49,6 +50,7 @@ LOCAL_APPS = [ ...@@ -49,6 +50,7 @@ LOCAL_APPS = [
"instance", "instance",
"storage", "storage",
"template", "template",
"authorization",
] ]
INSTALLED_APPS += LOCAL_APPS INSTALLED_APPS += LOCAL_APPS
...@@ -112,6 +114,7 @@ REST_FRAMEWORK = { ...@@ -112,6 +114,7 @@ REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ( 'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.TokenAuthentication',
), ),
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' # needed for swagger
} }
# Internationalization # Internationalization
...@@ -230,3 +233,10 @@ LOGGING = { ...@@ -230,3 +233,10 @@ LOGGING = {
for i in LOCAL_APPS: for i in LOCAL_APPS:
LOGGING['loggers'][i] = {'handlers': ['console'], 'level': 'DEBUG'} LOGGING['loggers'][i] = {'handlers': ['console'], 'level': 'DEBUG'}
# Configure django-guardian for the authorization
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend', # this is default
'guardian.backends.ObjectPermissionBackend',
)
...@@ -12,5 +12,8 @@ ADMIN_ENABLED = True ...@@ -12,5 +12,8 @@ ADMIN_ENABLED = True
ALLOWED_HOSTS = ['*'] ALLOWED_HOSTS = ['*']
AUTH_PASSWORD_VALIDATORS = []
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
NOSE_ARGS = LOCAL_APPS NOSE_ARGS = LOCAL_APPS
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment