mirror of
https://github.com/khairul169/vaulterm.git
synced 2025-04-29 00:59:40 +07:00
130 lines
2.8 KiB
Go
130 lines
2.8 KiB
Go
package lib
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
type PVEServer struct {
|
|
HostName string
|
|
Port int
|
|
Username string
|
|
Realm string
|
|
Password string
|
|
}
|
|
|
|
type PVERequestInit struct {
|
|
Body map[string]string
|
|
Ticket string
|
|
CSRF string
|
|
}
|
|
|
|
func fetch(method string, url string, cfg *PVERequestInit) ([]byte, error) {
|
|
var body io.Reader
|
|
if cfg.Body != nil {
|
|
json, _ := json.Marshal(cfg.Body)
|
|
body = bytes.NewBuffer(json)
|
|
}
|
|
|
|
req, _ := http.NewRequest(method, url, body)
|
|
|
|
if cfg.Ticket != "" {
|
|
req.Header.Add("Cookie", "PVEAuthCookie="+cfg.Ticket)
|
|
}
|
|
if cfg.CSRF != "" {
|
|
req.Header.Add("CSRFPreventionToken", cfg.CSRF)
|
|
}
|
|
if body != nil {
|
|
req.Header.Add("Content-Type", "application/json")
|
|
}
|
|
|
|
tr := &http.Transport{
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
}
|
|
client := &http.Client{
|
|
Transport: tr,
|
|
}
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("request failed with status code %d", resp.StatusCode)
|
|
}
|
|
|
|
return io.ReadAll(resp.Body)
|
|
}
|
|
|
|
type PVEAccessTicket struct {
|
|
CSRFPreventionToken string `json:"CSRFPreventionToken"`
|
|
Ticket string `json:"ticket"`
|
|
Username string `json:"username"`
|
|
}
|
|
|
|
func (pve *PVEServer) GetAccessTicket() (*PVEAccessTicket, error) {
|
|
url := fmt.Sprintf("https://%s:%d/api2/json/access/ticket", pve.HostName, pve.Port)
|
|
|
|
// note for myself: don't forget the realm
|
|
body, err := fetch("POST", url, &PVERequestInit{Body: map[string]string{
|
|
"username": fmt.Sprintf("%s@%s", pve.Username, pve.Realm),
|
|
"password": pve.Password,
|
|
}})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var res struct {
|
|
Data PVEAccessTicket `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(body, &res); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &res.Data, nil
|
|
}
|
|
|
|
type PVEInstance struct {
|
|
Type string `json:"type"` // "qemu" | "lxc"
|
|
Node string `json:"node"`
|
|
VMID string `json:"vmid"`
|
|
}
|
|
|
|
type PVEVNCTicketData struct {
|
|
Port string `json:"port"`
|
|
User string `json:"user"`
|
|
Ticket string `json:"ticket"`
|
|
CERT string `json:"cert"`
|
|
Upid string `json:"upid"`
|
|
}
|
|
|
|
func (pve *PVEServer) GetVNCTicket(access *PVEAccessTicket, instance *PVEInstance, isVNC bool) (*PVEVNCTicketData, error) {
|
|
proxyType := "termproxy"
|
|
if isVNC {
|
|
proxyType = "vncproxy"
|
|
}
|
|
|
|
url := fmt.Sprintf("https://%s:%d/api2/json/nodes/%s/%s/%s/%s",
|
|
pve.HostName, pve.Port, instance.Node, instance.Type, instance.VMID, proxyType)
|
|
|
|
body, err := fetch("POST", url, &PVERequestInit{Ticket: access.Ticket, CSRF: access.CSRFPreventionToken})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var res struct {
|
|
Data PVEVNCTicketData `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(body, &res); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &res.Data, nil
|
|
}
|