From 6389d208ccd68d5f921b005d60b00e3126882bec Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 21:33:27 +0100 Subject: [PATCH] Key server API integrated in CLI --- cmd/new.go | 2 +- cmd/serve.go | 86 ++++++++++++++++++++++++++++++++++++++-------- proxy/keys.go | 8 +++-- proxy/keys_test.go | 2 +- 4 files changed, 79 insertions(+), 19 deletions(-) diff --git a/cmd/new.go b/cmd/new.go index 5ac0d3b9..27c7dce7 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -33,7 +33,7 @@ passed as a command line argument for security.`, func init() { RootCmd.AddCommand(newCmd) - newCmd.Flags().StringP("type", "t", "ed25519", "Type of key (ed25519|secp256k1") + newCmd.Flags().StringP("type", "t", "ed25519", "Type of key (ed25519|secp256k1)") } func newPassword(cmd *cobra.Command, args []string) { diff --git a/cmd/serve.go b/cmd/serve.go index 06e923c7..1555c648 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -16,8 +16,16 @@ package cmd import ( "fmt" + "net" + "net/http" + "os" + "github.com/gorilla/handlers" + "github.com/gorilla/mux" + "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/tendermint/go-keys/proxy" ) // serveCmd represents the serve command @@ -28,23 +36,71 @@ var serveCmd = &cobra.Command{ private keys much more in depth than the cli can perform. In particular, this will allow you to sign transactions with the private keys in the store.`, - Run: func(cmd *cobra.Command, args []string) { - // TODO: Work your own magic here - fmt.Println("serve called") - }, + RunE: server, } func init() { RootCmd.AddCommand(serveCmd) - - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // serveCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // serveCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") - + serveCmd.Flags().IntP("port", "p", 8118, "TCP Port for listen for http server") + serveCmd.Flags().StringP("socket", "s", "", "UNIX socket for more secure http server") + serveCmd.Flags().StringP("type", "t", "ed25519", "Default key type (ed25519|secp256k1)") +} + +func server(cmd *cobra.Command, args []string) error { + var l net.Listener + var err error + socket := viper.GetString("socket") + if socket != "" { + l, err = createSocket(socket) + if err != nil { + return errors.Wrap(err, "Cannot create socket") + } + } else { + port := viper.GetInt("port") + l, err = net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + return errors.Errorf("Cannot listen on port %d", port) + } + } + + router := mux.NewRouter() + ks := proxy.NewKeyServer(manager, viper.GetString("type")) + ks.Register(router) + + // only set cors for tcp listener + var h http.Handler + if socket == "" { + allowedHeaders := handlers.AllowedHeaders([]string{"Content-Type"}) + h = handlers.CORS(allowedHeaders)(router) + } else { + h = router + } + + err = http.Serve(l, h) + fmt.Printf("Server Killed: %+v\n", err) + return nil +} + +// createSocket deletes existing socket if there, creates a new one, +// starts a server on the socket, and sets permissions to 0600 +func createSocket(socket string) (net.Listener, error) { + err := os.Remove(socket) + if err != nil && !os.IsNotExist(err) { + // only fail if it does exist and cannot be deleted + return nil, err + } + + l, err := net.Listen("unix", socket) + if err != nil { + return nil, err + } + + mode := os.FileMode(0700) | os.ModeSocket + err = os.Chmod(socket, mode) + if err != nil { + l.Close() + return nil, err + } + + return l, nil } diff --git a/proxy/keys.go b/proxy/keys.go index 64b6819c..0dde5707 100644 --- a/proxy/keys.go +++ b/proxy/keys.go @@ -11,16 +11,20 @@ import ( type KeyServer struct { manager keys.Manager + algo string } -func NewKeyServer(manager keys.Manager) KeyServer { +func NewKeyServer(manager keys.Manager, algo string) KeyServer { return KeyServer{ manager: manager, + algo: algo, } } func (k KeyServer) GenerateKey(w http.ResponseWriter, r *http.Request) { - req := types.CreateKeyRequest{} + req := types.CreateKeyRequest{ + Algo: k.algo, // default key type from cli + } err := readRequest(r, &req) if err != nil { writeError(w, err) diff --git a/proxy/keys_test.go b/proxy/keys_test.go index 6eee94e3..3a9c7371 100644 --- a/proxy/keys_test.go +++ b/proxy/keys_test.go @@ -92,7 +92,7 @@ func setupServer() http.Handler { ) // build your http server - ks := proxy.NewKeyServer(cstore) + ks := proxy.NewKeyServer(cstore, "ed25519") r := mux.NewRouter() sk := r.PathPrefix("/keys").Subrouter() ks.Register(sk)