Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VNC Trough the API #17

Open
RamonSmit opened this issue Jan 23, 2017 · 31 comments
Open

VNC Trough the API #17

RamonSmit opened this issue Jan 23, 2017 · 31 comments
Assignees

Comments

@RamonSmit
Copy link
Contributor

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

@zzantares
Copy link
Owner

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.

@RamonSmit
Copy link
Contributor Author

Hi there,

Could not solve the problem :(.

@YWatchman
Copy link

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

@YWatchman
Copy link

YWatchman commented Apr 23, 2018

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;
}

@zzantares
Copy link
Owner

zzantares commented Apr 23, 2018

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. 👍

@YWatchman
Copy link

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

@RamonSmit
Copy link
Contributor Author

Kudos hehe!

@frius94
Copy link

frius94 commented Feb 15, 2019

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?

@YWatchman
Copy link

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

@fwelvering
Copy link

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

@YWatchman
Copy link

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

@DanielSpravtsev
Copy link

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/

@zzantares
Copy link
Owner

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

@DanielSpravtsev
Copy link

DanielSpravtsev commented Jun 2, 2019

@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);

@floreich
Copy link

@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

@JohnDepon
Copy link

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

@DanielSpravtsev
Copy link

DanielSpravtsev commented Dec 28, 2019

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.

@JohnDepon
Copy link

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!

@mrcatof
Copy link

mrcatof commented Feb 2, 2020

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
Copy link

mrcatof commented Feb 2, 2020

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

The post above fully describes how to access the console.

@DanielSpravtsev
Copy link

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

@dagababaev
Copy link

dagababaev commented Sep 8, 2020

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>';
}

?>

@carloscmx
Copy link

401 No ticket i need help :(

@dagababaev
Copy link

dagababaev commented Feb 6, 2021

@carloscmx

401 No ticket i need help :(

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

@carloscmx
Copy link

@carloscmx

401 No ticket i need help :(

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

not working :/

@dagababaev
Copy link

dagababaev commented Feb 10, 2021

@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
Copy link

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

@mrzibbert
Copy link

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

@GothShoot GothShoot self-assigned this Jun 14, 2022
@WillNilges
Copy link

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?

@Snakzi
Copy link

Snakzi commented Jul 14, 2022

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?

@bennetgallein
Copy link

So for anyone here setting PVEAuth Cookies: Don't. This is acceptable for internal development stuff, but don't give that access outside of your infrastructure ever.
You are:

  1. exposing the DNS/IP of the Node itself and
  2. exposing working credentials.

From what I know, even if you have a very strict setup for the user you use to create vnc-connections with, the user will have access to all vncs and (worse) can change his own password, so the account can be hijacked quite easily.

There is the https://github.com/novnc/websockify project. which works as a proxy server between the client and the Proxmox Node. You can use a token-provider like redis to generate tokens in the backend and open a connection between the client and the proxy-server. The connection is then between the proxy and the node itself. This way you don't need credentials (and no weird cookies) and you can have your proxmox server fully isolated, only allowing managment-access and access from the proxy server.

AFAIK there is no direct tutorial anywhere on how to implement this correctly, but I've implemented it in my product so I'll leave the documentation link here in case that's helpful: https://docs-next.bennetg.de/products/proxmox-cp/configuration/vnc-terminal

Maintainers: if this link is not okay here, just remove please.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests