diff --git a/go.mod b/go.mod index b425fa58..428e8beb 100644 --- a/go.mod +++ b/go.mod @@ -53,11 +53,13 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-cmp v0.5.6 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/imdario/mergo v0.3.5 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/lib/pq v1.1.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect diff --git a/go.sum b/go.sum index 75ef6616..fedc2546 100644 --- a/go.sum +++ b/go.sum @@ -205,6 +205,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= diff --git a/sshpiperd/upstream/kubernetes/example/deploy-stfp.yml b/sshpiperd/upstream/kubernetes/example/deploy-sftp.yaml similarity index 100% rename from sshpiperd/upstream/kubernetes/example/deploy-stfp.yml rename to sshpiperd/upstream/kubernetes/example/deploy-sftp.yaml diff --git a/sshpiperd/upstream/kubernetes/kubernetes.go b/sshpiperd/upstream/kubernetes/kubernetes.go index e7dbb0fc..5dc14bfd 100644 --- a/sshpiperd/upstream/kubernetes/kubernetes.go +++ b/sshpiperd/upstream/kubernetes/kubernetes.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net" + //"path/filepath" //"strings" @@ -11,6 +12,7 @@ import ( "golang.org/x/crypto/ssh" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" + //"k8s.io/client-go/util/homedir" //"k8s.io/client-go/tools/clientcmd" sshpipeclientset "github.com/pockost/sshpipe-k8s-lib/pkg/client/clientset/versioned" @@ -28,17 +30,16 @@ type pipeConfig struct { // } func (p *plugin) getClientSet() (*sshpipeclientset.Clientset, error) { - /* - var kubeconfig string - home := homedir.HomeDir() - kubeconfig = filepath.Join(home, ".kube", "config") - // use the current context in kubeconfig - config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) - if err != nil { - return nil, err - } - */ + // var kubeconfig string + // home := homedir.HomeDir() + // kubeconfig = filepath.Join(home, ".kube", "config") + + // // use the current context in kubeconfig + // config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) + // if err != nil { + // return nil, err + // } config, err := rest.InClusterConfig() if err != nil { return nil, err @@ -53,34 +54,29 @@ func (p *plugin) getClientSet() (*sshpipeclientset.Clientset, error) { return clientset, nil } -func (p *plugin) getConfig(clientset *sshpipeclientset.Clientset) ([]pipeConfig, error) { +func (p *plugin) getConfig(clientset *sshpipeclientset.Clientset, sshPipeName string) (pipeConfig, error) { listOptions := metav1.ListOptions{} pipes, err := clientset.PockostV1beta1().SshPipes("").List(context.TODO(), listOptions) if err != nil { - return nil, err + return pipeConfig{}, err } if err != nil { - return nil, err + return pipeConfig{}, err } - var config []pipeConfig for _, pipe := range pipes.Items { - targetHost := fmt.Sprintf("%s.%s", pipe.Spec.Target.Name, pipe.ObjectMeta.Namespace) - - for _, username := range pipe.Spec.Users { - config = append( - config, - pipeConfig{ - Username: username, - UpstreamHost: targetHost, - }, - ) + if pipe.Name == sshPipeName { + targetHost := fmt.Sprintf("%s.%s", pipe.Spec.Target.Name, pipe.ObjectMeta.Namespace) + return pipeConfig{ + Username: pipe.Spec.Users[0], + UpstreamHost: targetHost, + }, nil } } - return config, nil + return pipeConfig{}, fmt.Errorf("sshPipe [%s] not found", sshPipeName) } func (p *plugin) createAuthPipe(pipe pipeConfig, conn ssh.ConnMetadata, challengeContext ssh.AdditionalChallengeContext) (*ssh.AuthPipe, error) { @@ -107,30 +103,22 @@ func (p *plugin) findUpstream(conn ssh.ConnMetadata, challengeContext ssh.Additi } // Get config from k8s - config, err := p.getConfig(clientset) + pipeConfig, err := p.getConfig(clientset, user) if err != nil { return nil, nil, err } // Retreive corresponding configuration - for _, pipe := range config { - matched := pipe.Username == user - - if matched { - c, err := upstream.DialForSSH(pipe.UpstreamHost) - if err != nil { - return nil, nil, err - } - - a, err := p.createAuthPipe(pipe, conn, challengeContext) - if err != nil { - return nil, nil, err - } - - p.logger.Printf("Forwarding connection to [%v] for user [%v]", pipe.UpstreamHost, pipe.Username) - return c, a, nil - } + c, err := upstream.DialForSSH(pipeConfig.UpstreamHost) + if err != nil { + return nil, nil, err } - return nil, nil, fmt.Errorf("username not [%v] found", user) + a, err := p.createAuthPipe(pipeConfig, conn, challengeContext) + if err != nil { + return nil, nil, err + } + + p.logger.Printf("SSH Pipe [%s] forwarding connection to [%s] with user [%s]", user, pipeConfig.UpstreamHost, pipeConfig.Username) + return c, a, nil } diff --git a/sshpiperd/upstream/kubernetes/pipemgr.go b/sshpiperd/upstream/kubernetes/pipemgr.go index d5988364..185e948a 100644 --- a/sshpiperd/upstream/kubernetes/pipemgr.go +++ b/sshpiperd/upstream/kubernetes/pipemgr.go @@ -1,14 +1,33 @@ package kubernetes import ( + "context" + "fmt" + "github.com/tg123/sshpiper/sshpiperd/upstream" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // Return All pipes inside upstream func (p *plugin) ListPipe() ([]upstream.Pipe, error) { - - var pipes []upstream.Pipe - + pipes := []upstream.Pipe{} + clientset, err := p.getClientSet() + if err != nil { + return nil, err + } + pipeList, err := clientset.PockostV1beta1().SshPipes("").List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return nil, err + } + for _, p := range pipeList.Items { + targetHost := fmt.Sprintf("%s.%s", p.Spec.Target.Name, p.ObjectMeta.Namespace) + pipes = append(pipes, upstream.Pipe{ + Username: p.Name, + UpstreamUsername: p.Spec.Users[0], + Host: targetHost, + Port: 22, + }) + } return pipes, nil } @@ -19,5 +38,20 @@ func (p *plugin) CreatePipe(opt upstream.CreatePipeOption) error { // Remove a pipe from upstream func (p *plugin) RemovePipe(name string) error { - return nil + clientset, err := p.getClientSet() + if err != nil { + return err + } + pipeList, err := clientset.PockostV1beta1().SshPipes("").List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return err + } + + for _, p := range pipeList.Items { + if p.Name == name { + return clientset.PockostV1beta1().SshPipes(p.ObjectMeta.Namespace).Delete(context.TODO(), name, metav1.DeleteOptions{}) + } + } + + return fmt.Errorf("SSH Pipe [%s] not found", name) } diff --git a/sshpiperd/upstream/yaml/yaml.go b/sshpiperd/upstream/yaml/yaml.go index 00b7a4fc..e83159e6 100644 --- a/sshpiperd/upstream/yaml/yaml.go +++ b/sshpiperd/upstream/yaml/yaml.go @@ -375,5 +375,5 @@ func (p *plugin) findUpstream(conn ssh.ConnMetadata, challengeContext ssh.Additi } } - return nil, nil, fmt.Errorf("username not [%v] found", user) + return nil, nil, fmt.Errorf("username [%v] not found", user) }