ProxmoxVE icon indicating copy to clipboard operation
ProxmoxVE copied to clipboard

VNC Trough the API

Open RamonSmit opened this issue 8 years ago • 31 comments

Hi there,

Thanks for developing this nice API wrapper! I'm very pleased with this!

I want to show the VNC client out of the Proxmox environment but get a 401 No Ticket and I don't really see what i'm doing wrong around here.

Would you mind to take a look at my code?

if($proxmox->login()) {
    $config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy');
    $websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket',
        [
            'vncticket' => $config['data']['ticket'],
            'port'      => $config['data']['port'],
        ]);
    
    return '<iframe  src="https://my-server:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>';
}

Thanks in advance! Cheers, Ramon

RamonSmit avatar Jan 23 '17 20:01 RamonSmit

I'm sorry, I'm just seeing this! 😩 . A guy have contacted me with the same exact problem, did you manage to solve it? it was a problem with the library or with the API consumption? I honestly should say I did never test the vnc via api, so I couldn't help.

If you could share your findings would be helpful for others having the same issue.

zzantares avatar Oct 07 '17 04:10 zzantares

Hi there,

Could not solve the problem :(.

RamonSmit avatar Oct 09 '17 07:10 RamonSmit

You haven't closed your src="" the last "

YWatchman avatar Apr 23 '18 10:04 YWatchman

Hi @RamonSmit @ZzAntares

This code would work, be aware that you have to change the default variables.

<?php
use ProxmoxVE\Proxmox;

$credentials = [
    'hostname'  => 'server-node',
    'username'  => 'root',
    'password'  => 'supersecurestrongpassword',
    'realm'     => 'pam'
];



$proxmox = new Proxmox($credentials);

if($proxmox->login()) {
    $config = $proxmox->create('/nodes/server-node/qemu/100/vncproxy');
    $websock = $proxmox->get('/nodes/server-node/qemu/100/vncwebsocket',
        [
            'vncticket' => $config['data']['ticket'],
            'port' => $config['data']['port']
        ]);

    echo 'https://server-node:8006/?console=kvm&novnc=1&node=server-node&resize=scale&vmid=100&path=api2/json/nodes/server-node/qemu/100/vncwebsocket?port=' . $config['data']['port'] . '&vncticket=' . $config["data"]["ticket"];
    echo PHP_EOL;
}

YWatchman avatar Apr 23 '18 10:04 YWatchman

Thanks! So the generated URL just needs to be in an iframe and that's it, right?

I'll add this to the Readme before closing the issue. 👍

zzantares avatar Apr 23 '18 15:04 zzantares

That's true, I'd have to test it further and then I'll give you a final response.

YWatchman avatar Apr 24 '18 08:04 YWatchman

Kudos hehe!

RamonSmit avatar Apr 24 '18 14:04 RamonSmit

Hi @YWatchman I tried it just like you mentioned it above, but unfortunately it didn't work. I get a 401 No ticket error. How did you get it working? Isn't it mandatory to use cookies for this?

frius94 avatar Feb 15 '19 13:02 frius94

Haven't had any time looking at it further, I'll note it in my calendar for this sunday.

YWatchman avatar Feb 15 '19 13:02 YWatchman

Hi @YWatchman, i have the same 401 no ticket error. Did you make any progress on this issue?

fwelvering avatar Feb 19 '19 17:02 fwelvering

Didn't make any progress. It seems like you will need to create your own VNC client or use the vnc sdk.

YWatchman avatar Feb 26 '19 13:02 YWatchman

Didn't make any progress. It seems like you will need to create your own VNC client or use the vnc sdk.

Problem can be solved by adding modifications to HTTPServer.pm file under /usr/share/perl5/PVE/

DanielSpravtsev avatar May 25 '19 11:05 DanielSpravtsev

Hi @justamoose, exactly which modifications need to be added?

zzantares avatar Jun 02 '19 00:06 zzantares

@ZzAntares One of solutions is authorization through external user with vnc permissions At first - create user for vnc with limited rights,then patch HTTPServer.pm file with following code (edit username to your)

   if ($require_auth) {

-              die "No ticket\n" if !$ticket;
-
-              ($username, $age) = PVE::AccessControl::verify_ticket($ticket);
-
-              $rpcenv->set_user($username);
+        if ($rel_uri =~ /vncwebsocket/ && $method eq 'GET' && !$ticket)
+        {
+               $rpcenv->set_user("vnc\@pve");
+               $username = "vnc\@pve";
+               $age = 60;
+        } else {
+               die "No ticket\n" if !$ticket;
+               ($username, $age) = PVE::AccessControl::verify_ticket($ticket);
+               $rpcenv->set_user($username);
+        }

                if ($method eq 'POST' && $rel_uri =~ m|^/nodes/([^/]+)/storage/([^/]+)/upload$|) {
                   my ($node, $storeid) = ($1, $2);

DanielSpravtsev avatar Jun 02 '19 17:06 DanielSpravtsev

@ZzAntares One of solutions is authorization through external user with vnc permissions At first - create user for vnc with limited rights,then patch HTTPServer.pm file with following code (edit username to your)

if ($require_auth) {

  •          die "No ticket\n" if !$ticket;
    
  •          ($username, $age) = PVE::AccessControl::verify_ticket($ticket);
    
  •          $rpcenv->set_user($username);
    
  •    if ($rel_uri =~ /vncwebsocket/ && $method eq 'GET' && !$ticket)
    
  •    {
    
  •           $rpcenv->set_user("vnc\@pve");
    
  •           $username = "vnc\@pve";
    
  •           $age = 60;
    
  •    } else {
    
  •           die "No ticket\n" if !$ticket;
    
  •           ($username, $age) = PVE::AccessControl::verify_ticket($ticket);
    
  •           $rpcenv->set_user($username);
    
  •    }
    
              if ($method eq 'POST' && $rel_uri =~ m|^/nodes/([^/]+)/storage/([^/]+)/upload$|) {
                 my ($node, $storeid) = ($1, $2);
    

How do I need to add the user

floreich avatar Jun 22 '19 14:06 floreich

Did anyone figure out a way to make this work without having to patch PVE?

JohnDepon avatar Dec 28 '19 15:12 JohnDepon

Did anyone figure out a way to make this work without having to patch PVE?

Yes. I found a way to cheat it with cookies. Works only if everything(proxmox + client panel) at one domain (including subdomains) Example: node1.pve.example.com - proxmox cp.example.com - client panel, where you need to make redirect user to VNC with restricted access.

DanielSpravtsev avatar Dec 28 '19 15:12 DanielSpravtsev

Thank you very much for your quick reply! You steered me in the right direction (everything under the same domain) and the rest was easy :)

Works great. Thank you!

JohnDepon avatar Dec 28 '19 15:12 JohnDepon

Hi there,

Thanks for developing this nice API wrapper! I'm very pleased with this!

I want to show the VNC client out of the Proxmox environment but get a 401 No Ticket and I don't really see what i'm doing wrong around here.

Would you mind to take a look at my code?

if($proxmox->login()) {
    $config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy');
    $websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket',
        [
            'vncticket' => $config['data']['ticket'],
            'port'      => $config['data']['port'],
        ]);
    
    return '<iframe  src="https://my-server:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>';
}

Thanks in advance! Cheers, Ramon

  1. Your site and the panel itself must be in 1 domain (Example: example.com & cp.example.com)
  2. Before showing the iframe, you must set the cookie "PVEAuthCookie"
<?php
if($login = $proxmox->login()) {
    /* SET COOKIE FOR DOMAIN & SUBDOMAINS example.com, .example.com*/
    setcookie('PVEAuthCookie', $login->getTicket(), 0, '/', 'example.com', false);
    $config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy');
    $websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket', [
        'vncticket' => $config['data']['ticket'],
        'port'      => $config['data']['port'],
    ]);
    return '<iframe  src="https://cp.example.com:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>';
}
?>

mrcatof avatar Feb 02 '20 23:02 mrcatof

Hi @justamoose, exactly which modifications need to be added?

The post above fully describes how to access the console.

mrcatof avatar Feb 02 '20 23:02 mrcatof

Hi there, Thanks for developing this nice API wrapper! I'm very pleased with this! I want to show the VNC client out of the Proxmox environment but get a 401 No Ticket and I don't really see what i'm doing wrong around here. Would you mind to take a look at my code?

if($proxmox->login()) {
    $config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy');
    $websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket',
        [
            'vncticket' => $config['data']['ticket'],
            'port'      => $config['data']['port'],
        ]);
    
    return '<iframe  src="https://my-server:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>';
}

Thanks in advance! Cheers, Ramon

  1. Your site and the panel itself must be in 1 domain (Example: example.com & cp.example.com)
  2. Before showing the iframe, you must set the cookie "PVEAuthCookie"
<?php
if($login = $proxmox->login()) {
    /* SET COOKIE FOR DOMAIN & SUBDOMAINS example.com, .example.com*/
    setcookie('PVEAuthCookie', $login->getTicket(), 0, '/', 'example.com', false);
    $config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy');
    $websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket', [
        'vncticket' => $config['data']['ticket'],
        'port'      => $config['data']['port'],
    ]);
    return '<iframe  src="https://cp.example.com:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>';
}
?>

There is a mistake in your solution. You do not need to call vncproxy or vncticket. If you set cookie for user, it will be able to open your proxmox from frame url and get access not only for a console. So, you need to restrict all except vnc access at the point of user creation: Client X

  1. Create user if not. Restrict access only for vnc from pool
  2. Create ordered vm
  3. Add vm to user pool Then you can load console just by it links

DanielSpravtsev avatar Feb 02 '20 23:02 DanielSpravtsev

I finally won and connected to noVNC from remote host! Previous solutions have any problems and don't work properly…

100% worked solution:

<?php

/*
For the first you need:
1. Create User group "VNC" –> Datacenter / Permissions / Group
2. Create new user -> Datacenter / Permissions / Users - select Group: "VNC", Realm: pve
3. Create new Role -> Datacenter / Permissions / Roles - select Name: "VNC", Privilegies: VM.Console (only)
3. Add permision to access VM -> Datacenter / Node / VM / Permissions / Add Group Permissions - select Group: "VNC", Role: "VNC"
*/

require_once 'vendor/autoload.php';
use ProxmoxVE\Proxmox;

$host = 'pve1.your.com';
$node = 'pve-01';
$vmid = '100';

$credentials = [
    'hostname'  => $host,
    'username'  => 'username',
    'password'  => 'password',
    'realm'     => 'pve' // pve or pam
];

$proxmox = new Proxmox($credentials);

if($login = $proxmox->login()) {
    // Get and save ticket
    $ticket = $login->getTicket();
    $config = $proxmox->create('/nodes/'.$node.'/qemu/'.$vmid.'/vncproxy', [
        'websocket' => 1 // Start websocket
    ]);
    $websock = $proxmox->get('/nodes/'.$node.'/qemu/'.$vmid.'/vncwebsocket', [
        'vncticket' => $ticket,
        'port'      => $config['data']['port'],

    ]);
    // Set Cookies (domain must be in same space that pve. Example: pve – pve1.your.com, host – auth.your.com, Set cookies to your.com)
    setcookie('PVEAuthCookie', $ticket , 0, '/', 'your.com', false);

    $src_href = 'https://'.$host.':8006/?console=kvm&novnc=1&node='.$node.'&resize=1&vmid='.$vmid.'&path=api2/json/nodes/'.$node.'/qemu/'.$vmid.'/vncwebsocket/port/'.$config['data']['port'].'"/vncticket/"'.$ticket;
    echo '<iframe src="'.$src_href.'" frameborder="0" scrolling="no" width="800px" height="600px"></iframe>';
}

?>

dagababaev avatar Sep 08 '20 15:09 dagababaev

401 No ticket i need help :(

carloscmx avatar Feb 05 '21 18:02 carloscmx

@carloscmx

401 No ticket i need help :(

You can see my solution – https://github.com/dagababaev/ProxmoxVE_API_php

dagababaev avatar Feb 06 '21 09:02 dagababaev

@carloscmx

401 No ticket i need help :(

You can see my solution – https://github.com/dagababaev/ProxmoxVE_API_php

not working :/

carloscmx avatar Feb 10 '21 16:02 carloscmx

@carloscmx

401 No ticket i need help :(

You can see my solution – https://github.com/dagababaev/ProxmoxVE_API_php

not working :/

not working and all… :) need more information if you have 401 – check if your hostname of node and hostname where are you open VNC is same. It's may be different subdomain, but domain must be same (h1.yourhost.com and h2.yourhost.com). And check in Chrome local storage where ticket is wrote.

Eventually you can delete all code and add this for check what PVE is return:

if($login = $proxmox->login()) {
    var_dump($login."\n\n");
    $ticket = $login->getTicket();
    var_dump($ticket);
}

If in response you can't see ticket – check if all parameters you pass are correct. I was check now – code 100% worked with PVE 6.3-2 and Chrome 88.0.4324.150

dagababaev avatar Feb 10 '21 19:02 dagababaev

My last message correct if you use this API. If you have problem with my code need write issues there

dagababaev avatar Feb 10 '21 21:02 dagababaev

Maybe this article will help you. You can enable "ip:port" access, install noVNC on a separate host, and pass "ip: port" & pass to novnc. Use official docs: https://pve.proxmox.com/wiki/VNC_Client_Access

mrzibbert avatar Apr 01 '21 18:04 mrzibbert

Hey there! Can someone elaborate on how you'd circumvent the cookie requirement? I'm under the impression that you can call vncproxy and make it return a password to be used in place of the cookie?

https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/qemu/{vmid}/vncproxy

image

The issue with using a cookie, that I can see, is that even if you create a user with only the VNC role, you're still giving whoever's on the other end of the console a cookie which they can use to view other users' VNC terminals, correct?

WillNilges avatar Jul 04 '22 15:07 WillNilges

Hey there! Can someone elaborate on how you'd circumvent the cookie requirement? I'm under the impression that you can call vncproxy and make it return a password to be used in place of the cookie?

https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/qemu/{vmid}/vncproxy

image

The issue with using a cookie, that I can see, is that even if you create a user with only the VNC role, you're still giving whoever's on the other end of the console a cookie which they can use to view other users' VNC terminals, correct?

Have you found a solution for this?

Snakzi avatar Jul 14 '22 13:07 Snakzi