Host SSH portals to applications
You can not 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

2 years ago
package main
import (
"flag"
"fmt"
"log"
"os"
"os/signal"
"path"
"strings"
"sync"
"syscall"
"github.com/anmitsu/go-shlex"
"gitlab.com/tslocum/sshtargate/pkg/gate"
2 years ago
)
const (
version = "0.0.0"
versionInfo = `sshtargate - Host SSH portals to applications - v` + version + `
https://gitlab.com/tslocum/sshtargate
2 years ago
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()
}