You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.2 KiB
Go
116 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"path"
|
|
"strings"
|
|
"sync"
|
|
"syscall"
|
|
|
|
"git.sr.ht/~tslocum/sshtargate/pkg/gate"
|
|
"github.com/anmitsu/go-shlex"
|
|
)
|
|
|
|
const (
|
|
version = "0.0.0"
|
|
|
|
versionInfo = `sshtargate - Host SSH portals to applications - v` + version + `
|
|
https://git.sr.ht/~tslocum/sshtargate
|
|
The MIT License (MIT)
|
|
Copyright (c) 2020 Trevor Slocum <trevor@rocketnine.space>
|
|
`
|
|
)
|
|
|
|
var (
|
|
printVersionInfo bool
|
|
configPath string
|
|
|
|
portals []*gate.Portal
|
|
portalsLock = new(sync.Mutex)
|
|
|
|
done = make(chan bool)
|
|
)
|
|
|
|
func main() {
|
|
flag.BoolVar(&printVersionInfo, "version", false, "print version information and exit")
|
|
flag.StringVar(&configPath, "config", "", "path to configuration file")
|
|
flag.Parse()
|
|
|
|
if printVersionInfo {
|
|
fmt.Print(versionInfo)
|
|
return
|
|
}
|
|
|
|
// TODO: Allow portals to be specified via arguments
|
|
|
|
// TODO: Catch SIGHUP
|
|
sigc := make(chan os.Signal, 1)
|
|
signal.Notify(sigc,
|
|
syscall.SIGINT,
|
|
syscall.SIGTERM)
|
|
go func() {
|
|
<-sigc
|
|
|
|
done <- true
|
|
}()
|
|
|
|
log.Println("Initializing sshtargate...")
|
|
|
|
if configPath == "" {
|
|
homedir, err := os.UserHomeDir()
|
|
if err == nil && homedir != "" {
|
|
configPath = path.Join(homedir, ".config", "sshtargate", "config.yaml")
|
|
}
|
|
}
|
|
|
|
err := readConfig(configPath)
|
|
if err != nil {
|
|
log.Fatalf("failed to read configuration file %s: %s", configPath, err)
|
|
}
|
|
|
|
for pname, pcfg := range config.Portals {
|
|
cs, err := shlex.Split(pcfg.Command, true)
|
|
if err != nil {
|
|
log.Fatalf("failed to split command %s", pcfg.Command)
|
|
}
|
|
|
|
pname, pcfg := pname, pcfg // Capture
|
|
go func() {
|
|
wg := new(sync.WaitGroup)
|
|
|
|
for _, address := range pcfg.Host {
|
|
wg.Add(1)
|
|
address := address // Capture
|
|
|
|
go func() {
|
|
p, err := gate.NewPortal(pname, address, cs)
|
|
if err != nil {
|
|
log.Fatalf("failed to start portal %s on %s: %s", pname, address, err)
|
|
}
|
|
|
|
portalsLock.Lock()
|
|
portals = append(portals, p)
|
|
portalsLock.Unlock()
|
|
|
|
wg.Done()
|
|
}()
|
|
}
|
|
|
|
wg.Wait()
|
|
log.Printf("Opened portal %s on %s to %s", pname, strings.Join(pcfg.Host, ","), pcfg.Command)
|
|
}()
|
|
}
|
|
|
|
<-done
|
|
|
|
portalsLock.Lock()
|
|
for _, p := range portals {
|
|
p.Shutdown()
|
|
}
|
|
portalsLock.Unlock()
|
|
}
|