introduce working dir pipe mgr
This commit is contained in:
parent
7e9f9300d4
commit
650023f363
7 changed files with 133 additions and 97 deletions
7
Gopkg.lock
generated
7
Gopkg.lock
generated
|
|
@ -14,10 +14,11 @@
|
|||
revision = "d32a9ef172a1ec91efdf3ce26b240c946285bfe7"
|
||||
|
||||
[[projects]]
|
||||
branch = "ignore_unknown_ini"
|
||||
name = "github.com/jessevdk/go-flags"
|
||||
packages = ["."]
|
||||
revision = "c6ca198ec95c841fdb89fc0de7496fed11ab854e"
|
||||
version = "v1.4.0"
|
||||
revision = "f0dfbc82957e3db331cb27732d270e275614b005"
|
||||
source = "https://github.com/tg123/go-flags"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jinzhu/gorm"
|
||||
|
|
@ -65,6 +66,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "52065920d52958f5461e7df92a92483c9eb78c9bb4b504e0bc82e68e38cfb191"
|
||||
inputs-digest = "534da9de5467ab2fd3960701473a3fd7da82684491b7b65f21644b0a6b7147f5"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
|||
|
|
@ -30,5 +30,6 @@
|
|||
name = "github.com/jinzhu/gorm"
|
||||
|
||||
[[constraint]]
|
||||
version = "v1.4.0"
|
||||
branch = "ignore_unknown_ini"
|
||||
name = "github.com/jessevdk/go-flags"
|
||||
source = "https://github.com/tg123/go-flags"
|
||||
|
|
|
|||
188
sshpiperd/cmd.go
188
sshpiperd/cmd.go
|
|
@ -19,15 +19,17 @@ func (s *subCommand) Execute(args []string) error {
|
|||
return s.callback(args)
|
||||
}
|
||||
|
||||
func addSubCommand(parser *flags.Parser, name, desc string, callback interface{}) {
|
||||
_, err := parser.AddCommand(name, desc, "", callback)
|
||||
func addSubCommand(parser *flags.Command, name, desc string, callback interface{}) *flags.Command {
|
||||
c, err := parser.AddCommand(name, desc, "", callback)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func addOpt(parser *flags.Parser, name string, data interface{}) {
|
||||
func addOpt(parser *flags.Group, name string, data interface{}) {
|
||||
_, err := parser.AddGroup(name, "", data)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -35,7 +37,7 @@ func addOpt(parser *flags.Parser, name string, data interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
func addPlugins(parser *flags.Parser, name string, pluginNames []string, getter func(n string) registry.Plugin) {
|
||||
func addPlugins(parser *flags.Group, name string, pluginNames []string, getter func(n string) registry.Plugin) {
|
||||
for _, n := range pluginNames {
|
||||
|
||||
p := getter(n)
|
||||
|
|
@ -76,30 +78,41 @@ func populateFromConfig(ini *flags.IniParser, data interface{}, longopt string)
|
|||
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", &subCommand{func(args []string) error {
|
||||
showVersion()
|
||||
return nil
|
||||
}})
|
||||
// public config
|
||||
configFile := &struct {
|
||||
ConfigFile flags.Filename `long:"config" description:"Config file path. Will be overwriten by arg options and environment variables" default:"/etc/sshpiperd.ini" env:"SSHPIPERD_CONFIG_FILE" no-ini:"true"`
|
||||
}{}
|
||||
addOpt(parser.Group, "sshpiperd", configFile)
|
||||
|
||||
// dumpini
|
||||
addSubCommand(parser, "dumpconfig", "dump current config ini to stdout", &subCommand{func(args []string) error {
|
||||
loadFromConfigFile := func(c *flags.Command) {
|
||||
parser := flags.NewNamedParser("sshpiperd", flags.IgnoreUnknown)
|
||||
parser.Command = c
|
||||
ini := flags.NewIniParser(parser)
|
||||
ini.Write(os.Stdout, flags.IniIncludeDefaults)
|
||||
return nil
|
||||
}})
|
||||
err := populateFromConfig(ini, configFile, "config")
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Sprintf("load config file failed %v", err))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// version
|
||||
{
|
||||
addSubCommand(parser.Command, "version", "show version", &subCommand{func(args []string) error {
|
||||
showVersion()
|
||||
return nil
|
||||
}})
|
||||
}
|
||||
|
||||
// manpage
|
||||
addSubCommand(parser, "manpage", "write man page to stdout", &subCommand{func(args []string) error {
|
||||
addSubCommand(parser.Command, "manpage", "write man page to stdout", &subCommand{func(args []string) error {
|
||||
parser.WriteManPage(os.Stdout)
|
||||
return nil
|
||||
}})
|
||||
|
||||
// plugins
|
||||
addSubCommand(parser, "plugins", "list support plugins, e.g. sshpiperd plugis upstream", &subCommand{func(args []string) error {
|
||||
addSubCommand(parser.Command, "plugins", "list support plugins, e.g. sshpiperd plugis upstream", &subCommand{func(args []string) error {
|
||||
|
||||
output := func(all []string) {
|
||||
for _, p := range all {
|
||||
|
|
@ -126,68 +139,59 @@ func main() {
|
|||
return nil
|
||||
}})
|
||||
|
||||
// options, for snap only at the moment
|
||||
addSubCommand(parser, "options", "list all options", &subCommand{func(args []string) error {
|
||||
for _, g := range parser.Groups() {
|
||||
for _, o := range g.Options() {
|
||||
fmt.Println(o.LongName)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}})
|
||||
|
||||
// generate key tools
|
||||
addSubCommand(parser, "genkey", "generate a 2048 rsa key to stdout", &subCommand{func(args []string) error {
|
||||
key, err := sshkey.GenerateKey(sshkey.KEY_RSA, 2048)
|
||||
if err != nil {
|
||||
{
|
||||
addSubCommand(parser.Command, "genkey", "generate a 2048 rsa key to stdout", &subCommand{func(args []string) error {
|
||||
key, err := sshkey.GenerateKey(sshkey.KEY_RSA, 2048)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := sshkey.MarshalPrivate(key, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprint(os.Stdout, string(out))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := sshkey.MarshalPrivate(key, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprint(os.Stdout, string(out))
|
||||
|
||||
return err
|
||||
}})
|
||||
|
||||
config := &struct {
|
||||
piperdConfig
|
||||
|
||||
loggerConfig
|
||||
|
||||
// need to be shown in help, or will be moved to populate config
|
||||
ConfigFile flags.Filename `long:"config" description:"Config file path. Will be overwriten by arg options and environment variables" default:"/etc/sshpiperd.ini" env:"SSHPIPERD_CONFIG_FILE" no-ini:"true"`
|
||||
}{}
|
||||
|
||||
addSubCommand(parser, "pipe", "manage pipe on current upstream driver", createPipeMgr(&config.UpstreamDriver))
|
||||
|
||||
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) })
|
||||
|
||||
// populate by config
|
||||
ini := flags.NewIniParser(parser)
|
||||
err := populateFromConfig(ini, config, "config")
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Sprintf("load config file failed %v", err))
|
||||
os.Exit(1)
|
||||
}})
|
||||
}
|
||||
|
||||
parser.CommandHandler = func(command flags.Commander, args []string) error {
|
||||
// pipe management
|
||||
{
|
||||
config := &struct {
|
||||
UpstreamDriver string `long:"upstream-driver" description:"Upstream provider driver" default:"workingdir" env:"SSHPIPERD_UPSTREAM_DRIVER" ini-name:"upstream-driver"`
|
||||
}{}
|
||||
|
||||
// no subcommand called, start to serve
|
||||
if command == nil {
|
||||
var c *flags.Command
|
||||
c = addSubCommand(parser.Command, "pipe", "manage pipe on current upstream driver", createPipeMgr(func() (upstream.Provider, error) {
|
||||
|
||||
if len(args) > 0 {
|
||||
return fmt.Errorf("unknown command %v", args)
|
||||
loadFromConfigFile(c)
|
||||
|
||||
if config.UpstreamDriver == "" {
|
||||
return nil, fmt.Errorf("must provider upstream driver")
|
||||
}
|
||||
|
||||
return upstream.Get(config.UpstreamDriver).(upstream.Provider), nil
|
||||
}))
|
||||
|
||||
addOpt(c.Group, "sshpiperd", config)
|
||||
addPlugins(c.Group, "upstream", upstream.All(), func(n string) registry.Plugin { return upstream.Get(n) })
|
||||
}
|
||||
|
||||
// daemon command
|
||||
{
|
||||
config := &struct {
|
||||
piperdConfig
|
||||
loggerConfig
|
||||
}{}
|
||||
|
||||
var c *flags.Command
|
||||
c = addSubCommand(parser.Command, "daemon", "run in daemon mode, serving traffic", &subCommand{func(args []string) error {
|
||||
// populate by config
|
||||
loadFromConfigFile(c)
|
||||
|
||||
showVersion()
|
||||
|
||||
// dump used configure only
|
||||
|
|
@ -195,7 +199,7 @@ func main() {
|
|||
fmt.Println()
|
||||
for _, gk := range []string{"sshpiperd", "upstream." + config.UpstreamDriver, "challenger." + config.ChallengerDriver, "auditor." + config.AuditorDriver} {
|
||||
|
||||
g := parser.Group.Find(gk)
|
||||
g := c.Group.Find(gk)
|
||||
if g == nil {
|
||||
continue
|
||||
}
|
||||
|
|
@ -210,9 +214,45 @@ func main() {
|
|||
}
|
||||
|
||||
return startPiper(&config.piperdConfig, config.createLogger())
|
||||
}
|
||||
}})
|
||||
c.SubcommandsOptional = true
|
||||
|
||||
addOpt(c.Group, "sshpiperd", config)
|
||||
addPlugins(c.Group, "upstream", upstream.All(), func(n string) registry.Plugin { return upstream.Get(n) })
|
||||
addPlugins(c.Group, "challenger", challenger.All(), func(n string) registry.Plugin { return challenger.Get(n) })
|
||||
addPlugins(c.Group, "auditor", auditor.All(), func(n string) registry.Plugin { return auditor.Get(n) })
|
||||
|
||||
// dumpini for daemon
|
||||
addSubCommand(c, "dumpconfig", "dump current config for daemon ini to stdout", &subCommand{func(args []string) error {
|
||||
loadFromConfigFile(c)
|
||||
|
||||
parser := flags.NewNamedParser("sshpiperd", flags.Default)
|
||||
parser.Command = c
|
||||
ini := flags.NewIniParser(parser)
|
||||
ini.Write(os.Stdout, flags.IniIncludeDefaults)
|
||||
return nil
|
||||
}})
|
||||
|
||||
// options, for snap only at the moment
|
||||
addSubCommand(c, "options", "list all options for daemon mode", &subCommand{func(args []string) error {
|
||||
|
||||
var printOpts func(*flags.Group)
|
||||
|
||||
printOpts = func(group *flags.Group) {
|
||||
for _, o := range group.Options() {
|
||||
fmt.Println(o.LongName)
|
||||
}
|
||||
|
||||
for _, g := range group.Groups() {
|
||||
printOpts(g)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
printOpts(c.Group)
|
||||
return nil
|
||||
}})
|
||||
|
||||
return command.Execute(args)
|
||||
}
|
||||
|
||||
parser.Parse()
|
||||
|
|
|
|||
|
|
@ -1,20 +1,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/tg123/sshpiper/sshpiperd/upstream"
|
||||
)
|
||||
|
||||
func createPipeMgr(driver *string) interface{} {
|
||||
|
||||
load := func() (upstream.Provider, error) {
|
||||
if *driver == "" {
|
||||
return nil, fmt.Errorf("must provider upstream driver")
|
||||
}
|
||||
|
||||
return upstream.Get(*driver).(upstream.Provider), nil
|
||||
}
|
||||
|
||||
func createPipeMgr(load func() (upstream.Provider, error)) interface{} {
|
||||
// pipe management
|
||||
pipeMgrCmd := struct {
|
||||
List struct {
|
||||
|
|
@ -23,12 +13,12 @@ func createPipeMgr(driver *string) interface{} {
|
|||
Add struct {
|
||||
subCommand
|
||||
|
||||
PiperUserName string `long:"piper-username" description:"" required:"true" no-ini:"true"`
|
||||
PiperUserName string `short:"n" long:"piper-username" description:"" required:"true" no-ini:"true"`
|
||||
// PiperAuthorizedKeysFile flags.Filename
|
||||
|
||||
UpstreamUserName string `long:"upstream-username" description:"mapped user name" no-ini:"true"`
|
||||
UpstreamHost string `long:"host" description:"upstream sshd host" required:"true" no-ini:"true"`
|
||||
UpstreamPort uint `long:"port" description:"upstream sshd port" default:"22" no-ini:"true"`
|
||||
UpstreamHost string `short:"u" long:"host" description:"upstream sshd host" required:"true" no-ini:"true"`
|
||||
UpstreamPort uint `short:"p" long:"port" description:"upstream sshd port" default:"22" no-ini:"true"`
|
||||
// UpstreamKeyFile flags.Filename
|
||||
|
||||
// UpstreamHostKey
|
||||
|
|
@ -38,7 +28,7 @@ func createPipeMgr(driver *string) interface{} {
|
|||
Remove struct {
|
||||
subCommand
|
||||
|
||||
Name string `long:"name" required:"true" no-ini:"true"`
|
||||
Name string `short:"n" long:"piper-username" required:"true" no-ini:"true"`
|
||||
} `command:"remove" description:"remove a pipe from current upstream"`
|
||||
}{}
|
||||
|
||||
|
|
|
|||
4
sshpiperd/snap/snap/hooks/configure
vendored
4
sshpiperd/snap/snap/hooks/configure
vendored
|
|
@ -5,7 +5,7 @@ bin=$SNAP/sshpiperd
|
|||
config=$SNAP_DATA/sshpiperd.ini
|
||||
|
||||
args=""
|
||||
for opt in $($bin options); do
|
||||
for opt in $($bin daemon options); do
|
||||
v=$(snapctl get $opt)
|
||||
|
||||
if [ "$v" != "" ]; then
|
||||
|
|
@ -27,4 +27,4 @@ for opt in $($bin options); do
|
|||
done
|
||||
|
||||
echo ";DO NOT MODIFY, USE snap set sshpiperd key=val, AUTO GENERATED" $(date) > $config
|
||||
$bin --config /dev/null $args dumpconfig >> $config
|
||||
$bin daemon --config /dev/null $args dumpconfig >> $config
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ parts:
|
|||
|
||||
apps:
|
||||
sshpiperd-daemon:
|
||||
command: sshpiperd --config $SNAP_DATA/sshpiperd.ini
|
||||
command: sshpiperd daemon --config $SNAP_DATA/sshpiperd.ini
|
||||
plugs: [network-bind]
|
||||
daemon: simple
|
||||
sshpiperd:
|
||||
|
|
|
|||
6
vendor/github.com/jessevdk/go-flags/ini.go
generated
vendored
6
vendor/github.com/jessevdk/go-flags/ini.go
generated
vendored
|
|
@ -505,7 +505,11 @@ func (i *IniParser) parse(ini *ini) error {
|
|||
groups := i.matchingGroups(name)
|
||||
|
||||
if len(groups) == 0 {
|
||||
return newErrorf(ErrUnknownGroup, "could not find option group `%s'", name)
|
||||
if (p.Options & IgnoreUnknown) == None {
|
||||
return newErrorf(ErrUnknownGroup, "could not find option group `%s'", name)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
for _, inival := range section {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue