Skip to content

Commit

Permalink
support cross auth type mapping (#483)
Browse files Browse the repository at this point in the history
* add testcase

* add fix

* Refactor skelpipe wrappers to separate password and private key handling
  • Loading branch information
tg123 authored Nov 10, 2024
1 parent 503f112 commit 085ba59
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 57 deletions.
18 changes: 17 additions & 1 deletion e2e/k8sworkload.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
---
4 changes: 4 additions & 0 deletions e2e/kubernetes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
65 changes: 31 additions & 34 deletions libplugin/skel.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -270,27 +253,15 @@ func (p *SkelPlugin) PublicKeyCallback(conn ConnMetadata, publicKey []byte) (*Up
return nil, err
}

u, err := p.createUpstream(conn, to)
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)
u, err := p.createUpstream(conn, to, nil)
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
Expand All @@ -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
}
30 changes: 25 additions & 5 deletions plugin/docker/skel.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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
}

Expand All @@ -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
Expand All @@ -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
}

Expand Down
36 changes: 29 additions & 7 deletions plugin/kubernetes/skel.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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{})
Expand Down Expand Up @@ -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{})
Expand Down
23 changes: 19 additions & 4 deletions plugin/workingdir/skel.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ type skelpipeToWrapper struct {
skelpipeWrapper
}

type skelpipeToPasswordWrapper struct {
skelpipeToWrapper
}

type skelpipeToPrivateKeyWrapper struct {
skelpipeToWrapper
}

func (s *skelpipeWrapper) From() []libplugin.SkelPipeFrom {

w := skelpipeFromWrapper{
Expand Down Expand Up @@ -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
}

Expand All @@ -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
Expand All @@ -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
}

Expand Down
33 changes: 27 additions & 6 deletions plugin/yaml/skel.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}

Expand All @@ -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,
Expand All @@ -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
}

Expand Down

0 comments on commit 085ba59

Please sign in to comment.