feat: start new cmd with custom args in ?cmd=
continuous-integration/drone/tag Build is passing Details

master
Evan Chen 2021-11-18 13:52:07 +08:00
parent 6a75a1e27f
commit b6b0774531
7 changed files with 54 additions and 9 deletions

View File

@ -37,6 +37,7 @@ var (
flagVer bool flagVer bool
flagArgs arrayFlags flagArgs arrayFlags
flagProfile bool flagProfile bool
flagSalt string
) )
func init() { func init() {
@ -49,6 +50,7 @@ func init() {
flag.IntVar(&flagLogLevel, "log-level", 9, "log level, error:1 debug:2 warn:4 info:8") flag.IntVar(&flagLogLevel, "log-level", 9, "log level, error:1 debug:2 warn:4 info:8")
flag.StringVar(&flagAllowIP, "allow", "", "restrict ip") flag.StringVar(&flagAllowIP, "allow", "", "restrict ip")
flag.BoolVar(&flagProfile, "profile", false, "print default profile, could be invoked with <(..)") flag.BoolVar(&flagProfile, "profile", false, "print default profile, could be invoked with <(..)")
flag.StringVar(&flagSalt, "salt", "", "add salt to encoded keyparam")
flag.BoolVar(&flagVer, "v", false, "show version") flag.BoolVar(&flagVer, "v", false, "show version")
flag.Usage = func() { flag.Usage = func() {
@ -76,6 +78,7 @@ func main() {
g.Cmd = flagShell g.Cmd = flagShell
g.Args = flagArgs g.Args = flagArgs
g.Dir = flagDir g.Dir = flagDir
g.Salt = flagSalt
server := &http.Server{ server := &http.Server{
Addr: flagAddr, Addr: flagAddr,

1
go.mod
View File

@ -7,6 +7,7 @@ require (
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
kumoly.io/lib/klog v0.0.8 kumoly.io/lib/klog v0.0.8
kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298 kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298
kumoly.io/lib/xorencrypt v0.1.0
) )
require ( require (

2
go.sum
View File

@ -11,3 +11,5 @@ kumoly.io/lib/klog v0.0.8 h1:6hTfDlZh7KGnPrd2tUrauCKRImSnyyN9DHXpey3Czn8=
kumoly.io/lib/klog v0.0.8/go.mod h1:Snm+c1xRrh/RbXsxQf7UGYbAJGPcIa6bEEN+CmzJh7M= kumoly.io/lib/klog v0.0.8/go.mod h1:Snm+c1xRrh/RbXsxQf7UGYbAJGPcIa6bEEN+CmzJh7M=
kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298 h1:0raqoIXmNpD6s1SrJbieAyIIkDyhe+aqfaXvx8wenrI= kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298 h1:0raqoIXmNpD6s1SrJbieAyIIkDyhe+aqfaXvx8wenrI=
kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298/go.mod h1:pwd+NspxnoxPJAETRY2V4i2qZc+orKLxvWzGUBiqBW8= kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298/go.mod h1:pwd+NspxnoxPJAETRY2V4i2qZc+orKLxvWzGUBiqBW8=
kumoly.io/lib/xorencrypt v0.1.0 h1:VssGocaBAPyLn+QURVY8FdFYRBmwFr26z7ame0zwV44=
kumoly.io/lib/xorencrypt v0.1.0/go.mod h1:+L3JtdD/CTlcXvE8X7AvOJBVbN16qvnxxv3zIWPZgQM=

View File

@ -8,6 +8,7 @@ import (
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"strings" "strings"
"time" "time"
@ -16,6 +17,7 @@ import (
"kumoly.io/lib/klog" "kumoly.io/lib/klog"
"kumoly.io/lib/ksrv" "kumoly.io/lib/ksrv"
"kumoly.io/lib/ksrv/engine" "kumoly.io/lib/ksrv/engine"
"kumoly.io/lib/xorencrypt"
"kumoly.io/tools/gterm/public" "kumoly.io/tools/gterm/public"
) )
@ -53,6 +55,7 @@ type GTerm struct {
// cycle should be tolerated, beyond this the connection should be deemed dead // cycle should be tolerated, beyond this the connection should be deemed dead
Timeout time.Duration Timeout time.Duration
BufferSize int BufferSize int
Salt string
} }
func New() *GTerm { func New() *GTerm {
@ -125,6 +128,22 @@ func (g *GTerm) App(w http.ResponseWriter, r *http.Request) {
servePublic.ServeHTTP(w, r) servePublic.ServeHTTP(w, r)
} }
type NewCmdRequest struct {
Cmd string `json:"cmd"`
Envs []string `json:"envs"`
Args []string `json:"args"`
Dir string `json:"dir"`
}
func (g *GTerm) defaultCmd() *exec.Cmd {
cmd := exec.Command(g.Cmd, g.Args...)
cmd.Env = g.Envs
if g.Dir != "" && g.Dir != "." {
cmd.Dir = g.Dir
}
return cmd
}
func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) { func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
id := fmt.Sprintf("[%02d] %s", ctr(), ksrv.GetIP(r)) id := fmt.Sprintf("[%02d] %s", ctr(), ksrv.GetIP(r))
pool[id] = make(chan struct{}, 1) pool[id] = make(chan struct{}, 1)
@ -133,7 +152,26 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
delete(pool, id) delete(pool, id)
}() }()
l := klog.Sub(id) l := klog.Sub(id)
l.Info("connection established.")
var cmd *exec.Cmd
base := filepath.Base(r.URL.Path)
if base != "ws" && base != "." && base != "/" {
base = strings.Trim(base, "/")
param, _ := xorencrypt.Decrypt(base, g.Salt)
l.Info("starting cmd => ", l.M(param, klog.FgHiGreen))
req := &NewCmdRequest{}
err := json.Unmarshal([]byte(param), req)
if err != nil {
cmd = g.defaultCmd()
} else {
cmd = exec.Command(req.Cmd, req.Args...)
cmd.Env = req.Envs
cmd.Dir = req.Dir
}
} else {
cmd = g.defaultCmd()
}
upgrader := websocket.Upgrader{ upgrader := websocket.Upgrader{
HandshakeTimeout: 0, HandshakeTimeout: 0,
ReadBufferSize: g.BufferSize, ReadBufferSize: g.BufferSize,
@ -144,12 +182,8 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
l.Error(err) l.Error(err)
return return
} }
l.Info("connection established.")
cmd := exec.Command(g.Cmd, g.Args...)
cmd.Env = g.Envs
if g.Dir != "" && g.Dir != "." {
cmd.Dir = g.Dir
}
tty, err := pty.Start(cmd) tty, err := pty.Start(cmd)
if err != nil { if err != nil {
l.Error(err) l.Error(err)

View File

@ -17,8 +17,13 @@ import 'xterm/css/xterm.css'
}); });
const fitAddon = new FitAddon(); const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon); terminal.loadAddon(fitAddon);
const params = new URLSearchParams(window.location.search);
let newcmd = '';
if (params.has('cmd')){
newcmd = "/"+params.get('cmd')
}
var protocol = (location.protocol === "https:") ? "wss://" : "ws://"; var protocol = (location.protocol === "https:") ? "wss://" : "ws://";
var url = protocol + location.host + location.pathname + "ws" var url = protocol + location.host + location.pathname + "ws" + newcmd
const ws = new WebSocket(url); const ws = new WebSocket(url);
const attachAddon = new AttachAddon(ws); const attachAddon = new AttachAddon(ws);
const webLinksAddon = new WebLinksAddon(); const webLinksAddon = new WebLinksAddon();

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html><html><head><link rel="stylesheet" href="index.6999253a.css"><title>{{.AppName}}</title><style>body::-webkit-scrollbar,div::-webkit-scrollbar,html::-webkit-scrollbar{display:none;width:0}body,html{margin:0;overflow:hidden;padding:0}div#terminal{height:100%;left:0;position:absolute;top:0;width:100%}div#terminal div{height:100%}.xterm-screen,.xterm-viewport{height:100%;margin:0;padding:0}</style></head><body> <div id="terminal"></div> <script type="module" src="index.52560dc1.js"></script> </body></html> <!DOCTYPE html><html><head><link rel="stylesheet" href="index.6999253a.css"><title>{{.AppName}}</title><style>body::-webkit-scrollbar,div::-webkit-scrollbar,html::-webkit-scrollbar{display:none;width:0}body,html{margin:0;overflow:hidden;padding:0}div#terminal{height:100%;left:0;position:absolute;top:0;width:100%}div#terminal div{height:100%}.xterm-screen,.xterm-viewport{height:100%;margin:0;padding:0}</style></head><body> <div id="terminal"></div> <script type="module" src="index.2719cc8f.js"></script> </body></html>