sshpiper/sshpiperd/cmd.go
2018-12-29 06:13:14 +00:00

129 lines
3.3 KiB
Go

package main
import (
"fmt"
"os"
"github.com/jessevdk/go-flags"
"github.com/tg123/sshpiper/sshpiperd/auditor"
_ "github.com/tg123/sshpiper/sshpiperd/auditor/loader"
"github.com/tg123/sshpiper/sshpiperd/challenger"
_ "github.com/tg123/sshpiper/sshpiperd/challenger/loader"
"github.com/tg123/sshpiper/sshpiperd/registry"
"github.com/tg123/sshpiper/sshpiperd/upstream"
_ "github.com/tg123/sshpiper/sshpiperd/upstream/loader"
)
type subCommand struct{ callback func(args []string) error }
func (s *subCommand) Execute(args []string) error {
return s.callback(args)
}
func addSubCommand(parser *flags.Parser, name, desc string, callback func(args []string) error) {
_, err := parser.AddCommand(name, desc, "", &subCommand{callback})
if err != nil {
panic(err)
}
}
func addOpt(parser *flags.Parser, name string, data interface{}) {
_, err := parser.AddGroup(name, "", data)
if err != nil {
panic(err)
}
}
func addPlugins(parser *flags.Parser, name string, pluginNames []string, getter func(n string) registry.Plugin) {
for _, n := range pluginNames {
p := getter(n)
opt := p.GetOpts()
if opt == nil {
continue
}
_, err := parser.AddGroup(name+"."+p.GetName(), "", opt)
if err != nil {
panic(err)
}
}
}
func main() {
parser := flags.NewNamedParser("sshpiperd", flags.Default)
parser.SubcommandsOptional = true
parser.LongDescription = "SSH Piper works as a proxy-like ware, and route connections by username, src ip , etc. Please see <https://github.com/tg123/sshpiper> for more information"
// version
addSubCommand(parser, "version", "show version", func(args []string) error {
showVersion()
return nil
})
dumpConfig := func() {
ini := flags.NewIniParser(parser)
ini.Write(os.Stdout, flags.IniIncludeDefaults)
}
// dumpini
addSubCommand(parser, "dumpconfig", "dump current config ini to stdout", func(args []string) error {
dumpConfig()
return nil
})
// manpage
addSubCommand(parser, "manpage", "write man page to stdout", func(args []string) error {
parser.WriteManPage(os.Stdout)
return nil
})
config := &struct {
piperdConfig
Logfile string `long:"log" description:"Logfile path. Leave empty or any error occurs will fall back to stdout" env:"SSHPIPERD_LOG_PATH" ini-name:"log-path"`
ConfigFile flags.Filename `long:"config" description:"Config file path. Higher priority than arg options and environment variables" default:"/etc/sshpiperd.ini" env:"SSHPIPERD_CONFIG_FILE" no-ini:"true"`
}{}
addOpt(parser, "sshpiperd", config)
addPlugins(parser, "upstream", upstream.All(), func(n string) registry.Plugin { return upstream.Get(n) })
addPlugins(parser, "challenger", challenger.All(), func(n string) registry.Plugin { return challenger.Get(n) })
addPlugins(parser, "auditor", auditor.All(), func(n string) registry.Plugin { return auditor.Get(n) })
if _, err := parser.Parse(); err != nil {
return
}
o := parser.FindOptionByLongName("config")
ini := flags.NewIniParser(parser)
err := ini.ParseFile(string(config.ConfigFile))
if err != nil {
// set by user
if !o.IsSetDefault() {
fmt.Printf("load config file %v failed %v", config.ConfigFile, err)
fmt.Println()
os.Exit(1)
}
}
// init log
initLogger(config.Logfile)
// no subcommand called, start to serve
if parser.Active == nil {
showVersion()
dumpConfig()
startPiper(&config.piperdConfig)
}
}