From 329d6aad1cc88337550bb9c52ae2f4f83ec33b40 Mon Sep 17 00:00:00 2001 From: Boshi Lian Date: Tue, 13 Jul 2021 12:20:20 +0000 Subject: [PATCH] fix db model not loading keys --- sshpiperd/loader.go | 2 +- sshpiperd/upstream/database/handler.go | 197 +++++++------------- sshpiperd/upstream/database/handler_test.go | 2 +- sshpiperd/upstream/database/model.go | 46 +---- sshpiperd/upstream/database/plugin.go | 9 +- 5 files changed, 80 insertions(+), 176 deletions(-) diff --git a/sshpiperd/loader.go b/sshpiperd/loader.go index 0084c41b..26a869bf 100644 --- a/sshpiperd/loader.go +++ b/sshpiperd/loader.go @@ -2,9 +2,9 @@ package main import ( _ "github.com/tg123/sshpiper/sshpiperd/upstream/database" + _ "github.com/tg123/sshpiper/sshpiperd/upstream/kubernetes" _ "github.com/tg123/sshpiper/sshpiperd/upstream/workingdir" _ "github.com/tg123/sshpiper/sshpiperd/upstream/yaml" - _ "github.com/tg123/sshpiper/sshpiperd/upstream/kubernetes" _ "github.com/tg123/sshpiper/sshpiperd/challenger/authy" _ "github.com/tg123/sshpiper/sshpiperd/challenger/azdevicecode" diff --git a/sshpiperd/upstream/database/handler.go b/sshpiperd/upstream/database/handler.go index a0cde132..a13c168e 100644 --- a/sshpiperd/upstream/database/handler.go +++ b/sshpiperd/upstream/database/handler.go @@ -19,13 +19,13 @@ type pipeConfig struct { MappedUsername string FromType authMapType FromPassword string - FromPrivateKey downstreamPrivateKey - FromAuthorizedKeys []downstreamAuthorizedKey + FromPrivateKey keydata + FromAuthorizedKeys keydata FromAllowAnyPublicKey bool ToType authMapType ToPassword string - ToPrivateKey upstreamPrivateKey - ToAuthorizedKeys []upstreamAuthorizedKey + ToPrivateKey keydata + ToAuthorizedKeys keydata NoPassthrough bool KnownHosts string KnownHostsData string @@ -52,7 +52,6 @@ func (p *plugin) loadPipeFromDB(conn ssh.ConnMetadata) (pipeConfig, error) { ToType: d.Upstream.AuthMapType, ToPassword: d.Upstream.Password, ToPrivateKey: d.Upstream.PrivateKey, - ToAuthorizedKeys: d.Upstream.AuthorizedKeys, NoPassthrough: d.NoPassthrough, KnownHosts: d.Upstream.KnownHosts, IgnoreHostkey: d.Upstream.Server.IgnoreHostKey, @@ -79,9 +78,7 @@ func (p *plugin) createAuthPipe(pipe pipeConfig, conn ssh.ConnMetadata, challeng } } - to := func(key ssh.PublicKey) (ssh.AuthPipeType, ssh.AuthMethod, error) { - var err error - + to := func() (ssh.AuthPipeType, ssh.AuthMethod, error) { switch pipe.ToType { case authMapTypeNone: return ssh.AuthPipeTypeNone, nil, nil @@ -90,36 +87,7 @@ func (p *plugin) createAuthPipe(pipe pipeConfig, conn ssh.ConnMetadata, challeng return ssh.AuthPipeTypeMap, ssh.Password(pipe.ToPassword), nil case authMapTypePrivateKey: - - privateBytes := []byte(pipe.ToPrivateKey.Key.Data) - - // did not find to 1 private key try key map - if len(privateBytes) == 0 && key != nil { - for _, privkey := range pipe.ToAuthorizedKeys { - rest := []byte(privkey.Key.Data) - - var authedPubkey ssh.PublicKey - - for len(rest) > 0 { - authedPubkey, _, _, rest, err = ssh.ParseAuthorizedKey(rest) - if err != nil { - return ssh.AuthPipeTypeDiscard, nil, err - } - - keydata := key.Marshal() - - if bytes.Equal(authedPubkey.Marshal(), keydata) { - privateBytes = []byte(pipe.ToPrivateKey.Key.Data) - - if len(privateBytes) > 0 { - // found mapped - break - } - } - } - - } - } + privateBytes := []byte(pipe.ToPrivateKey.Data) if len(privateBytes) == 0 { return ssh.AuthPipeTypeDiscard, nil, fmt.Errorf("no private key found") @@ -143,109 +111,84 @@ func (p *plugin) createAuthPipe(pipe pipeConfig, conn ssh.ConnMetadata, challeng return ssh.AuthPipeTypePassThrough, nil, nil } - allowPasswords := make(map[string]bool) - var allowPubKeys []ssh.PublicKey - allowAnyPubKey := false - a := &ssh.AuthPipe{ - User: pipe.MappedUsername, - + User: pipe.MappedUsername, UpstreamHostKeyCallback: hostKeyCallback, } + noneauth := func(conn ssh.ConnMetadata) (ssh.AuthPipeType, ssh.AuthMethod, error) { + return to() + } + + passauth := func(conn ssh.ConnMetadata, password []byte) (ssh.AuthPipeType, ssh.AuthMethod, error) { + if string(password) == pipe.FromPassword { + return to() + } + + if pipe.NoPassthrough { + return ssh.AuthPipeTypeDiscard, nil, nil + } + + return ssh.AuthPipeTypePassThrough, nil, nil + } + + var allowPubKeys []ssh.PublicKey + allowAnyPubKey := pipe.FromAllowAnyPublicKey + if !allowAnyPubKey { + var err error + rest := []byte(pipe.FromAuthorizedKeys.Data) + + var authedPubkey ssh.PublicKey + + for len(rest) > 0 { + authedPubkey, _, _, rest, err = ssh.ParseAuthorizedKey(rest) + if err != nil { + return nil, err + } + + allowPubKeys = append(allowPubKeys, authedPubkey) + } + } + + keyuath := func(conn ssh.ConnMetadata, key ssh.PublicKey) (ssh.AuthPipeType, ssh.AuthMethod, error) { + + if allowAnyPubKey { + return to() + } + + keydata := key.Marshal() + + for _, authedPubkey := range allowPubKeys { + if bytes.Equal(authedPubkey.Marshal(), keydata) { + return to() + } + } + + if pipe.NoPassthrough { + return ssh.AuthPipeTypeDiscard, nil, nil + } + + // will fail but discard will lead a timeout + return ssh.AuthPipeTypePassThrough, nil, nil + } + switch pipe.FromType { case authMapTypeNone: - - if a.NoneAuthCallback == nil { - a.NoneAuthCallback = func(conn ssh.ConnMetadata) (ssh.AuthPipeType, ssh.AuthMethod, error) { - return to(nil) - } - } + a.NoneAuthCallback = noneauth case authMapTypePassword: - - allowPasswords[pipe.FromPassword] = true - - if a.PasswordCallback == nil { - a.PasswordCallback = func(conn ssh.ConnMetadata, password []byte) (ssh.AuthPipeType, ssh.AuthMethod, error) { - - _, ok := allowPasswords[string(password)] - - if ok { - return to(nil) - } - - if pipe.NoPassthrough { - return ssh.AuthPipeTypeDiscard, nil, nil - } - - return ssh.AuthPipeTypePassThrough, nil, nil - } - } + a.PasswordCallback = passauth case authMapTypePrivateKey: - var err error - - allowAnyPubKey = allowAnyPubKey || pipe.FromAllowAnyPublicKey - - if !allowAnyPubKey { - for _, privkey := range pipe.FromAuthorizedKeys { - rest := []byte(privkey.Key.Data) - - var authedPubkey ssh.PublicKey - - for len(rest) > 0 { - authedPubkey, _, _, rest, err = ssh.ParseAuthorizedKey(rest) - if err != nil { - return nil, err - } - - allowPubKeys = append(allowPubKeys, authedPubkey) - } - } - } - - if a.PublicKeyCallback == nil { - a.PublicKeyCallback = func(conn ssh.ConnMetadata, key ssh.PublicKey) (ssh.AuthPipeType, ssh.AuthMethod, error) { - - if allowAnyPubKey { - return to(key) - } - - keydata := key.Marshal() - - for _, authedPubkey := range allowPubKeys { - if bytes.Equal(authedPubkey.Marshal(), keydata) { - return to(key) - } - } - - if pipe.NoPassthrough { - return ssh.AuthPipeTypeDiscard, nil, nil - } - - // will fail but discard will lead a timeout - return ssh.AuthPipeTypePassThrough, nil, nil - } - } + a.PublicKeyCallback = keyuath case authMapTypeAny: - a.NoneAuthCallback = func(conn ssh.ConnMetadata) (ssh.AuthPipeType, ssh.AuthMethod, error) { - return to(nil) - } - - a.PasswordCallback = func(conn ssh.ConnMetadata, password []byte) (ssh.AuthPipeType, ssh.AuthMethod, error) { - return to(nil) - } - - a.PublicKeyCallback = func(conn ssh.ConnMetadata, key ssh.PublicKey) (ssh.AuthPipeType, ssh.AuthMethod, error) { - return to(key) - } - - return a, nil + a.NoneAuthCallback = noneauth + a.PasswordCallback = passauth + a.PublicKeyCallback = keyuath default: - return a, fmt.Errorf("unsupported auth type [%v],", pipe.FromType) + return nil, fmt.Errorf("unsupported auth type [%v],", pipe.FromType) } return a, nil diff --git a/sshpiperd/upstream/database/handler_test.go b/sshpiperd/upstream/database/handler_test.go index dd1938f8..5310ab6c 100644 --- a/sshpiperd/upstream/database/handler_test.go +++ b/sshpiperd/upstream/database/handler_test.go @@ -92,7 +92,7 @@ func createEntry(t *testing.T, db *gorm.DB, downUser, upUser, serverAddr string, Upstream: upstream{ Username: upUser, AuthMapType: authMapTypePrivateKey, - PrivateKey: upstreamPrivateKey{ + PrivateKey: privateKey{ Key: keydata{ Data: priv, Type: "rsa", diff --git a/sshpiperd/upstream/database/model.go b/sshpiperd/upstream/database/model.go index 33f98a31..fd85593e 100644 --- a/sshpiperd/upstream/database/model.go +++ b/sshpiperd/upstream/database/model.go @@ -23,27 +23,6 @@ type keydata struct { Type string `gorm:"type:varchar(45)"` } -type upstreamPrivateKey struct { - Key keydata - KeyID int - - UpstreamID int -} - -type downstreamPrivateKey struct { - Key keydata - KeyID int - - DownstreamID int -} - -type hostKey struct { - Key keydata - KeyID int - - ServerID int -} - type server struct { gorm.Model @@ -51,7 +30,7 @@ type server struct { Address string `gorm:"type:varchar(100)"` HostKeyID int - HostKey hostKey + HostKey keydata IgnoreHostKey bool } @@ -65,18 +44,9 @@ type upstream struct { Username string `gorm:"type:varchar(45)"` Password string `gorm:"type:varchar(60)"` PrivateKeyID int - PrivateKey upstreamPrivateKey + PrivateKey keydata AuthMapType authMapType KnownHosts string `gorm:"type:varchar(100)"` - - AuthorizedKeys []upstreamAuthorizedKey -} - -type upstreamAuthorizedKey struct { - Key keydata - KeyID int - - DownstreamID int } type downstream struct { @@ -85,8 +55,6 @@ type downstream struct { Name string `gorm:"type:varchar(45)"` Username string `gorm:"type:varchar(45);unique_index"` Password string `gorm:"type:varchar(60)"` - PrivateKeyID int - PrivateKey downstreamPrivateKey AuthMapType authMapType AllowAnyPublicKey bool NoPassthrough bool @@ -94,14 +62,8 @@ type downstream struct { UpstreamID int Upstream upstream - AuthorizedKeys []downstreamAuthorizedKey -} - -type downstreamAuthorizedKey struct { - Key keydata - KeyID int - - UpstreamID int + AuthorizedKeysID int + AuthorizedKeys keydata } type config struct { diff --git a/sshpiperd/upstream/database/plugin.go b/sshpiperd/upstream/database/plugin.go index 3487f91c..66c5f6ce 100644 --- a/sshpiperd/upstream/database/plugin.go +++ b/sshpiperd/upstream/database/plugin.go @@ -38,13 +38,8 @@ func (p *plugin) Init(glogger *log.Logger) error { err = db.AutoMigrate( new(keydata), - new(upstreamPrivateKey), - new(downstreamPrivateKey), - new(hostKey), new(server), new(upstream), - new(upstreamAuthorizedKey), - new(downstreamAuthorizedKey), new(downstream), new(config), ).Error @@ -53,6 +48,10 @@ func (p *plugin) Init(glogger *log.Logger) error { logger.Printf("AutoMigrate error: %v", err) } + // TODO add config + // db.SetLogger(logger) + // db.LogMode(true) + p.db = db // plugin is alive within program lifecycle, close when unload added