support cross auth type mapping (#483)
* add testcase * add fix * Refactor skelpipe wrappers to separate password and private key handling
This commit is contained in:
parent
503f112c5d
commit
085ba59c58
7 changed files with 152 additions and 57 deletions
|
|
@ -274,4 +274,20 @@ spec:
|
|||
username: "client_123"
|
||||
private_key_secret:
|
||||
name: host-publickey-key-ca
|
||||
ignore_hostkey: true
|
||||
ignore_hostkey: true
|
||||
---
|
||||
apiVersion: sshpiper.com/v1beta1
|
||||
kind: Pipe
|
||||
metadata:
|
||||
name: pipe-keytopass
|
||||
spec:
|
||||
from:
|
||||
- username: "keytopass"
|
||||
authorized_keys_file: /files/authorized_keys
|
||||
to:
|
||||
host: host-password:2222
|
||||
username: "user"
|
||||
password_secret:
|
||||
name: host-pass-secret
|
||||
ignore_hostkey: true
|
||||
---
|
||||
|
|
@ -36,6 +36,10 @@ func TestKubernetes(t *testing.T) {
|
|||
title: "key_public_ca",
|
||||
user: "hostcapublickey",
|
||||
},
|
||||
{
|
||||
title: "key_to_pass",
|
||||
user: "keytopass",
|
||||
},
|
||||
}
|
||||
|
||||
for _, testcase := range pubkeycases {
|
||||
|
|
|
|||
|
|
@ -168,29 +168,12 @@ func (p *SkelPlugin) PasswordCallback(conn ConnMetadata, password []byte) (*Upst
|
|||
return nil, err
|
||||
}
|
||||
|
||||
u, err := p.createUpstream(conn, to)
|
||||
u, err := p.createUpstream(conn, to, password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
toPass, ok := to.(SkelPipeToPassword)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("pipe to does not support password")
|
||||
}
|
||||
|
||||
overridepassword, err := toPass.OverridePassword(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if overridepassword != nil {
|
||||
u.Auth = CreatePasswordAuth(overridepassword)
|
||||
} else {
|
||||
u.Auth = CreatePasswordAuth(password)
|
||||
}
|
||||
|
||||
return u, nil
|
||||
|
||||
}
|
||||
|
||||
func (p *SkelPlugin) PublicKeyCallback(conn ConnMetadata, publicKey []byte) (*Upstream, error) {
|
||||
|
|
@ -270,27 +253,15 @@ func (p *SkelPlugin) PublicKeyCallback(conn ConnMetadata, publicKey []byte) (*Up
|
|||
return nil, err
|
||||
}
|
||||
|
||||
u, err := p.createUpstream(conn, to)
|
||||
u, err := p.createUpstream(conn, to, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
toPrivateKey, ok := to.(SkelPipeToPrivateKey)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("pipe to does not support private key")
|
||||
}
|
||||
|
||||
priv, cert, err := toPrivateKey.PrivateKey(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u.Auth = CreatePrivateKeyAuth(priv, cert)
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (p *SkelPlugin) createUpstream(conn ConnMetadata, to SkelPipeTo) (*Upstream, error) {
|
||||
func (p *SkelPlugin) createUpstream(conn ConnMetadata, to SkelPipeTo, originalPassword []byte) (*Upstream, error) {
|
||||
host, port, err := SplitHostPortForSSH(to.Host(conn))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -303,10 +274,36 @@ func (p *SkelPlugin) createUpstream(conn ConnMetadata, to SkelPipeTo) (*Upstream
|
|||
|
||||
p.cache.SetDefault(conn.UniqueID(), to)
|
||||
|
||||
return &Upstream{
|
||||
u := &Upstream{
|
||||
Host: host,
|
||||
Port: int32(port), // port is already checked to be within int32 range in SplitHostPortForSSH
|
||||
UserName: user,
|
||||
IgnoreHostKey: to.IgnoreHostKey(conn),
|
||||
}, err
|
||||
}
|
||||
|
||||
switch to := to.(type) {
|
||||
case SkelPipeToPassword:
|
||||
overridepassword, err := to.OverridePassword(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if overridepassword != nil {
|
||||
u.Auth = CreatePasswordAuth(overridepassword)
|
||||
} else {
|
||||
u.Auth = CreatePasswordAuth(originalPassword)
|
||||
}
|
||||
|
||||
case SkelPipeToPrivateKey:
|
||||
priv, cert, err := to.PrivateKey(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u.Auth = CreatePrivateKeyAuth(priv, cert)
|
||||
default:
|
||||
return nil, fmt.Errorf("pipe to does not support any auth method")
|
||||
}
|
||||
|
||||
return u, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,14 @@ type skelpipeToWrapper struct {
|
|||
username string
|
||||
}
|
||||
|
||||
type skelpipeToPasswordWrapper struct {
|
||||
skelpipeToWrapper
|
||||
}
|
||||
|
||||
type skelpipeToPrivateKeyWrapper struct {
|
||||
skelpipeToWrapper
|
||||
}
|
||||
|
||||
func (s *skelpipeWrapper) From() []libplugin.SkelPipeFrom {
|
||||
|
||||
w := skelpipeFromWrapper{
|
||||
|
|
@ -76,9 +84,21 @@ func (s *skelpipeFromWrapper) MatchConn(conn libplugin.ConnMetadata) (libplugin.
|
|||
}
|
||||
|
||||
if matched {
|
||||
return &skelpipeToWrapper{
|
||||
skelpipeWrapper: s.skelpipeWrapper,
|
||||
username: targetuser,
|
||||
|
||||
if s.pipe.PrivateKey != "" {
|
||||
return &skelpipeToPrivateKeyWrapper{
|
||||
skelpipeToWrapper: skelpipeToWrapper{
|
||||
skelpipeWrapper: s.skelpipeWrapper,
|
||||
username: targetuser,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &skelpipeToPasswordWrapper{
|
||||
skelpipeToWrapper: skelpipeToWrapper{
|
||||
skelpipeWrapper: s.skelpipeWrapper,
|
||||
username: targetuser,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +117,7 @@ func (s *skelpipePublicKeyWrapper) TrustedUserCAKeys(conn libplugin.ConnMetadata
|
|||
return nil, nil // TODO support this
|
||||
}
|
||||
|
||||
func (s *skelpipeToWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []byte, error) {
|
||||
func (s *skelpipeToPrivateKeyWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []byte, error) {
|
||||
k, err := base64.StdEncoding.DecodeString(s.pipe.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
@ -106,7 +126,7 @@ func (s *skelpipeToWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []b
|
|||
return k, nil, nil
|
||||
}
|
||||
|
||||
func (s *skelpipeToWrapper) OverridePassword(conn libplugin.ConnMetadata) ([]byte, error) {
|
||||
func (s *skelpipeToPasswordWrapper) OverridePassword(conn libplugin.ConnMetadata) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,14 @@ type skelpipeToWrapper struct {
|
|||
to *piperv1beta1.ToSpec
|
||||
}
|
||||
|
||||
type skelpipeToPasswordWrapper struct {
|
||||
skelpipeToWrapper
|
||||
}
|
||||
|
||||
type skelpipeToPrivateKeyWrapper struct {
|
||||
skelpipeToWrapper
|
||||
}
|
||||
|
||||
func (s *skelpipeWrapper) From() []libplugin.SkelPipeFrom {
|
||||
var froms []libplugin.SkelPipeFrom
|
||||
for _, f := range s.pipe.Spec.From {
|
||||
|
|
@ -108,11 +116,25 @@ func (s *skelpipeFromWrapper) MatchConn(conn libplugin.ConnMetadata) (libplugin.
|
|||
}
|
||||
|
||||
if matched {
|
||||
return &skelpipeToWrapper{
|
||||
plugin: s.plugin,
|
||||
pipe: s.pipe,
|
||||
username: targetuser,
|
||||
to: s.to,
|
||||
|
||||
if s.to.PrivateKeySecret.Name != "" {
|
||||
return &skelpipeToPrivateKeyWrapper{
|
||||
skelpipeToWrapper: skelpipeToWrapper{
|
||||
plugin: s.plugin,
|
||||
pipe: s.pipe,
|
||||
username: targetuser,
|
||||
to: s.to,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &skelpipeToPasswordWrapper{
|
||||
skelpipeToWrapper: skelpipeToWrapper{
|
||||
plugin: s.plugin,
|
||||
pipe: s.pipe,
|
||||
username: targetuser,
|
||||
to: s.to,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +178,7 @@ func (s *skelpipePublicKeyWrapper) TrustedUserCAKeys(conn libplugin.ConnMetadata
|
|||
return nil, nil // TODO support trusted_user_ca_keys
|
||||
}
|
||||
|
||||
func (s *skelpipeToWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []byte, error) {
|
||||
func (s *skelpipeToPrivateKeyWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []byte, error) {
|
||||
|
||||
log.Debugf("mapping to %v private key using secret %v", s.to.Host, s.to.PrivateKeySecret.Name)
|
||||
secret, err := s.plugin.k8sclient.Secrets(s.pipe.Namespace).Get(context.Background(), s.to.PrivateKeySecret.Name, metav1.GetOptions{})
|
||||
|
|
@ -189,7 +211,7 @@ func (s *skelpipeToWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []b
|
|||
return privateKey, publicKey, nil
|
||||
}
|
||||
|
||||
func (s *skelpipeToWrapper) OverridePassword(conn libplugin.ConnMetadata) ([]byte, error) {
|
||||
func (s *skelpipeToPasswordWrapper) OverridePassword(conn libplugin.ConnMetadata) ([]byte, error) {
|
||||
if s.to.PasswordSecret.Name != "" {
|
||||
log.Debugf("mapping to %v password using secret %v", s.to.Host, s.to.PasswordSecret.Name)
|
||||
secret, err := s.plugin.k8sclient.Secrets(s.pipe.Namespace).Get(context.Background(), s.to.PasswordSecret.Name, metav1.GetOptions{})
|
||||
|
|
|
|||
|
|
@ -42,6 +42,14 @@ type skelpipeToWrapper struct {
|
|||
skelpipeWrapper
|
||||
}
|
||||
|
||||
type skelpipeToPasswordWrapper struct {
|
||||
skelpipeToWrapper
|
||||
}
|
||||
|
||||
type skelpipeToPrivateKeyWrapper struct {
|
||||
skelpipeToWrapper
|
||||
}
|
||||
|
||||
func (s *skelpipeWrapper) From() []libplugin.SkelPipeFrom {
|
||||
|
||||
w := skelpipeFromWrapper{
|
||||
|
|
@ -76,8 +84,15 @@ func (s *skelpipeToWrapper) KnownHosts(conn libplugin.ConnMetadata) ([]byte, err
|
|||
}
|
||||
|
||||
func (s *skelpipeFromWrapper) MatchConn(conn libplugin.ConnMetadata) (libplugin.SkelPipeTo, error) {
|
||||
return &skelpipeToWrapper{
|
||||
skelpipeWrapper: s.skelpipeWrapper,
|
||||
|
||||
if s.dir.Exists(userKeyFile) {
|
||||
return &skelpipeToPrivateKeyWrapper{
|
||||
skelpipeToWrapper: skelpipeToWrapper(*s),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &skelpipeToPasswordWrapper{
|
||||
skelpipeToWrapper: skelpipeToWrapper(*s),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +108,7 @@ func (s *skelpipePublicKeyWrapper) TrustedUserCAKeys(conn libplugin.ConnMetadata
|
|||
return nil, nil // TODO support this
|
||||
}
|
||||
|
||||
func (s *skelpipeToWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []byte, error) {
|
||||
func (s *skelpipeToPrivateKeyWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []byte, error) {
|
||||
k, err := s.dir.Readfile(userKeyFile)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
@ -102,7 +117,7 @@ func (s *skelpipeToWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []b
|
|||
return k, nil, nil
|
||||
}
|
||||
|
||||
func (s *skelpipeToWrapper) OverridePassword(conn libplugin.ConnMetadata) ([]byte, error) {
|
||||
func (s *skelpipeToPasswordWrapper) OverridePassword(conn libplugin.ConnMetadata) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,14 @@ type skelpipeToWrapper struct {
|
|||
to *yamlPipeTo
|
||||
}
|
||||
|
||||
type skelpipeToPasswordWrapper struct {
|
||||
skelpipeToWrapper
|
||||
}
|
||||
|
||||
type skelpipeToPrivateKeyWrapper struct {
|
||||
skelpipeToWrapper
|
||||
}
|
||||
|
||||
func (s *skelpipeWrapper) From() []libplugin.SkelPipeFrom {
|
||||
var froms []libplugin.SkelPipeFrom
|
||||
for _, f := range s.pipe.From {
|
||||
|
|
@ -99,10 +107,23 @@ func (s *skelpipeFromWrapper) MatchConn(conn libplugin.ConnMetadata) (libplugin.
|
|||
}
|
||||
|
||||
if matched {
|
||||
return &skelpipeToWrapper{
|
||||
config: s.config,
|
||||
username: targetuser,
|
||||
to: s.to,
|
||||
|
||||
if s.to.PrivateKey != "" || s.to.PrivateKeyData != "" {
|
||||
return &skelpipeToPrivateKeyWrapper{
|
||||
skelpipeToWrapper: skelpipeToWrapper{
|
||||
config: s.config,
|
||||
username: targetuser,
|
||||
to: s.to,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &skelpipeToPasswordWrapper{
|
||||
skelpipeToWrapper: skelpipeToWrapper{
|
||||
config: s.config,
|
||||
username: targetuser,
|
||||
to: s.to,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +146,7 @@ func (s *skelpipePublicKeyWrapper) TrustedUserCAKeys(conn libplugin.ConnMetadata
|
|||
})
|
||||
}
|
||||
|
||||
func (s *skelpipeToWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []byte, error) {
|
||||
func (s *skelpipeToPrivateKeyWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []byte, error) {
|
||||
p, err := s.config.loadFileOrDecode(s.to.PrivateKey, s.to.PrivateKeyData, map[string]string{
|
||||
"DOWNSTREAM_USER": conn.User(),
|
||||
"UPSTREAM_USER": s.username,
|
||||
|
|
@ -138,7 +159,7 @@ func (s *skelpipeToWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []b
|
|||
return p, nil, nil
|
||||
}
|
||||
|
||||
func (s *skelpipeToWrapper) OverridePassword(conn libplugin.ConnMetadata) ([]byte, error) {
|
||||
func (s *skelpipeToPasswordWrapper) OverridePassword(conn libplugin.ConnMetadata) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue