diff --git a/cmd/sshpiperd/daemon.go b/cmd/sshpiperd/daemon.go index b43d318b..81823a64 100644 --- a/cmd/sshpiperd/daemon.go +++ b/cmd/sshpiperd/daemon.go @@ -1,6 +1,7 @@ package main import ( + "encoding/base64" "fmt" "net" "os" @@ -27,29 +28,46 @@ func newDaemon(ctx *cli.Context) (*daemon, error) { config := &ssh.PiperConfig{} config.SetDefaults() - privateKeys, err := filepath.Glob(ctx.String("server-key")) - if err != nil { - return nil, err - } + keybase64 := ctx.String("server-key-data") + if keybase64 != "" { + log.Infof("parsing host key in base64 params") - if len(privateKeys) == 0 { - return nil, fmt.Errorf("no server key found") - } - - log.Infof("found host keys %v", privateKeys) - for _, privateKey := range privateKeys { - log.Infof("loading host key %v", privateKey) - privateBytes, err := os.ReadFile(privateKey) + privateBytes, err := base64.StdEncoding.DecodeString(keybase64) if err != nil { return nil, err } - private, err := ssh.ParsePrivateKey(privateBytes) + private, err := ssh.ParsePrivateKey([]byte(privateBytes)) if err != nil { return nil, err } config.AddHostKey(private) + } else { + privateKeyFiles, err := filepath.Glob(ctx.String("server-key")) + if err != nil { + return nil, err + } + + if len(privateKeyFiles) == 0 { + return nil, fmt.Errorf("no server key found") + } + + log.Infof("found host keys %v", privateKeyFiles) + for _, privateKey := range privateKeyFiles { + log.Infof("loading host key %v", privateKey) + privateBytes, err := os.ReadFile(privateKey) + if err != nil { + return nil, err + } + + private, err := ssh.ParsePrivateKey(privateBytes) + if err != nil { + return nil, err + } + + config.AddHostKey(private) + } } lis, err := net.Listen("tcp", net.JoinHostPort(ctx.String("address"), ctx.String("port"))) diff --git a/cmd/sshpiperd/main.go b/cmd/sshpiperd/main.go index ca2d0be1..058be7fc 100644 --- a/cmd/sshpiperd/main.go +++ b/cmd/sshpiperd/main.go @@ -97,6 +97,11 @@ func main() { Value: "/etc/ssh/ssh_host_ed25519_key", EnvVars: []string{"SSHPIPERD_SERVER_KEY"}, }, + &cli.StringFlag{ + Name: "server-key-data", + Usage: "server key in base64 format, server-key will be ignored if set", + EnvVars: []string{"SSHPIPERD_SERVER_KEY_DATA"}, + }, &cli.DurationFlag{ Name: "login-grace-time", Value: 30 * time.Second, diff --git a/e2e/fixed_test.go b/e2e/fixed_test.go index 87479277..a0805393 100644 --- a/e2e/fixed_test.go +++ b/e2e/fixed_test.go @@ -1,7 +1,9 @@ package e2e_test import ( + "encoding/base64" "fmt" + "strings" "testing" "time" @@ -58,3 +60,35 @@ func TestFixed(t *testing.T) { checkSharedFileContent(t, targetfie, randtext) } + +func TestHostkeyParam(t *testing.T) { + _, piperport := nextAvailablePiperAddress() + keyparam := base64.StdEncoding.EncodeToString([]byte(testprivatekey)) + + piper, _, _, err := runCmd("/sshpiperd/sshpiperd", + "-p", + piperport, + "--server-key-data", + keyparam, + "/sshpiperd/plugins/fixed", + "--target", + "host-password:2222", + ) + + if err != nil { + t.Errorf("failed to run sshpiperd: %v", err) + } + + defer killCmd(piper) + + b, err := runAndGetStdout( + "ssh-keyscan", + "-p", + piperport, + "127.0.0.1", + ) + + if !strings.Contains(string(b), testpublickey) { + t.Errorf("failed to get correct hostkey, %v", err) + } +} diff --git a/e2e/main_test.go b/e2e/main_test.go index a830a142..b9d52da3 100644 --- a/e2e/main_test.go +++ b/e2e/main_test.go @@ -29,6 +29,8 @@ AAAEDcQgdh2z2r/6blq0ziJ1l6s6IAX8C+9QHfAH931cHNO9RGTH325rDUp12tplwukHmR -----END OPENSSH PRIVATE KEY----- ` +const testpublickey = `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINRGTH325rDUp12tplwukHmR8ytbC9TPZ886gCstynP1` + const waitTimeout = time.Second * 10 func waitForEndpointReady(addr string) {