Add host key flag to SSH server

pull/58/head
Miguel Mota 4 years ago
parent 2fca6eefb0
commit 3fc19adefa

@ -1,4 +1,4 @@
FROM golang:latest FROM golang:1.14
RUN mkdir /app RUN mkdir /app
WORKDIR /app WORKDIR /app
@ -7,4 +7,5 @@ ADD . /app/
RUN go build -o main . RUN go build -o main .
RUN mv main /bin/cointop RUN mv main /bin/cointop
CMD cointop ENTRYPOINT cointop
CMD []

@ -195,3 +195,6 @@ docker-run:
docker-push: docker-push:
docker push cointop/cointop:latest docker push cointop/cointop:latest
docker-run-ssh:
docker run -p 2222:22 -v ~/.ssh/demo:/keys --entrypoint cointop -it cointop/cointop server -k /keys/id_rsa

@ -83,7 +83,7 @@ There are multiple ways you can install cointop depending on the platform you're
Make sure to have [go](https://golang.org/) (1.12+) installed, then do: Make sure to have [go](https://golang.org/) (1.12+) installed, then do:
```bash ```bash
go get -u github.com/miguelmota/cointop go get github.com/miguelmota/cointop
``` ```
Make sure `$GOPATH/bin` is added to the `$PATH` variable. Make sure `$GOPATH/bin` is added to the `$PATH` variable.
@ -599,6 +599,12 @@ SSH demo:
ssh cointop.sh ssh cointop.sh
``` ```
Using docker to run SSH server:
```bash
docker run -p 2222:22 -v ~/.ssh:/keys --entrypoint cointop -it cointop/cointop server -k /keys/id_rsa
```
## FAQ ## FAQ
Frequently asked questions: Frequently asked questions:

@ -171,6 +171,7 @@ For more information, visit: https://github.com/miguelmota/cointop`,
var address string = "0.0.0.0" var address string = "0.0.0.0"
var idleTimeout uint = 60 var idleTimeout uint = 60
var executableBinary string = "cointop" var executableBinary string = "cointop"
var hostKeyFile string = cssh.DefaultHostKeyFile
serverCmd := &cobra.Command{ serverCmd := &cobra.Command{
Use: "server", Use: "server",
@ -182,6 +183,7 @@ For more information, visit: https://github.com/miguelmota/cointop`,
Port: port, Port: port,
IdleTimeout: time.Duration(int(idleTimeout)) * time.Second, IdleTimeout: time.Duration(int(idleTimeout)) * time.Second,
ExecutableBinary: executableBinary, ExecutableBinary: executableBinary,
HostKeyFile: hostKeyFile,
}) })
fmt.Printf("Running SSH server on port %v\n", port) fmt.Printf("Running SSH server on port %v\n", port)
@ -192,7 +194,8 @@ For more information, visit: https://github.com/miguelmota/cointop`,
serverCmd.Flags().UintVarP(&port, "port", "p", port, "Port") serverCmd.Flags().UintVarP(&port, "port", "p", port, "Port")
serverCmd.Flags().StringVarP(&address, "address", "a", address, "Address") serverCmd.Flags().StringVarP(&address, "address", "a", address, "Address")
serverCmd.Flags().UintVarP(&idleTimeout, "idle-timeout", "t", idleTimeout, "Idle timeout in seconds") serverCmd.Flags().UintVarP(&idleTimeout, "idle-timeout", "t", idleTimeout, "Idle timeout in seconds")
serverCmd.Flags().StringVarP(&executableBinary, "binary", "b", executableBinary, "ExecutableBinary") serverCmd.Flags().StringVarP(&executableBinary, "binary", "b", executableBinary, "Executable binary path")
serverCmd.Flags().StringVarP(&hostKeyFile, "host-key-file", "k", hostKeyFile, "Host key file")
rootCmd.AddCommand(versionCmd, cleanCmd, resetCmd, priceCmd, testCmd, serverCmd) rootCmd.AddCommand(versionCmd, cleanCmd, resetCmd, priceCmd, testCmd, serverCmd)

@ -14,6 +14,7 @@ import (
"github.com/miguelmota/cointop/cointop/common/filecache" "github.com/miguelmota/cointop/cointop/common/filecache"
"github.com/miguelmota/cointop/cointop/common/gizak/termui" "github.com/miguelmota/cointop/cointop/common/gizak/termui"
"github.com/miguelmota/cointop/cointop/common/humanize" "github.com/miguelmota/cointop/cointop/common/humanize"
"github.com/miguelmota/cointop/cointop/common/pathutil"
"github.com/miguelmota/cointop/cointop/common/table" "github.com/miguelmota/cointop/cointop/common/table"
"github.com/miguelmota/gocui" "github.com/miguelmota/gocui"
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
@ -467,7 +468,7 @@ func Reset(config *ResetConfig) error {
} }
// default config path // default config path
configPath := fmt.Sprintf("%s%s", UserPreferredHomeDir(), "/.cointop") configPath := fmt.Sprintf("%s%s", pathutil.UserPreferredHomeDir(), "/.cointop")
if _, err := os.Stat(configPath); !os.IsNotExist(err) { if _, err := os.Stat(configPath); !os.IsNotExist(err) {
if config.Log { if config.Log {
fmt.Printf("removing %s\n", configPath) fmt.Printf("removing %s\n", configPath)

@ -0,0 +1,37 @@
package pathutil
import (
"os"
"path/filepath"
"runtime"
"strings"
)
// UserPreferredHomeDir returns the preferred home directory for the user
func UserPreferredHomeDir() string {
var home string
if runtime.GOOS == "windows" {
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
} else if runtime.GOOS == "linux" {
home = os.Getenv("XDG_CONFIG_HOME")
}
if home == "" {
home, _ = os.UserHomeDir()
}
return home
}
// NormalizePath normalizes and extends the path string
func NormalizePath(path string) string {
// expand tilde
if strings.HasPrefix(path, "~/") {
path = filepath.Join(UserPreferredHomeDir(), path[2:])
}
path = strings.Replace(path, "/", string(filepath.Separator), -1)
return path
}

@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/miguelmota/cointop/cointop/common/pathutil"
) )
var fileperm = os.FileMode(0644) var fileperm = os.FileMode(0644)
@ -77,7 +78,7 @@ func (ct *Cointop) CreateConfigIfNotExists() error {
} }
for _, previousConfigFilepath := range previousDefaultConfigPaths { for _, previousConfigFilepath := range previousDefaultConfigPaths {
normalizedPath := NormalizePath(previousConfigFilepath) normalizedPath := pathutil.NormalizePath(previousConfigFilepath)
if _, err := os.Stat(normalizedPath); err == nil { if _, err := os.Stat(normalizedPath); err == nil {
ct.configFilepath = normalizedPath ct.configFilepath = normalizedPath
return nil return nil
@ -100,7 +101,7 @@ func (ct *Cointop) CreateConfigIfNotExists() error {
// ConfigDirPath returns the config directory path // ConfigDirPath returns the config directory path
func (ct *Cointop) ConfigDirPath() string { func (ct *Cointop) ConfigDirPath() string {
ct.debuglog("configDirPath()") ct.debuglog("configDirPath()")
path := NormalizePath(ct.configFilepath) path := pathutil.NormalizePath(ct.configFilepath)
separator := string(filepath.Separator) separator := string(filepath.Separator)
parts := strings.Split(path, separator) parts := strings.Split(path, separator)
return strings.Join(parts[0:len(parts)-1], separator) return strings.Join(parts[0:len(parts)-1], separator)
@ -109,7 +110,7 @@ func (ct *Cointop) ConfigDirPath() string {
// ConfigFilePath return the config file path // ConfigFilePath return the config file path
func (ct *Cointop) ConfigFilePath() string { func (ct *Cointop) ConfigFilePath() string {
ct.debuglog("configFilePath()") ct.debuglog("configFilePath()")
return NormalizePath(ct.configFilepath) return pathutil.NormalizePath(ct.configFilepath)
} }
// ConfigPath return the config file path // ConfigPath return the config file path
@ -331,7 +332,7 @@ func (ct *Cointop) getColorschemeColors() (map[string]interface{}, error) {
return nil, err return nil, err
} }
} else { } else {
path := NormalizePath(fmt.Sprintf("~/.cointop/colors/%s.toml", ct.colorschemeName)) path := pathutil.NormalizePath(fmt.Sprintf("~/.cointop/colors/%s.toml", ct.colorschemeName))
if _, err := os.Stat(path); os.IsNotExist(err) { if _, err := os.Stat(path); os.IsNotExist(err) {
// NOTE: case for when cointop is set as the theme but the colorscheme file doesn't exist // NOTE: case for when cointop is set as the theme but the colorscheme file doesn't exist
if ct.colorschemeName == "cointop" { if ct.colorschemeName == "cointop" {

@ -10,22 +10,26 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path"
"syscall" "syscall"
"time" "time"
"unsafe" "unsafe"
"github.com/creack/pty" "github.com/creack/pty"
"github.com/gliderlabs/ssh" "github.com/gliderlabs/ssh"
"github.com/miguelmota/cointop/cointop/common/pathutil"
gossh "golang.org/x/crypto/ssh" gossh "golang.org/x/crypto/ssh"
) )
// DefaultHostKeyFile ...
var DefaultHostKeyFile = "~/.ssh/id_rsa"
// Config ... // Config ...
type Config struct { type Config struct {
Port uint Port uint
Address string Address string
IdleTimeout time.Duration IdleTimeout time.Duration
ExecutableBinary string ExecutableBinary string
HostKeyFile string
} }
// Server ... // Server ...
@ -35,25 +39,29 @@ type Server struct {
idleTimeout time.Duration idleTimeout time.Duration
executableBinary string executableBinary string
sshServer *ssh.Server sshServer *ssh.Server
hostKeyFile string
} }
// NewServer ... // NewServer ...
func NewServer(config *Config) *Server { func NewServer(config *Config) *Server {
hostKeyFile := DefaultHostKeyFile
if config.HostKeyFile != "" {
hostKeyFile = config.HostKeyFile
}
hostKeyFile = pathutil.NormalizePath(hostKeyFile)
return &Server{ return &Server{
port: config.Port, port: config.Port,
address: config.Address, address: config.Address,
idleTimeout: config.IdleTimeout, idleTimeout: config.IdleTimeout,
executableBinary: config.ExecutableBinary, executableBinary: config.ExecutableBinary,
hostKeyFile: hostKeyFile,
} }
} }
// ListenAndServe ... // ListenAndServe ...
func (s *Server) ListenAndServe() error { func (s *Server) ListenAndServe() error {
homeDir, err := os.UserHomeDir()
if err != nil {
return err
}
s.sshServer = &ssh.Server{ s.sshServer = &ssh.Server{
Addr: fmt.Sprintf("%s:%v", s.address, s.port), Addr: fmt.Sprintf("%s:%v", s.address, s.port),
IdleTimeout: s.idleTimeout, IdleTimeout: s.idleTimeout,
@ -116,12 +124,11 @@ func (s *Server) ListenAndServe() error {
}, },
} }
hostKeyFile := path.Join(homeDir, ".ssh", "id_rsa") if _, err := os.Stat(s.hostKeyFile); os.IsNotExist(err) {
if _, err := os.Stat(hostKeyFile); os.IsNotExist(err) {
return errors.New("SSH key is required to start server") return errors.New("SSH key is required to start server")
} }
err = s.sshServer.SetOption(ssh.HostKeyFile(hostKeyFile)) err := s.sshServer.SetOption(ssh.HostKeyFile(s.hostKeyFile))
if err != nil { if err != nil {
return err return err
} }

@ -3,9 +3,6 @@ package cointop
import ( import (
"bytes" "bytes"
"encoding/gob" "encoding/gob"
"os"
"path/filepath"
"runtime"
"strings" "strings"
"github.com/miguelmota/cointop/cointop/common/open" "github.com/miguelmota/cointop/cointop/common/open"
@ -29,35 +26,6 @@ func GetBytes(key interface{}) ([]byte, error) {
return buf.Bytes(), nil return buf.Bytes(), nil
} }
// UserPreferredHomeDir returns the preferred home directory for the user
func UserPreferredHomeDir() string {
var home string
if runtime.GOOS == "windows" {
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
} else if runtime.GOOS == "linux" {
home = os.Getenv("XDG_CONFIG_HOME")
}
if home == "" {
home, _ = os.UserHomeDir()
}
return home
}
// NormalizePath normalizes and extends the path string
func NormalizePath(path string) string {
// expand tilde
if strings.HasPrefix(path, "~/") {
path = filepath.Join(UserPreferredHomeDir(), path[2:])
}
path = strings.Replace(path, "/", string(filepath.Separator), -1)
return path
}
// Slugify returns a slugified string // Slugify returns a slugified string
func Slugify(s string) string { func Slugify(s string) string {
s = strings.TrimSpace(strings.ToLower(s)) s = strings.TrimSpace(strings.ToLower(s))

Loading…
Cancel
Save