Proxmox vncwebsocket connection - 401 No ticket

D

Deleted member 259573

Guest
We try to avoid getting csrf token because of the lack of api token support. We wanted to get a script to run on the lxc without the need of ssh and tried to make use of the API websocket implementation. We've come up with following code:

Python:
import requests
import threading
from time import sleep
import urllib.parse
import ssl
import websocket

proxmox_host="PLACEHOLDER"
api_token="PLACEHOLDER"
node="PLACEHOLDER"
vmid="PLACEHOLDER"

url_proxy = f"{proxmox_host}/api2/json/nodes/{node}/lxc/{vmid}/vncproxy"
headers = {"Authorization": f"PVEAPIToken={api_token}"}

vncproxy_response = requests.post(
    url_proxy,
    headers=headers,
    verify=False,
    )

vncproxy_response = vncproxy_response.json()
print (vncproxy_response)

if 'errors' in vncproxy_response:
    print(f"Error: {vncproxy_response['errors']}")
else:
    ticket_not_encoded = vncproxy_response["data"]["ticket"]
    port = vncproxy_response["data"]["port"]

    ticket_encoded = urllib.parse.quote(ticket_not_encoded, safe="")
    url_vnc_websocket = f"{proxmox_host}/api2/json/nodes/{node}/lxc/{vmid}/vncwebsocket?port={port}&vncticket={ticket_encoded}"
    websocket_url = url_vnc_websocket.replace ("https", "wss")
    
    print (url_vnc_websocket)
    print (websocket_url)
    
    def on_message(ws, message):
        print(f"Message received: {message}")

    def on_close(ws, close_status_code, close_msg):
        print(f"Channel closed with status code: {close_status_code}, message: {close_msg}")

    if __name__ == "__main__":
        websocket.enableTrace(True)
        ws = websocket.WebSocketApp(
            websocket_url,
            on_message=on_message,
            on_close=on_close,
        )

        ws_listener = threading.Thread(target=ws.run_forever, kwargs={
            "sslopt": {"cert_reqs": ssl.CERT_NONE},
        })
        ws_listener.daemon = True
        ws_listener.start()

        timeout = 5
        while not ws.sock or not ws.sock.connected and timeout:
            sleep(1)
            timeout -= 1

        if timeout == 0:
            print("Connection to server timed out")
        else:
            print("Connected to server")

        message_num = 0
        while ws.sock.connected:
            message = 'ls\n'
            ws.send(message)
            sleep(1)
            message_num += 1

but unfortunately we're getting following error when the connection tries to upgrade to websocket:

Handshake status 401 No ticket -+-+- {'cache-control': 'max-age=0', 'date': 'Mon, 16 Sep 2024 05:45:02 GMT', 'pragma': 'no-cache', 'server': 'pve-api-daemon/3.0', 'expires': 'Mon, 16 Sep 2024 05:45:02 GMT', 'set-cookie': 'SERVERID=PLACEHOLDER; path=/', 'connection': 'close'} -+-+- None - goodbye

Anyone can help or has a similar problem?