Dude it works holy shit

We need to fix some logistical bugs, probably, and also like remove dead
code lol
This commit is contained in:
Will Nilges 2022-07-08 01:31:43 -04:00
parent 586536c708
commit 0b4efa9784
4 changed files with 52 additions and 24 deletions

View file

@ -42,6 +42,7 @@ from proxstar.vnc import (
get_vnc_targets,
delete_vnc_target,
stop_websockify,
open_vnc_session,
)
from proxstar.auth import get_auth
from proxstar.util import gen_password
@ -286,17 +287,12 @@ def vm_console(vmid):
if user.rtp or int(vmid) in user.allowed_vms:
# import pdb; pdb.set_trace()
vm = VM(vmid)
stop_ssh_tunnel(vm.id, ssh_tunnels)
port = str(5900 + int(vmid))
token = add_vnc_target(port)
node = '{}.csh.rit.edu'.format(vm.node)
logging.info('creating SSH tunnel to %s for VM %s', node, vm.id)
tunnel = start_ssh_tunnel(node, port)
vm.configure_vnc_in_vm_config(app.config['PROXMOX_SSH_USER'], app.config['PROXMOX_SSH_KEY_PASS'])
ssh_tunnels.append(tunnel)
# vm.start_vnc(port) # Broken :(
# return json.dumps([app.config['VNC_HOST'], token]), 200
return {'host' : app.config['VNC_HOST'], 'token' : token}, 200
vnc_ticket, vnc_port = open_vnc_session(vmid, vm.node, app.config['PROXMOX_USER'], app.config['PROXMOX_PASS'])
node = f'proxmox01-nrh.csh.rit.edu'
token = add_vnc_target(node, vnc_port)
# return {'host' : node, 'port' : vnc_port, 'token' : token, 'password' : vnc_ticket}, 200
return {'host' : app.config['VNC_HOST'], 'port' : 8081, 'token' : token, 'password' : vnc_ticket}, 200
else:
return '', 403

View file

@ -654,7 +654,7 @@ $("#console-vm").click(function(){
}).then((vnc_params) => {
// TODO (willnilges): encrypt=true
// TODO (willnilges): set host and port to an env variable
window.open(`/static/noVNC/vnc.html?autoconnect=true&password=${vmid}&host=${vnc_params.host}&port=8081&path=path?token=${vnc_params.token}`, '_blank');
window.open(`/static/noVNC/vnc.html?autoconnect=true&password=${vnc_params.password}&host=${vnc_params.host}&port=${vnc_params.port}&path=path?token=${vnc_params.token}`, '_blank');
}).catch(err => {
if (err) {
swal("Uh oh...", `Unable to start console for ${vmname}. Please try again later.`, "error");

View file

@ -274,9 +274,7 @@ class VM:
def configure_vnc_in_vm_config(self, ssh_user, ssh_pass):
""" Sets the vm up for VNC. Enables it to open a socket on localhost
with a pre-determined password, which proxstar can then proxy to a noVNC
instance.
TODO (willnilges): Current password is "chomchom1", but should be changed lol
instance.
"""
# proxmox = connect_proxmox()
config = f'args: -object secret,id=secvnc{self.id},data={self.id} -vnc 127.0.0.1:{int(self.id)+5900},password-secret=secvnc{self.id}'

View file

@ -5,6 +5,7 @@ import time
import requests
from flask import current_app as app
from sshtunnel import SSHTunnelForwarder
import urllib.parse
from proxstar import logging
from proxstar.util import gen_password
@ -31,36 +32,69 @@ def get_vnc_targets():
target_dict = {}
values = line.strip().split(':')
target_dict['token'] = values[0]
target_dict['port'] = values[2]
target_dict['host'] = values[1] + values[2]
targets.append(target_dict)
target_file.close()
return targets
def add_vnc_target(port):
def add_vnc_target(node, port):
# TODO (willnilges): This doesn't throw an error if the target file is wrong.
targets = get_vnc_targets()
target = next((target for target in targets if target['port'] == port), None)
target = next((target for target in targets if target['host'] == f'{node}:{port}'), None)
if target:
return target['token']
else:
target_file = open(app.config['WEBSOCKIFY_TARGET_FILE'], 'a')
token = gen_password(32, 'abcdefghijklmnopqrstuvwxyz0123456789')
target_file.write('{}: 127.0.0.1:{}\n'.format(token, str(port)))
target_file.write(f'{token}: {node}:{port}\n')
target_file.close()
return token
def delete_vnc_target(port):
def delete_vnc_target(node, port):
targets = get_vnc_targets()
target = next((target for target in targets if target['port'] == str(port)), None)
target = next((target for target in targets if target['host'] == f'{node}:{port}'), None)
if target:
targets.remove(target)
target_file = open(app.config['WEBSOCKIFY_TARGET_FILE'], 'w')
for target in targets:
target_file.write('{}: 127.0.0.1:{}\n'.format(target['token'], target['port']))
target_file.write(f"{target['token']}: {target['host']}\n")
target_file.close()
def open_vnc_session(vmid, node, proxmox_user, proxmox_pass):
""" Pings the Proxmox API to request a VNC Proxy connection. Authenticates
against the API using a Uname/Pass, gets a few tokens back, then uses those
tokens to open the VNC Proxy. Use these to connect to the VM's host with
websockify proxy.
Returns: Ticket to use as the noVNC password, and a port.
"""
# Get Proxmox API ticket and CSRF_Prevention_Token
# TODO: Use Proxmoxer to get this information?
# TODO: Report errors!?
data = {"username": proxmox_user, "password": proxmox_pass}
response_data = requests.post(
f"https://{node}.csh.rit.edu:8006/" + "api2/json/access/ticket",
verify=False,
data=data,
).json()["data"]
if response_data is None:
raise AuthenticationError(
"Could not authenticate against `ticket` endpoint! Check uname/password"
)
csrf_prevention_token = response_data['CSRFPreventionToken']
ticket = response_data['ticket']
proxy_params = {"node": node, "vmid": str(vmid), "websocket": '1', "generate-password": '0'}
vncproxy_response_data = requests.post(
"https://proxmox01-nrh.csh.rit.edu:8006" + f"/api2/json/nodes/{node}/qemu/{vmid}/vncproxy",
verify=False,
timeout=5,
params=proxy_params,
headers={"CSRFPreventionToken": csrf_prevention_token},
cookies={"PVEAuthCookie": ticket}
).json()["data"]
return urllib.parse.quote_plus(vncproxy_response_data['ticket']), vncproxy_response_data['port']
def start_ssh_tunnel(node, port):
"""Forwards a port on a node