fix db model not loading keys

This commit is contained in:
Boshi Lian 2021-07-13 12:20:20 +00:00
parent 0b4bff37d7
commit 329d6aad1c
5 changed files with 80 additions and 176 deletions

View file

@ -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"

View file

@ -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

View file

@ -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",

View file

@ -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 {

View file

@ -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