From 98d1408693cf34081d50e8db6a68a02e1ef5d594 Mon Sep 17 00:00:00 2001 From: Will Nilges Date: Sun, 10 Jul 2022 18:06:03 -0400 Subject: [PATCH] Black --- README.md | 7 +++++++ proxstar/__init__.py | 26 +++++++++++++++++++++++--- proxstar/vm.py | 21 +++++++++++++++------ proxstar/vnc.py | 13 +++++++++---- 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e252204..d3aa792 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,13 @@ It is available to house members at [proxstar.csh.rit.edu](https://proxstar.csh. 1. [Fork](https://help.github.com/en/articles/fork-a-repo) this repository - Optionally create a new [git branch](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) if your change is more than a small tweak (`git checkout -b BRANCH-NAME-HERE`) +2. Create a Virtualenv to do your work in. +``` +mkdir venv +python3.8 -m venv venv +source venv/bin/activate +``` + 3. Make your changes locally, commit, and push to your fork - If you want to test locally, you should copy `config.py` to `config_local.py`, and talk to an RTP about filling in secrets. - Lint and format your local changes with `pylint proxstar` and `black proxstar` diff --git a/proxstar/__init__.py b/proxstar/__init__.py index 0843777..0364e58 100644 --- a/proxstar/__init__.py +++ b/proxstar/__init__.py @@ -13,7 +13,17 @@ from redis import Redis from rq_scheduler import Scheduler from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker -from flask import Flask, render_template, request, redirect, session, abort, url_for, jsonify, Response +from flask import ( + Flask, + render_template, + request, + redirect, + session, + abort, + url_for, + jsonify, + Response, +) import sentry_sdk from sentry_sdk.integrations.flask import FlaskIntegration from sentry_sdk.integrations.rq import RqIntegration @@ -135,6 +145,7 @@ if 'cleanup_vnc' not in scheduler: interval=3600, ) + def add_rq_dashboard_auth(blueprint): @blueprint.before_request @auth.oidc_auth @@ -159,6 +170,7 @@ def forbidden(e): user = User(session['userinfo']['preferred_username']) return render_template('403.html', user=user, e=e), 403 + @app.route('/') @app.route('/user/') @auth.oidc_auth @@ -287,15 +299,23 @@ def vm_console(vmid): if user.rtp or int(vmid) in user.allowed_vms: # import pdb; pdb.set_trace() vm = VM(vmid) - vnc_ticket, vnc_port = open_vnc_session(vmid, vm.node, app.config['PROXMOX_USER'], app.config['PROXMOX_PASS']) + vnc_ticket, vnc_port = open_vnc_session( + vmid, vm.node, app.config['PROXMOX_USER'], app.config['PROXMOX_PASS'] + ) node = f'{vm.node}.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 + return { + 'host': app.config['VNC_HOST'], + 'port': 8081, + 'token': token, + 'password': vnc_ticket, + }, 200 else: return '', 403 + @app.route('/vm//cpu/', methods=['POST']) @auth.oidc_auth def vm_cpu(vmid, cores): diff --git a/proxstar/vm.py b/proxstar/vm.py index f7ce8bf..5c6724d 100644 --- a/proxstar/vm.py +++ b/proxstar/vm.py @@ -272,19 +272,28 @@ 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 + """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. + 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}' path = f'/etc/pve/local/qemu-server/{self.id}.conf' with paramiko.SSHClient() as ssh: ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - ssh.connect(self.node, port=22, username=ssh_user, key_filename='proxmox_ssh_key', passphrase=ssh_pass) - ssh.exec_command(f"if grep -- '{config}' {path}; then echo identical config found; else sed -i /dev/null '/-vnc/d' {path}") #YOLO - ssh.exec_command(f"if grep -- '-vnc' {path}; then echo found config; else echo {config} >> {path}; fi") - + ssh.connect( + self.node, + port=22, + username=ssh_user, + key_filename='proxmox_ssh_key', + passphrase=ssh_pass, + ) + ssh.exec_command( + f"if grep -- '{config}' {path}; then echo identical config found; else sed -i /dev/null '/-vnc/d' {path}" + ) # YOLO + ssh.exec_command( + f"if grep -- '-vnc' {path}; then echo found config; else echo {config} >> {path}; fi" + ) @retry(wait=wait_fixed(2), stop=stop_after_attempt(5)) def eject_iso(self): diff --git a/proxstar/vnc.py b/proxstar/vnc.py index 57e5898..3030a2f 100644 --- a/proxstar/vnc.py +++ b/proxstar/vnc.py @@ -37,6 +37,7 @@ def get_vnc_targets(): target_file.close() return targets + def add_vnc_target(node, port): # TODO (willnilges): This doesn't throw an error if the target file is wrong. # TODO (willnilges): This will duplicate targets @@ -52,6 +53,7 @@ def add_vnc_target(node, port): target_file.close() return token + def delete_vnc_target(node, port): targets = get_vnc_targets() target = next((target for target in targets if target['host'] == f'{node}:{port}'), None) @@ -62,8 +64,9 @@ def delete_vnc_target(node, 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 + """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. @@ -91,17 +94,18 @@ def open_vnc_session(vmid, node, proxmox_user, proxmox_pass): timeout=5, params=proxy_params, headers={"CSRFPreventionToken": csrf_prevention_token}, - cookies={"PVEAuthCookie": ticket} + 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 to the proxstar container """ port = int(port) - + server = SSHTunnelForwarder( node, ssh_username=app.config['PROXMOX_SSH_USER'], @@ -113,6 +117,7 @@ def start_ssh_tunnel(node, port): server.start() return server + def stop_ssh_tunnel(vmid, ssh_tunnels): # Tear down the SSH tunnel and VNC target entry for a given VM port = 5900 + int(vmid)