147 lines
3.2 KiB
Go
Raw Normal View History

2024-11-13 22:45:03 +00:00
package term
2024-11-07 19:07:41 +00:00
import (
2024-11-08 15:09:32 +07:00
"log"
"time"
2024-11-08 15:09:32 +07:00
2024-11-07 19:07:41 +00:00
"github.com/gofiber/contrib/websocket"
2024-11-16 02:34:07 +07:00
"rul.sh/vaulterm/server/app/hosts"
"rul.sh/vaulterm/server/db"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
2024-11-07 19:07:41 +00:00
)
func HandleTerm(c *websocket.Conn) {
hostId := c.Query("hostId")
user := utils.GetUserWs(c)
hostRepo := hosts.NewRepository(&hosts.Hosts{User: user})
2024-11-08 15:09:32 +07:00
data, err := hostRepo.Get(hostId)
2024-11-07 19:07:41 +00:00
2024-11-12 17:17:10 +00:00
if data == nil || !data.HasAccess(&user.User) {
log.Printf("Cannot find host! %v\n", err)
2024-11-07 19:07:41 +00:00
c.WriteMessage(websocket.TextMessage, []byte("Host not found"))
return
}
log := ""
term := &models.TermSession{
UserID: user.ID,
HostID: hostId,
Reason: c.Query("reason"),
}
if err := db.Get().Create(term).Error; err != nil {
return
}
2024-11-07 19:07:41 +00:00
switch data.Host.Type {
case "ssh":
sshHandler(c, data, &log)
2024-11-07 19:07:41 +00:00
case "pve":
pveHandler(c, data)
case "incus":
incusHandler(c, data)
default:
c.WriteMessage(websocket.TextMessage, []byte("Invalid host type"))
}
// save session log
endsAt := time.Now()
db.Get().
Where("id = ?", term.ID).
Updates(&models.TermSession{
EndsAt: &endsAt,
Log: log,
})
2024-11-07 19:07:41 +00:00
}
func sshHandler(c *websocket.Conn, data *models.HostDecrypted, log *string) {
2024-11-09 14:37:09 +00:00
cfg := lib.NewSSHClient(&lib.SSHClientConfig{
2024-11-07 19:07:41 +00:00
HostName: data.Host.Host,
2024-11-09 14:37:09 +00:00
Port: data.Port,
Key: data.Key,
AltKey: data.AltKey,
})
2024-11-07 19:07:41 +00:00
out, err := NewSSHWebsocketSession(c, cfg)
if err != nil {
2024-11-07 19:07:41 +00:00
c.WriteMessage(websocket.TextMessage, []byte(err.Error()))
}
// copy output
if log != nil {
*log = string(out)
}
2024-11-07 19:07:41 +00:00
}
2024-11-09 14:37:09 +00:00
func pveHandler(c *websocket.Conn, data *models.HostDecrypted) {
2024-11-07 19:07:41 +00:00
client := c.Query("client")
username, _ := data.Key["username"].(string)
2024-11-09 18:57:36 +00:00
realm, _ := data.Key["realm"].(string)
2024-11-07 19:07:41 +00:00
password, _ := data.Key["password"].(string)
pve := &lib.PVEServer{
HostName: data.Host.Host,
2024-11-09 14:37:09 +00:00
Port: data.Port,
2024-11-07 19:07:41 +00:00
Username: username,
2024-11-09 18:57:36 +00:00
Realm: realm,
2024-11-07 19:07:41 +00:00
Password: password,
}
var i *lib.PVEInstance
if err := utils.ParseMapInterface(data.Host.Metadata, &i); err != nil {
c.WriteMessage(websocket.TextMessage, []byte(err.Error()))
return
}
if i == nil || i.Type == "" || i.Node == "" || i.VMID == "" {
c.WriteMessage(websocket.TextMessage, []byte("Invalid pve instance metadata"))
return
}
var err error
if client == "vnc" {
err = NewVNCSession(c, pve, i)
} else {
err = NewTerminalSession(c, pve, i)
}
if err != nil {
c.WriteMessage(websocket.TextMessage, []byte(err.Error()))
}
}
2024-11-09 14:37:09 +00:00
func incusHandler(c *websocket.Conn, data *models.HostDecrypted) {
2024-11-07 19:07:41 +00:00
shell := c.Query("shell")
cert, _ := data.Key["cert"].(string)
key, _ := data.Key["key"].(string)
if cert == "" || key == "" {
c.WriteMessage(websocket.TextMessage, []byte("Missing certificate or key"))
return
}
incus := &lib.IncusServer{
HostName: data.Host.Host,
2024-11-09 14:37:09 +00:00
Port: data.Port,
2024-11-07 19:07:41 +00:00
ClientCert: cert,
ClientKey: key,
}
session := &IncusWebsocketSession{}
if err := utils.ParseMapInterface(data.Host.Metadata, session); err != nil {
c.WriteMessage(websocket.TextMessage, []byte(err.Error()))
return
}
if shell != "" {
session.Shell = shell
}
if err := session.NewTerminal(c, incus); err != nil {
c.WriteMessage(websocket.TextMessage, []byte(err.Error()))
}
}