Skip to content

Commit

Permalink
Support for default TLS with auto-gen certs
Browse files Browse the repository at this point in the history
This patch enables TLS as the default communication method for accessing
a remote libStorage API endpoint. Additional features include:

* Auto-creation of x509 public and private key files upon installation
* Interactive CLI to allow users to trust an unknown, remote host. This
  feature behaves just like SSH's known hosts functionality.
  • Loading branch information
vladimirvivien authored and akutz committed May 2, 2017
1 parent 8e04870 commit aaa0d27
Show file tree
Hide file tree
Showing 11 changed files with 478 additions and 12 deletions.
96 changes: 96 additions & 0 deletions cli/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"fmt"
"net/url"
"os"
"time"

Expand Down Expand Up @@ -149,6 +150,9 @@ type CLI struct {
encryptionKey string
idempotent bool
scriptPath string
serverCertFile string
serverKeyFile string
serverCAFile string
}

const (
Expand Down Expand Up @@ -364,6 +368,7 @@ func (c *CLI) preRun(cmd *cobra.Command, args []string) {
c.ctx.WithField("cmd", cmd.Name()).Debug(
"creating libStorage client")
c.r, err = util.NewClient(c.ctx, c.config)
err = c.handleKnownHostsError(err)
}

if err != nil {
Expand Down Expand Up @@ -452,6 +457,82 @@ func (c *CLI) logLevel() string {
return c.config.GetString("rexray.logLevel")
}

// handles the known_hosts error,
// if error is ErrKnownHosts, stop execution to prevent unstable state
func (c *CLI) handleKnownHostsError(err error) error {
if err == nil {
return nil
}
urlErr, ok := err.(*url.Error)
if !ok {
return err
}

var khErr *apitypes.ErrKnownHost
var khConflictErr *apitypes.ErrKnownHostConflict
switch err := urlErr.Err.(type) {
case *apitypes.ErrKnownHost:
khErr = err
case *apitypes.ErrKnownHostConflict:
khConflictErr = err
}

if khErr == nil && khConflictErr == nil {
return err
}

pathConfig := context.MustPathConfig(c.ctx)
knownHostPath := pathConfig.UserDefaultTLSKnownHosts

if khConflictErr != nil {
// it's an ErrKnownHostConflict
fmt.Fprintf(
os.Stderr,
hostKeyCheckFailedFormat,
khConflictErr.PeerFingerprint,
knownHostPath,
khConflictErr.KnownHostName)
os.Exit(1)
}

// it's an ErrKnownHost

if !util.AssertTrustedHost(
c.ctx,
khErr.HostName,
khErr.PeerAlg,
khErr.PeerFingerprint) {
fmt.Fprintln(
os.Stderr,
"Aborting request, remote host not trusted.")
os.Exit(1)
}

if err := util.AddKnownHost(
c.ctx,
knownHostPath,
khErr.HostName,
khErr.PeerAlg,
khErr.PeerFingerprint,
); err == nil {
fmt.Fprintf(
os.Stderr,
"Permanently added host %s to known_hosts file %s\n",
khErr.HostName, knownHostPath)
fmt.Fprintln(
os.Stderr,
"It is safe to retry your last rexray command.")
} else {
fmt.Fprintf(
os.Stderr,
"Failed to add entry to known_hosts file: %v",
err)
}

os.Exit(1) // do not continue
return nil
}

func store() apitypes.Store {
return apiutils.NewStore()
}
Expand All @@ -462,3 +543,18 @@ func checkOpPerms(op string) error {
//}
return nil
}

const hostKeyCheckFailedFormat = `@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
%[1]x.
Please contact your system administrator.
Add correct host key in %[2]s to get rid of this message.
Offending key in %[2]s
RSA host key for %[3]s has changed and you have requested strict checking.
Host key verification failed.
`
1 change: 1 addition & 0 deletions cli/cli/cmds_00_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func (c *CLI) initOtherCmds() {
Short: "Install REX-Ray",
Run: func(cmd *cobra.Command, args []string) {
if installFunc != nil {
installSelfCert(c.ctx, c.config)
installFunc()
}
},
Expand Down
1 change: 0 additions & 1 deletion cli/cli/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (

log "github.com/Sirupsen/logrus"
"github.com/akutz/gotil"

"github.com/codedellemc/rexray/util"
)

Expand Down
10 changes: 10 additions & 0 deletions cli/cli/installer_client_agent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// +build rexray_build_type_client rexray_build_type_agent

package cli

import (
gofig "github.com/akutz/gofig/types"
apitypes "github.com/codedellemc/libstorage/api/types"
)

func installSelfCert(ctx apitypes.Context, config gofig.Config) {}
26 changes: 26 additions & 0 deletions cli/cli/installer_std_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// +build !rexray_build_type_client
// +build !rexray_build_type_agent

package cli

import (
"fmt"

log "github.com/Sirupsen/logrus"
gofig "github.com/akutz/gofig/types"
apitypes "github.com/codedellemc/libstorage/api/types"
"github.com/codedellemc/rexray/util"
)

func installSelfCert(ctx apitypes.Context, config gofig.Config) {
certPath := config.GetString(apitypes.ConfigTLSCertFile)
keyPath := config.GetString(apitypes.ConfigTLSKeyFile)
host := "127.0.0.1"

fmt.Println("Generating server self-signed certificate...")
if err := util.CreateSelfCert(ctx, certPath, keyPath, host); err != nil {
log.Fatalf("cert generation failed: %v\n", err)
}

fmt.Printf("Created cert file %s, key %s\n\n", certPath, keyPath)
}
33 changes: 30 additions & 3 deletions cli/rexray/rexray.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ package rexray

import (
"net/http"
_ "net/http/pprof"
"os"
"path/filepath"
"runtime/pprof"
"runtime/trace"
"strconv"
"sync"

log "github.com/Sirupsen/logrus"
"github.com/akutz/gotil"

"github.com/codedellemc/libstorage/api/context"
"github.com/codedellemc/libstorage/api/registry"
apitypes "github.com/codedellemc/libstorage/api/types"
Expand All @@ -19,6 +21,9 @@ import (

// load REX-Ray
_ "github.com/codedellemc/rexray"

// load the profiler
_ "net/http/pprof"
)

// Run the CLI.
Expand All @@ -34,11 +39,13 @@ func Run() {
exit sync.Once
)

pathConfig := utils.NewPathConfig(ctx, "", "")
ctx = ctx.WithValue(
context.PathConfigKey,
utils.NewPathConfig(ctx, "", ""))
context.PathConfigKey, pathConfig)
registry.ProcessRegisteredConfigs(ctx)

createUserKnownHostsFile(ctx, pathConfig)

onExit := func() {
if traceProfile != nil {
ctx.Info("stopping trace profile")
Expand Down Expand Up @@ -134,3 +141,23 @@ func setLogLevels(lvl log.Level) {
os.Setenv("REXRAY_LOGLEVEL", lvl.String())
os.Setenv("LIBSTORAGE_LOGGING_LEVEL", lvl.String())
}

func createUserKnownHostsFile(
ctx apitypes.Context,
pathConfig *apitypes.PathConfig) {

khPath := pathConfig.UserDefaultTLSKnownHosts

if gotil.FileExists(khPath) {
return
}

khDirPath := filepath.Dir(khPath)
os.MkdirAll(khDirPath, 0755)
khFile, err := os.Create(khPath)
if err != nil {
ctx.WithField("path", khPath).Fatal(
"failed to create known_hosts")
}
defer khFile.Close()
}
2 changes: 1 addition & 1 deletion glide-docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import:
repo: https://github.com/akutz/logrus

- package: github.com/codedellemc/libstorage
version: e752e4ca6ae3a8314c07b4a40d354cfce95c48bf # libstorage-version
version: 3a8dabcdad306c46dbb9e312e9e93e166674ec41 # libstorage-version
repo: https://github.com/codedellemc/libstorage # libstorage-repo

- package: github.com/akutz/gofig
Expand Down
34 changes: 28 additions & 6 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import:
repo: https://github.com/akutz/logrus

- package: github.com/codedellemc/libstorage
version: e752e4ca6ae3a8314c07b4a40d354cfce95c48bf # libstorage-version
version: 3a8dabcdad306c46dbb9e312e9e93e166674ec41 # libstorage-version
repo: https://github.com/codedellemc/libstorage # libstorage-repo

- package: github.com/akutz/gofig
Expand Down
Loading

0 comments on commit aaa0d27

Please sign in to comment.