...
1 package main
2
3 import (
4 "flag"
5 "fmt"
6 "log"
7 "os"
8 "os/signal"
9 "strings"
10 "sync"
11 "syscall"
12
13 "codeberg.org/tslocum/sshtargate/portal"
14 "github.com/anmitsu/go-shlex"
15 )
16
17 const (
18 version = "0.0.0"
19
20 versionInfo = `sshtargate - Host SSH portals to applications - v` + version + `
21 https://codeberg.org/tslocum/sshtargate
22 The MIT License (MIT)
23 Copyright (c) 2020 Trevor Slocum <trevor@rocket9labs.com>
24 `
25 )
26
27 var (
28 printVersionInfo bool
29 configPath string
30
31 portals []*portal.Portal
32 portalsLock = new(sync.Mutex)
33
34 done = make(chan bool)
35 )
36
37 func main() {
38 flag.BoolVar(&printVersionInfo, "version", false, "print version information and exit")
39 flag.StringVar(&configPath, "config", "", "path to configuration file")
40 flag.Parse()
41
42 if printVersionInfo {
43 fmt.Print(versionInfo)
44 return
45 }
46
47 if configPath == "" {
48 var err error
49 configPath, err = defaultConfigPath()
50 if err != nil {
51 log.Fatal(err)
52 }
53 }
54
55
56
57
58 sigc := make(chan os.Signal, 1)
59 signal.Notify(sigc,
60 syscall.SIGINT,
61 syscall.SIGTERM)
62 go func() {
63 <-sigc
64
65 done <- true
66 }()
67
68 log.Println("Initializing sshtargate...")
69
70 err := deserializeConfig(configPath)
71 if err != nil {
72 log.Fatalf("failed to read configuration file: %s", err)
73 }
74
75 if len(config.Portals) == 0 {
76 log.Println("Warning: No portals are defined")
77 }
78
79 for pname, pcfg := range config.Portals {
80 cs, err := shlex.Split(pcfg.Command, true)
81 if err != nil {
82 log.Fatalf("failed to split command %s", pcfg.Command)
83 }
84
85 pname, pcfg := pname, pcfg
86 go func() {
87 wg := new(sync.WaitGroup)
88
89 for _, address := range pcfg.Host {
90 wg.Add(1)
91 address := address
92
93 go func() {
94 p, err := portal.New(pname, address, cs)
95 if err != nil {
96 log.Fatalf("failed to start portal %s on %s: %s", pname, address, err)
97 }
98
99 portalsLock.Lock()
100 portals = append(portals, p)
101 portalsLock.Unlock()
102
103 wg.Done()
104 }()
105 }
106
107 wg.Wait()
108 log.Printf("Opened portal %s on %s to %s", pname, strings.Join(pcfg.Host, ","), pcfg.Command)
109 }()
110 }
111
112 <-done
113
114 portalsLock.Lock()
115 for _, p := range portals {
116 p.Shutdown()
117 }
118 portalsLock.Unlock()
119 }
120
View as plain text