From c285f0990fdc9297093c26b77e26ae54d9f3af1b Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Fri, 2 Oct 2020 17:09:14 -0600 Subject: [PATCH] Run go fmt --- api.go | 114 +++++++++++++++++++------------------ auth.go | 16 +++--- boringproxy.go | 139 +++++++++++++++++++++++----------------------- client.go | 55 +++++++++--------- main.go | 38 ++++++------- ssh_server.go | 98 ++++++++++++++++---------------- tunnel_manager.go | 116 +++++++++++++++++++------------------- 7 files changed, 284 insertions(+), 292 deletions(-) diff --git a/api.go b/api.go index 0d59a0a..0c9dca3 100644 --- a/api.go +++ b/api.go @@ -1,59 +1,57 @@ package main import ( - //"fmt" - //"strings" - "net/http" - "io" - "encoding/json" + //"fmt" + //"strings" + "encoding/json" + "io" + "net/http" ) type Api struct { - config *BoringProxyConfig - auth *Auth - tunMan *TunnelManager - mux *http.ServeMux + config *BoringProxyConfig + auth *Auth + tunMan *TunnelManager + mux *http.ServeMux } type CreateTunnelResponse struct { - ServerAddress string `json:"server_address"` - ServerPort int `json:"server_port"` - ServerPublicKey string `json:"server_public_key"` - TunnelPort int `json:"tunnel_port"` - TunnelPrivateKey string `json:"tunnel_private_key"` + ServerAddress string `json:"server_address"` + ServerPort int `json:"server_port"` + ServerPublicKey string `json:"server_public_key"` + TunnelPort int `json:"tunnel_port"` + TunnelPrivateKey string `json:"tunnel_private_key"` } - func NewApi(config *BoringProxyConfig, auth *Auth, tunMan *TunnelManager) *Api { - api := &Api{config, auth, tunMan, nil} + api := &Api{config, auth, tunMan, nil} - mux := http.NewServeMux() + mux := http.NewServeMux() - mux.Handle("/tunnels", http.StripPrefix("/tunnels", http.HandlerFunc(api.handleTunnels))) + mux.Handle("/tunnels", http.StripPrefix("/tunnels", http.HandlerFunc(api.handleTunnels))) - api.mux = mux + api.mux = mux - return api + return api } - func (a *Api) ServeHTTP(w http.ResponseWriter, r *http.Request) { - a.mux.ServeHTTP(w, r) + a.mux.ServeHTTP(w, r) } func (a *Api) handleTunnels(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case "POST": - a.validateSession(http.HandlerFunc(a.handleCreateTunnel)).ServeHTTP(w, r) - default: + switch r.Method { + case "POST": + a.validateSession(http.HandlerFunc(a.handleCreateTunnel)).ServeHTTP(w, r) + default: w.WriteHeader(405) w.Write([]byte("Invalid method for /tunnels")) - } + } } func (a *Api) handleCreateTunnel(w http.ResponseWriter, r *http.Request) { - query := r.URL.Query() + query := r.URL.Query() if len(query["domain"]) != 1 { w.WriteHeader(400) @@ -62,47 +60,47 @@ func (a *Api) handleCreateTunnel(w http.ResponseWriter, r *http.Request) { } domain := query["domain"][0] - port, privKey, err := a.tunMan.CreateTunnel(domain) - if err != nil { + port, privKey, err := a.tunMan.CreateTunnel(domain) + if err != nil { w.WriteHeader(400) - io.WriteString(w, err.Error()) + io.WriteString(w, err.Error()) return - } + } - response := &CreateTunnelResponse{ - ServerAddress: a.config.AdminDomain, - ServerPort: 22, - ServerPublicKey: "", - TunnelPort: port, - TunnelPrivateKey: privKey, - } + response := &CreateTunnelResponse{ + ServerAddress: a.config.AdminDomain, + ServerPort: 22, + ServerPublicKey: "", + TunnelPort: port, + TunnelPrivateKey: privKey, + } - responseJson, err := json.MarshalIndent(response, "", " ") - if err != nil { + responseJson, err := json.MarshalIndent(response, "", " ") + if err != nil { w.WriteHeader(500) - io.WriteString(w, "Error encoding response") + io.WriteString(w, "Error encoding response") return - } + } - w.Write(responseJson) + w.Write(responseJson) } func (a *Api) validateSession(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - token, err := extractToken("access_token", r) - if err != nil { - w.WriteHeader(401) - w.Write([]byte("No token provided")) - return - } + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token, err := extractToken("access_token", r) + if err != nil { + w.WriteHeader(401) + w.Write([]byte("No token provided")) + return + } - if !a.auth.Authorized(token) { - w.WriteHeader(403) - w.Write([]byte("Not authorized")) - return - } + if !a.auth.Authorized(token) { + w.WriteHeader(403) + w.Write([]byte("Not authorized")) + return + } - h.ServeHTTP(w, r) - }) + h.ServeHTTP(w, r) + }) } diff --git a/auth.go b/auth.go index 31b7a54..db45ec9 100644 --- a/auth.go +++ b/auth.go @@ -20,7 +20,7 @@ type Auth struct { } type LoginRequest struct { - Email string + Email string } type Session struct { @@ -109,16 +109,16 @@ func (a *Auth) Verify(key string) (string, error) { delete(a.pendingRequests, key) - token, err := genRandomKey() - if err != nil { - return "", errors.New("Error generating key") - } + token, err := genRandomKey() + if err != nil { + return "", errors.New("Error generating key") + } - a.sessions[token] = &Session{Id: request.Email} + a.sessions[token] = &Session{Id: request.Email} - saveJson(a.sessions, "sessions.json") + saveJson(a.sessions, "sessions.json") - return token, nil + return token, nil } const chars string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/boringproxy.go b/boringproxy.go index 14d5cb6..cae3040 100644 --- a/boringproxy.go +++ b/boringproxy.go @@ -4,16 +4,16 @@ import ( "crypto/tls" "encoding/json" "fmt" + "github.com/GeertJohan/go.rice" + "github.com/caddyserver/certmagic" + "html/template" "io" "io/ioutil" "log" "net" "net/http" - "html/template" "strconv" "sync" - "github.com/caddyserver/certmagic" - "github.com/GeertJohan/go.rice" ) type BoringProxyConfig struct { @@ -70,10 +70,10 @@ func NewBoringProxy() *BoringProxy { p := &BoringProxy{config, auth, tunMan, adminListener, certConfig} http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - p.handleAdminRequest(w, r) - }) + p.handleAdminRequest(w, r) + }) - api := NewApi(config, auth, tunMan) + api := NewApi(config, auth, tunMan) http.Handle("/api/", http.StripPrefix("/api", api)) go http.Serve(adminListener, nil) @@ -106,26 +106,26 @@ func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) case "/login": p.handleLogin(w, r) case "/": - box, err := rice.FindBox("webui") - if err != nil { + box, err := rice.FindBox("webui") + if err != nil { w.WriteHeader(500) - io.WriteString(w, "Error opening webui") + io.WriteString(w, "Error opening webui") return - } + } token, err := extractToken("access_token", r) if err != nil { - loginTemplate, err := box.String("login.tmpl") - if err != nil { - log.Println(err) - w.WriteHeader(500) - io.WriteString(w, "Error reading login.tmpl") - return - } + loginTemplate, err := box.String("login.tmpl") + if err != nil { + log.Println(err) + w.WriteHeader(500) + io.WriteString(w, "Error reading login.tmpl") + return + } w.WriteHeader(401) - io.WriteString(w, loginTemplate) + io.WriteString(w, loginTemplate) return } @@ -135,26 +135,24 @@ func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) return } - - indexTemplate, err := box.String("index.tmpl") - if err != nil { + indexTemplate, err := box.String("index.tmpl") + if err != nil { w.WriteHeader(500) - io.WriteString(w, "Error reading index.tmpl") + io.WriteString(w, "Error reading index.tmpl") return - } + } - tmpl, err := template.New("test").Parse(indexTemplate) - if err != nil { + tmpl, err := template.New("test").Parse(indexTemplate) + if err != nil { w.WriteHeader(500) - log.Println(err) - io.WriteString(w, "Error compiling index.tmpl") + log.Println(err) + io.WriteString(w, "Error compiling index.tmpl") return - } + } + tmpl.Execute(w, p.tunMan.tunnels) - tmpl.Execute(w, p.tunMan.tunnels) - - //io.WriteString(w, indexTemplate) + //io.WriteString(w, indexTemplate) case "/tunnels": @@ -174,7 +172,7 @@ func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) p.handleTunnels(w, r) case "/delete-tunnel": - token, err := extractToken("access_token", r) + token, err := extractToken("access_token", r) if err != nil { w.WriteHeader(401) w.Write([]byte("No token provided")) @@ -187,7 +185,7 @@ func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) return } - r.ParseForm() + r.ParseForm() if len(r.Form["host"]) != 1 { w.WriteHeader(400) @@ -198,7 +196,7 @@ func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) p.tunMan.DeleteTunnel(host) - http.Redirect(w, r, "/", 307) + http.Redirect(w, r, "/", 307) default: w.WriteHeader(400) w.Write([]byte("Invalid endpoint")) @@ -234,49 +232,48 @@ func (p *BoringProxy) handleTunnels(w http.ResponseWriter, r *http.Request) { func (p *BoringProxy) handleLogin(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case "GET": - query := r.URL.Query() - key, exists := query["key"] + switch r.Method { + case "GET": + query := r.URL.Query() + key, exists := query["key"] - if !exists { - w.WriteHeader(400) - fmt.Fprintf(w, "Must provide key for verification") - return - } + if !exists { + w.WriteHeader(400) + fmt.Fprintf(w, "Must provide key for verification") + return + } - token, err := p.auth.Verify(key[0]) + token, err := p.auth.Verify(key[0]) - if err != nil { - w.WriteHeader(400) - fmt.Fprintf(w, "Invalid key") - return - } + if err != nil { + w.WriteHeader(400) + fmt.Fprintf(w, "Invalid key") + return + } - cookie := &http.Cookie{Name: "access_token", Value: token, Secure: true, HttpOnly: true} - http.SetCookie(w, cookie) + cookie := &http.Cookie{Name: "access_token", Value: token, Secure: true, HttpOnly: true} + http.SetCookie(w, cookie) - http.Redirect(w, r, "/", 307) + http.Redirect(w, r, "/", 307) + case "POST": - case "POST": + r.ParseForm() - r.ParseForm() + toEmail, ok := r.Form["email"] - toEmail, ok := r.Form["email"] + if !ok { + w.WriteHeader(400) + w.Write([]byte("Email required for login")) + return + } - if !ok { - w.WriteHeader(400) - w.Write([]byte("Email required for login")) - return - } + // run in goroutine because it can take some time to send the + // email + go p.auth.Login(toEmail[0], p.config) - // run in goroutine because it can take some time to send the - // email - go p.auth.Login(toEmail[0], p.config) - - io.WriteString(w, "Check your email to finish logging in") - default: + io.WriteString(w, "Check your email to finish logging in") + default: w.WriteHeader(405) w.Write([]byte("Invalid method for login")) } @@ -284,7 +281,7 @@ func (p *BoringProxy) handleLogin(w http.ResponseWriter, r *http.Request) { func (p *BoringProxy) handleCreateTunnel(w http.ResponseWriter, r *http.Request) { - r.ParseForm() + r.ParseForm() if len(r.Form["host"]) != 1 { w.WriteHeader(400) @@ -307,13 +304,13 @@ func (p *BoringProxy) handleCreateTunnel(w http.ResponseWriter, r *http.Request) } err = p.tunMan.SetTunnel(host, port) - if err != nil { + if err != nil { w.WriteHeader(400) - io.WriteString(w, "Failed to get cert. Ensure your domain is valid") + io.WriteString(w, "Failed to get cert. Ensure your domain is valid") return - } + } - http.Redirect(w, r, "/", 303) + http.Redirect(w, r, "/", 303) } func (p *BoringProxy) handleConnection(clientConn net.Conn) { diff --git a/client.go b/client.go index 58f8258..a485ec8 100644 --- a/client.go +++ b/client.go @@ -1,64 +1,63 @@ package main import ( - "log" - "fmt" - "golang.org/x/crypto/ssh" - "io/ioutil" + "fmt" + "golang.org/x/crypto/ssh" + "io/ioutil" + "log" ) - type BoringProxyClient struct { } func NewBoringProxyClient() *BoringProxyClient { - return &BoringProxyClient{} + return &BoringProxyClient{} } func (c *BoringProxyClient) Run() { - log.Println("Run client") + log.Println("Run client") - //var hostKey ssh.PublicKey + //var hostKey ssh.PublicKey - config := &ssh.ClientConfig{ + config := &ssh.ClientConfig{ User: "user", Auth: []ssh.AuthMethod{ - ssh.Password("yolo"), + ssh.Password("yolo"), }, //HostKeyCallback: ssh.FixedHostKey(hostKey), HostKeyCallback: ssh.InsecureIgnoreHostKey(), } - client, err := ssh.Dial("tcp", "boringproxy.io:2022", config) + client, err := ssh.Dial("tcp", "boringproxy.io:2022", config) if err != nil { log.Fatal("Failed to dial: ", err) } - tunnelRequests := client.HandleChannelOpen("boringproxy-tunnel") + tunnelRequests := client.HandleChannelOpen("boringproxy-tunnel") - for req := range tunnelRequests { - go handleTunnelRequest(req) - } + for req := range tunnelRequests { + go handleTunnelRequest(req) + } } func handleTunnelRequest(req ssh.NewChannel) error { - tun, reqs, err := req.Accept() - if err != nil { - return err - } + tun, reqs, err := req.Accept() + if err != nil { + return err + } - go ssh.DiscardRequests(reqs) + go ssh.DiscardRequests(reqs) - port := req.ExtraData() + port := req.ExtraData() - fmt.Println(port) + fmt.Println(port) - data, err := ioutil.ReadAll(tun) - if err != nil { - return err - } + data, err := ioutil.ReadAll(tun) + if err != nil { + return err + } - fmt.Println(string(data)) - return nil + fmt.Println(string(data)) + return nil } diff --git a/main.go b/main.go index e277d04..766ac94 100644 --- a/main.go +++ b/main.go @@ -1,31 +1,31 @@ package main import ( - "fmt" + "fmt" "log" - "os" + "os" ) func main() { - if len(os.Args) < 2 { - fmt.Println("Invalid arguments") - os.Exit(1) - } + if len(os.Args) < 2 { + fmt.Println("Invalid arguments") + os.Exit(1) + } - command := os.Args[1] + command := os.Args[1] - switch command { - case "server": - log.Println("Starting up") - proxy := NewBoringProxy() - proxy.Run() + switch command { + case "server": + log.Println("Starting up") + proxy := NewBoringProxy() + proxy.Run() - case "client": - client := NewBoringProxyClient() - client.Run() - default: - fmt.Println("Invalid command " + command) - os.Exit(1) - } + case "client": + client := NewBoringProxyClient() + client.Run() + default: + fmt.Println("Invalid command " + command) + os.Exit(1) + } } diff --git a/ssh_server.go b/ssh_server.go index ea2c1b9..3a4e3c4 100644 --- a/ssh_server.go +++ b/ssh_server.go @@ -1,24 +1,22 @@ package main import ( - "fmt" - "log" - "net" - "io/ioutil" - "golang.org/x/crypto/ssh" + "fmt" + "golang.org/x/crypto/ssh" + "io/ioutil" + "log" + "net" ) - type SshServer struct { - config *ssh.ServerConfig - listener net.Listener + config *ssh.ServerConfig + listener net.Listener } - func NewSshServer() *SshServer { - config := &ssh.ServerConfig{} + config := &ssh.ServerConfig{} - privateBytes, err := ioutil.ReadFile("id_rsa_boringproxy") + privateBytes, err := ioutil.ReadFile("id_rsa_boringproxy") if err != nil { log.Fatal("Failed to load private key: ", err) } @@ -30,66 +28,66 @@ func NewSshServer() *SshServer { config.AddHostKey(private) - listener, err := net.Listen("tcp", "0.0.0.0:2022") + listener, err := net.Listen("tcp", "0.0.0.0:2022") if err != nil { log.Fatal("failed to listen for connection: ", err) } - server := &SshServer{config, listener} + server := &SshServer{config, listener} - go server.acceptAll() + go server.acceptAll() - return server + return server } func (s *SshServer) acceptAll() { - for { - nConn, err := s.listener.Accept() - if err != nil { - log.Print("failed to accept incoming connection: ", err) - continue - } + for { + nConn, err := s.listener.Accept() + if err != nil { + log.Print("failed to accept incoming connection: ", err) + continue + } - go s.handleServerConn(nConn) - } + go s.handleServerConn(nConn) + } } func (s *SshServer) handleServerConn(nConn net.Conn) { - var password string + var password string - s.config.PasswordCallback = func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { - password = string(pass) - if c.User() == "user" && string(pass) == "yolo" { - return nil, nil - } - return nil, fmt.Errorf("password rejected for %q", c.User()) - } - - conn, chans, reqs, err := ssh.NewServerConn(nConn, s.config) - if err != nil { - log.Print("failed to handshake: ", err) - return + s.config.PasswordCallback = func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { + password = string(pass) + if c.User() == "user" && string(pass) == "yolo" { + return nil, nil + } + return nil, fmt.Errorf("password rejected for %q", c.User()) } - fmt.Println(password) + conn, chans, reqs, err := ssh.NewServerConn(nConn, s.config) + if err != nil { + log.Print("failed to handshake: ", err) + return + } + + fmt.Println(password) go ssh.DiscardRequests(reqs) - go func() { - for newChannel := range chans { - newChannel.Reject(ssh.ResourceShortage, "too bad") - } - }() + go func() { + for newChannel := range chans { + newChannel.Reject(ssh.ResourceShortage, "too bad") + } + }() - ch, cReqs, err := conn.OpenChannel("boringproxy-tunnel", []byte{25, 25}) - if err != nil { - log.Print(err) - return - } + ch, cReqs, err := conn.OpenChannel("boringproxy-tunnel", []byte{25, 25}) + if err != nil { + log.Print(err) + return + } - go ssh.DiscardRequests(cReqs) + go ssh.DiscardRequests(cReqs) - ch.Write([]byte("Hi there")) - ch.Close() + ch.Write([]byte("Hi there")) + ch.Close() } diff --git a/tunnel_manager.go b/tunnel_manager.go index f4ac771..a9c543b 100644 --- a/tunnel_manager.go +++ b/tunnel_manager.go @@ -1,19 +1,19 @@ package main import ( - "fmt" - "strings" + "crypto/rand" + "crypto/rsa" + "crypto/x509" "encoding/json" + "encoding/pem" "errors" + "fmt" "github.com/caddyserver/certmagic" + "golang.org/x/crypto/ssh" "io/ioutil" "log" + "strings" "sync" - "crypto/rsa" - "crypto/rand" - "encoding/pem" - "crypto/x509" - "golang.org/x/crypto/ssh" ) type Tunnel struct { @@ -27,7 +27,7 @@ func NewTunnels() Tunnels { } type TunnelManager struct { - nextPort int + nextPort int tunnels Tunnels mutex *sync.Mutex certConfig *certmagic.Config @@ -57,7 +57,7 @@ func NewTunnelManager(certConfig *certmagic.Config) *TunnelManager { } } - nextPort := 9001 + nextPort := 9001 mutex := &sync.Mutex{} return &TunnelManager{nextPort, tunnels, mutex, certConfig} @@ -67,7 +67,7 @@ func (m *TunnelManager) SetTunnel(host string, port int) error { err := m.certConfig.ManageSync([]string{host}) if err != nil { log.Println(err) - return errors.New("Failed to get cert") + return errors.New("Failed to get cert") } tunnel := &Tunnel{port} @@ -76,36 +76,36 @@ func (m *TunnelManager) SetTunnel(host string, port int) error { saveJson(m.tunnels, "tunnels.json") m.mutex.Unlock() - return nil + return nil } func (m *TunnelManager) CreateTunnel(domain string) (int, string, error) { err := m.certConfig.ManageSync([]string{domain}) if err != nil { log.Println(err) - return 0, "", errors.New("Failed to get cert") + return 0, "", errors.New("Failed to get cert") } m.mutex.Lock() defer m.mutex.Unlock() - _, exists := m.tunnels[domain] - if exists { - return 0, "", errors.New("Tunnel exists for domain " + domain) - } + _, exists := m.tunnels[domain] + if exists { + return 0, "", errors.New("Tunnel exists for domain " + domain) + } - port := m.nextPort - m.nextPort += 1 + port := m.nextPort + m.nextPort += 1 tunnel := &Tunnel{port} m.tunnels[domain] = tunnel saveJson(m.tunnels, "tunnels.json") - privKey, err := m.addToAuthorizedKeys(port) - if err != nil { - return 0, "", err - } + privKey, err := m.addToAuthorizedKeys(port) + if err != nil { + return 0, "", err + } - return port, privKey, nil + return port, privKey, nil } func (m *TunnelManager) DeleteTunnel(host string) { @@ -129,29 +129,29 @@ func (m *TunnelManager) GetPort(serverName string) (int, error) { func (m *TunnelManager) addToAuthorizedKeys(port int) (string, error) { - akBytes, err := ioutil.ReadFile("/home/anders/.ssh/authorized_keys") - if err != nil { - return "", err - } + akBytes, err := ioutil.ReadFile("/home/anders/.ssh/authorized_keys") + if err != nil { + return "", err + } - akStr := string(akBytes) + akStr := string(akBytes) - pubKey, privKey, err := MakeSSHKeyPair() - if err != nil { - return "", err - } + pubKey, privKey, err := MakeSSHKeyPair() + if err != nil { + return "", err + } - options := fmt.Sprintf(`command="echo This key permits tunnels only",permitopen="fakehost:1",permitlisten="localhost:%d"`, port) + options := fmt.Sprintf(`command="echo This key permits tunnels only",permitopen="fakehost:1",permitlisten="localhost:%d"`, port) - pubKeyNoNewline := pubKey[:len(pubKey) - 1] - newAk := fmt.Sprintf("%s%s %s %s%d\n", akStr, options, pubKeyNoNewline, "boringproxy-", port) + pubKeyNoNewline := pubKey[:len(pubKey)-1] + newAk := fmt.Sprintf("%s%s %s %s%d\n", akStr, options, pubKeyNoNewline, "boringproxy-", port) - err = ioutil.WriteFile("/home/anders/.ssh/authorized_keys", []byte(newAk), 0600) - if err != nil { - return "", err - } + err = ioutil.WriteFile("/home/anders/.ssh/authorized_keys", []byte(newAk), 0600) + if err != nil { + return "", err + } - return privKey, nil + return privKey, nil } // Adapted from https://stackoverflow.com/a/34347463/943814 @@ -159,27 +159,27 @@ func (m *TunnelManager) addToAuthorizedKeys(port int) (string, error) { // Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file. // Private Key generated is PEM encoded func MakeSSHKeyPair() (string, string, error) { - privateKey, err := rsa.GenerateKey(rand.Reader, 1024) - if err != nil { - return "", "", err - } + privateKey, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + return "", "", err + } - // generate and write private key as PEM - var privKeyBuf strings.Builder + // generate and write private key as PEM + var privKeyBuf strings.Builder - privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} - if err := pem.Encode(&privKeyBuf, privateKeyPEM); err != nil { - return "", "", err - } + privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} + if err := pem.Encode(&privKeyBuf, privateKeyPEM); err != nil { + return "", "", err + } - // generate and write public key - pub, err := ssh.NewPublicKey(&privateKey.PublicKey) - if err != nil { - return "", "", err - } + // generate and write public key + pub, err := ssh.NewPublicKey(&privateKey.PublicKey) + if err != nil { + return "", "", err + } - var pubKeyBuf strings.Builder - pubKeyBuf.Write(ssh.MarshalAuthorizedKey(pub)) + var pubKeyBuf strings.Builder + pubKeyBuf.Write(ssh.MarshalAuthorizedKey(pub)) - return pubKeyBuf.String(), privKeyBuf.String(), nil + return pubKeyBuf.String(), privKeyBuf.String(), nil }