def user_from_request(request, admin=False, redirect=False): """Given request, initiate User instance (mist.api.users.model.User) First try to check if there is a valid api token header, else check if there is a valid cookie session, else raise UserUnauthorizedError. If admin is True, it will check if user obtained is an admin and will raise an AdminUnauthorizedError otherwise. If redirect is True and no valid api token or cookie session exists, redirect user to login. Once logged in, he will be redirected back to the page he was trying to visit the first time. If no exceptions were raised and no redirects made, it returns the user object. """ token = session_from_request(request) user = token.get_user() if user is None: # Redirect to login if redirect and request.method == 'GET': if not isinstance(token, SessionToken) or not token.get_user(): query = '' if request.query_string: query = '?' + request.query_string return_to = urllib.quote(request.path + query) url = "/login?return_to=" + return_to raise RedirectError(url) raise UserUnauthorizedError() # check if admin if admin and user.role != 'Admin': raise AdminUnauthorizedError(user.email) return user
def machine_console(request): """ Tags: machines --- Open VNC console. Generate and return an URI to open a VNC console to target machine READ permission required on cloud. READ permission required on machine. --- cloud: in: path required: true type: string machine: in: path required: true type: string rdp_port: default: 3389 in: query required: true type: integer host: in: query required: true type: string """ cloud_id = request.matchdict.get('cloud') auth_context = auth_context_from_request(request) if cloud_id: machine_id = request.matchdict['machine'] auth_context.check_perm("cloud", "read", cloud_id) try: machine = Machine.objects.get(cloud=cloud_id, machine_id=machine_id, state__ne='terminated') # used by logging_view_decorator request.environ['machine_uuid'] = machine.id except Machine.DoesNotExist: raise NotFoundError("Machine %s doesn't exist" % machine_id) else: machine_uuid = request.matchdict['machine_uuid'] try: machine = Machine.objects.get(id=machine_uuid, state__ne='terminated') # used by logging_view_decorator request.environ['machine_id'] = machine.machine_id request.environ['cloud_id'] = machine.cloud.id except Machine.DoesNotExist: raise NotFoundError("Machine %s doesn't exist" % machine_uuid) cloud_id = machine.cloud.id auth_context.check_perm("cloud", "read", cloud_id) auth_context.check_perm("machine", "read", machine.id) if machine.cloud.ctl.provider not in ['vsphere', 'openstack', 'libvirt']: raise MistNotImplementedError( "VNC console only supported for vSphere, OpenStack or KVM") if machine.cloud.ctl.provider == 'libvirt': import xml.etree.ElementTree as ET from html import unescape from datetime import datetime import hmac import hashlib xml_desc = unescape(machine.extra.get('xml_description', '')) root = ET.fromstring(xml_desc) vnc_element = root.find('devices').find('graphics[@type="vnc"]') if not vnc_element: raise MethodNotAllowedError( "VNC console not supported by this KVM domain") vnc_port = vnc_element.attrib.get('port') vnc_host = vnc_element.attrib.get('listen') from mongoengine import Q # Get key associations, prefer root or sudoer ones key_associations = KeyMachineAssociation.objects( Q(machine=machine.parent) & (Q(ssh_user='******') | Q(sudo=True))) \ or KeyMachineAssociation.objects(machine=machine.parent) if not key_associations: raise ForbiddenError() key_id = key_associations[0].key.id host = '%s@%s:%d' % (key_associations[0].ssh_user, machine.parent.hostname, key_associations[0].port) expiry = int(datetime.now().timestamp()) + 100 msg = '%s,%s,%s,%s,%s' % (host, key_id, vnc_host, vnc_port, expiry) mac = hmac.new(config.SECRET.encode(), msg=msg.encode(), digestmod=hashlib.sha256).hexdigest() base_ws_uri = config.CORE_URI.replace('http', 'ws') proxy_uri = '%s/proxy/%s/%s/%s/%s/%s/%s' % ( base_ws_uri, host, key_id, vnc_host, vnc_port, expiry, mac) return render_to_response('../templates/novnc.pt', {'url': proxy_uri}) if machine.cloud.ctl.provider == 'vsphere': console_uri = machine.cloud.ctl.compute.connection.ex_open_console( machine.machine_id) protocol, host = config.CORE_URI.split('://') protocol = protocol.replace('http', 'ws') params = urllib.parse.urlencode({'url': console_uri}) proxy_uri = f"{protocol}://{host}/wsproxy/?{params}" return render_to_response('../templates/novnc.pt', {'url': proxy_uri}) else: console_url = machine.cloud.ctl.compute.connection.ex_open_console( machine.machine_id) raise RedirectError(console_url)
def machine_console(request): """ Tags: machines --- Open VNC console. Generate and return an URI to open a VNC console to target machine READ permission required on cloud. READ permission required on machine. --- cloud: in: path required: true type: string machine: in: path required: true type: string rdp_port: default: 3389 in: query required: true type: integer host: in: query required: true type: string """ cloud_id = request.matchdict.get('cloud') auth_context = auth_context_from_request(request) if cloud_id: machine_id = request.matchdict['machine'] auth_context.check_perm("cloud", "read", cloud_id) try: machine = Machine.objects.get(cloud=cloud_id, machine_id=machine_id, state__ne='terminated') # used by logging_view_decorator request.environ['machine_uuid'] = machine.id except Machine.DoesNotExist: raise NotFoundError("Machine %s doesn't exist" % machine_id) else: machine_uuid = request.matchdict['machine_uuid'] try: machine = Machine.objects.get(id=machine_uuid, state__ne='terminated') # used by logging_view_decorator request.environ['machine_id'] = machine.machine_id request.environ['cloud_id'] = machine.cloud.id except Machine.DoesNotExist: raise NotFoundError("Machine %s doesn't exist" % machine_uuid) cloud_id = machine.cloud.id auth_context.check_perm("cloud", "read", cloud_id) auth_context.check_perm("machine", "read", machine.id) if machine.cloud.ctl.provider not in ['vsphere', 'openstack', 'libvirt']: raise NotImplementedError( "VNC console only supported for vSphere, OpenStack or KVM") if machine.cloud.ctl.provider == 'libvirt': import xml.etree.ElementTree as ET from html import unescape from datetime import datetime import hmac import hashlib xml_desc = unescape(machine.extra.get('xml_description', '')) root = ET.fromstring(xml_desc) vnc_element = root.find('devices').find('graphics[@type="vnc"]') vnc_port = vnc_element.attrib.get('port') vnc_host = vnc_element.attrib.get('listen') key_id = machine.cloud.key.id host = '%s@%s:%d' % (machine.cloud.username, machine.cloud.host, machine.cloud.port) expiry = int(datetime.now().timestamp()) + 100 msg = '%s,%s,%s,%s,%s' % (host, key_id, vnc_host, vnc_port, expiry) mac = hmac.new(config.SECRET.encode(), msg=msg.encode(), digestmod=hashlib.sha256).hexdigest() base_ws_uri = config.CORE_URI.replace('http', 'ws') ws_uri = '%s/proxy/%s/%s/%s/%s/%s/%s' % ( base_ws_uri, host, key_id, vnc_host, vnc_port, expiry, mac) return render_to_response('../templates/novnc.pt', {'url': ws_uri}) if machine.cloud.ctl.provider == 'vsphere': url_param = machine.cloud.ctl.compute.connection.ex_open_console( machine.machine_id) params = urllib.parse.urlencode({'url': url_param}) console_url = ("/ui/assets/vsphere-console-util-js/" f"console.html?{params}") else: console_url = machine.cloud.ctl.compute.connection.ex_open_console( machine.machine_id) raise RedirectError(console_url)
def machine_console(request): """ Tags: machines --- Open VNC console. Generate and return an URI to open a VNC console to target machine READ permission required on cloud. READ permission required on machine. --- cloud: in: path required: true type: string machine: in: path required: true type: string rdp_port: default: 3389 in: query required: true type: integer host: in: query required: true type: string """ cloud_id = request.matchdict.get('cloud') auth_context = auth_context_from_request(request) if cloud_id: machine_id = request.matchdict['machine'] auth_context.check_perm("cloud", "read", cloud_id) try: machine = Machine.objects.get(cloud=cloud_id, machine_id=machine_id, state__ne='terminated') # used by logging_view_decorator request.environ['machine_uuid'] = machine.id except Machine.DoesNotExist: raise NotFoundError("Machine %s doesn't exist" % machine_id) else: machine_uuid = request.matchdict['machine_uuid'] try: machine = Machine.objects.get(id=machine_uuid, state__ne='terminated') # used by logging_view_decorator request.environ['machine_id'] = machine.machine_id request.environ['cloud_id'] = machine.cloud.id except Machine.DoesNotExist: raise NotFoundError("Machine %s doesn't exist" % machine_uuid) cloud_id = machine.cloud.id auth_context.check_perm("cloud", "read", cloud_id) auth_context.check_perm("machine", "read", machine.id) if machine.cloud.ctl.provider != 'vsphere': raise NotImplementedError("VNC console only supported for vSphere") console_uri = machine.cloud.ctl.compute.connection.ex_open_console( machine.machine_id) raise RedirectError(console_uri)