mirror of
https://github.com/khairul169/vaulterm.git
synced 2025-04-29 00:59:40 +07:00
129 lines
2.6 KiB
Go
129 lines
2.6 KiB
Go
package lib
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
)
|
|
|
|
type IncusServer struct {
|
|
HostName string
|
|
Port int
|
|
ClientCert string
|
|
ClientKey string
|
|
}
|
|
|
|
type IncusFetchConfig struct {
|
|
Body map[string]interface{}
|
|
}
|
|
|
|
func (i *IncusServer) GetCertificate() (*tls.Certificate, error) {
|
|
return LoadClientCertificate(i.ClientCert, i.ClientKey)
|
|
}
|
|
|
|
func (i *IncusServer) Fetch(method string, url string, cfg *IncusFetchConfig) ([]byte, error) {
|
|
var body io.Reader
|
|
if cfg != nil && cfg.Body != nil {
|
|
json, _ := json.Marshal(cfg.Body)
|
|
body = bytes.NewBuffer(json)
|
|
}
|
|
|
|
reqUrl := fmt.Sprintf("https://%s:%d%s", i.HostName, i.Port, url)
|
|
req, _ := http.NewRequest(method, reqUrl, body)
|
|
|
|
if body != nil {
|
|
req.Header.Add("Content-Type", "application/json")
|
|
}
|
|
|
|
clientCert, err := i.GetCertificate()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
tr := &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
InsecureSkipVerify: true,
|
|
Certificates: []tls.Certificate{*clientCert},
|
|
},
|
|
}
|
|
client := &http.Client{
|
|
Transport: tr,
|
|
}
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode >= http.StatusBadRequest {
|
|
return nil, fmt.Errorf("request failed with status code %d", resp.StatusCode)
|
|
}
|
|
|
|
return io.ReadAll(resp.Body)
|
|
}
|
|
|
|
type IncusInstanceExecOptions struct {
|
|
Interactive bool
|
|
User *int
|
|
}
|
|
|
|
type IncusInstanceExecRes struct {
|
|
ID string
|
|
Operation string
|
|
Control string
|
|
Secret string
|
|
}
|
|
|
|
func (i *IncusServer) InstanceExec(instance string, command []string, options *IncusInstanceExecOptions) (*IncusInstanceExecRes, error) {
|
|
url := fmt.Sprintf("/1.0/instances/%s/exec?project=default", instance)
|
|
|
|
var user *int
|
|
if options != nil && options.User != nil {
|
|
user = options.User
|
|
}
|
|
|
|
body, err := i.Fetch("POST", url, &IncusFetchConfig{
|
|
Body: map[string]interface{}{
|
|
"command": command,
|
|
"interactive": options != nil && options.Interactive,
|
|
"wait-for-websocket": true,
|
|
"environment": map[string]string{
|
|
"TERM": "xterm-256color",
|
|
},
|
|
"user": user,
|
|
},
|
|
})
|
|
if err != nil {
|
|
log.Println(err)
|
|
return nil, err
|
|
}
|
|
|
|
var res struct {
|
|
Operation string `json:"operation"`
|
|
Metadata struct {
|
|
ID string `json:"id"`
|
|
Metadata struct {
|
|
Fds map[string]string `json:"fds"`
|
|
} `json:"metadata"`
|
|
} `json:"metadata"`
|
|
}
|
|
if err := json.Unmarshal(body, &res); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
control := res.Metadata.Metadata.Fds["control"]
|
|
secret := res.Metadata.Metadata.Fds["0"]
|
|
|
|
return &IncusInstanceExecRes{
|
|
ID: res.Metadata.ID,
|
|
Operation: res.Operation,
|
|
Control: control,
|
|
Secret: secret,
|
|
}, nil
|
|
}
|