From 376fe1f8867469034f9122dd796c5f2e2a2980e8 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 3 Dec 2019 13:22:00 +0100 Subject: [PATCH 01/21] Start working on keyring's encrypted file backend integration --- client/config.go | 4 ++-- client/flags/flags.go | 3 +++ client/keys/add.go | 1 + client/keys/delete.go | 3 +++ client/keys/export.go | 2 ++ client/keys/import.go | 2 ++ client/keys/list.go | 1 + client/keys/migrate.go | 1 + client/keys/show.go | 1 + client/keys/utils.go | 5 +++++ crypto/keys/keyring.go | 35 ++++++++++++++++++++++++++++------- 11 files changed, 49 insertions(+), 9 deletions(-) diff --git a/client/config.go b/client/config.go index 61258d96fe97..df4ea4f079c6 100644 --- a/client/config.go +++ b/client/config.go @@ -75,7 +75,7 @@ func runConfigCmd(cmd *cobra.Command, args []string) error { // get config value for a given key if getAction { switch key { - case "trace", "trust-node", "indent": + case "trace", "trust-node", "indent", "keyring-file": fmt.Println(tree.GetDefault(key, false).(bool)) default: @@ -101,7 +101,7 @@ func runConfigCmd(cmd *cobra.Command, args []string) error { case "chain-id", "output", "node", "broadcast-mode": tree.Set(key, value) - case "trace", "trust-node", "indent": + case "trace", "trust-node", "indent", "keyring-file": boolVal, err := strconv.ParseBool(value) if err != nil { return err diff --git a/client/flags/flags.go b/client/flags/flags.go index 62f2a8d012f9..e61bbb99f048 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -54,6 +54,7 @@ const ( FlagRPCWriteTimeout = "write-timeout" FlagOutputDocument = "output-document" // inspired by wget -O FlagSkipConfirmation = "yes" + FlagKeyringFile = "keyring-file" ) // LineBreak can be included in a command list to provide a blank line @@ -99,6 +100,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it") c.Flags().Bool(FlagGenerateOnly, false, "Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase is not accessible and the node operates offline)") c.Flags().BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation") + c.Flags().Bool(FlagKeyringFile, false, "Use the keyring's encrypted file backend") // --gas can accept integers and "simulate" c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf( @@ -109,6 +111,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { viper.BindPFlag(FlagTrustNode, c.Flags().Lookup(FlagTrustNode)) viper.BindPFlag(FlagUseLedger, c.Flags().Lookup(FlagUseLedger)) viper.BindPFlag(FlagNode, c.Flags().Lookup(FlagNode)) + viper.BindPFlag(FlagKeyringFile, c.Flags().Lookup(FlagKeyringFile)) c.MarkFlagRequired(FlagChainID) } diff --git a/client/keys/add.go b/client/keys/add.go index f55572887b12..70a81e0ccce4 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -72,6 +72,7 @@ the flag --nosort is set. cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation") cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation") cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") + cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") return cmd } diff --git a/client/keys/delete.go b/client/keys/delete.go index d2e535105a19..96d01552b0d0 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -4,6 +4,7 @@ import ( "bufio" "errors" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto/keys" @@ -34,6 +35,8 @@ private keys stored in a ledger device cannot be deleted with the CLI. "Skip confirmation prompt when deleting offline or ledger key references") cmd.Flags().BoolP(flagForce, "f", false, "Remove the key unconditionally without asking for the passphrase") + cmd.Flags().Bool(flags.FlagKeyringFile, false, + "Use the keyring's encrypted file backend") return cmd } diff --git a/client/keys/export.go b/client/keys/export.go index 393785501b45..d0afab4595e0 100644 --- a/client/keys/export.go +++ b/client/keys/export.go @@ -5,6 +5,7 @@ import ( "github.com/spf13/cobra" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" ) @@ -16,6 +17,7 @@ func exportKeyCommand() *cobra.Command { Args: cobra.ExactArgs(1), RunE: runExportCmd, } + cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") return cmd } diff --git a/client/keys/import.go b/client/keys/import.go index 127479ce994c..9ecbc7a7e636 100644 --- a/client/keys/import.go +++ b/client/keys/import.go @@ -6,6 +6,7 @@ import ( "github.com/spf13/cobra" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" ) @@ -17,6 +18,7 @@ func importKeyCommand() *cobra.Command { Args: cobra.ExactArgs(2), RunE: runImportCmd, } + cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") return cmd } diff --git a/client/keys/list.go b/client/keys/list.go index da4d4b22240f..53eff0dc4347 100644 --- a/client/keys/list.go +++ b/client/keys/list.go @@ -15,6 +15,7 @@ along with their associated name and address.`, RunE: runListCmd, } cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") + cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") return cmd } diff --git a/client/keys/migrate.go b/client/keys/migrate.go index 63f4e33b0262..047c8cf2e494 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -29,6 +29,7 @@ The command asks for every passphrase. If the passphrase is incorrect, it skips RunE: runMigrateCmd, } + cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") cmd.Flags().Bool(flags.FlagDryRun, false, "Do everything which is supposed to be done, but don't write any changes to the keyring.") return cmd } diff --git a/client/keys/show.go b/client/keys/show.go index fa37f372f90a..3124c64220f7 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -49,6 +49,7 @@ consisting of all the keys provided by name and multisig threshold.`, cmd.Flags().BoolP(FlagDevice, "d", false, "Output the address in a ledger device") cmd.Flags().Uint(flagMultiSigThreshold, 1, "K out of N required signatures") cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") + cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") return cmd } diff --git a/client/keys/utils.go b/client/keys/utils.go index 2b2ca06f0e5b..731ae06587b0 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -53,6 +53,11 @@ func NewKeyringFromDir(rootDir string, input io.Reader) (keys.Keybase, error) { if os.Getenv("COSMOS_SDK_TEST_KEYRING") != "" { return keys.NewTestKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir) } + + if viper.GetBool(flags.FlagKeyringFile) { + return keys.NewKeyringFile(sdk.GetConfig().GetKeyringServiceName(), rootDir, input) + } + return keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir, input) } diff --git a/crypto/keys/keyring.go b/crypto/keys/keyring.go index 839e15912f2e..f3c4bebbf96a 100644 --- a/crypto/keys/keyring.go +++ b/crypto/keys/keyring.go @@ -47,6 +47,16 @@ func NewKeyring(name string, dir string, userInput io.Reader) (Keybase, error) { return newKeyringKeybase(db), nil } +// NewKeyringFile creates a new instance of an encrypted file-backed keyring. +func NewKeyringFile(name string, dir string, userInput io.Reader) (Keybase, error) { + db, err := keyring.Open(newFileBackendKeyringConfig(name, dir, userInput)) + if err != nil { + return nil, err + } + + return newKeyringKeybase(db), nil +} + // NewTestKeyring creates a new instance of an on-disk keyring for // testing purposes that does not prompt users for password. func NewTestKeyring(name string, dir string) (Keybase, error) { @@ -463,7 +473,24 @@ func lkbToKeyringConfig(name, dir string, buf io.Reader, test bool) keyring.Conf } } - realPrompt := func(prompt string) (string, error) { + return keyring.Config{ + ServiceName: name, + FileDir: dir, + FilePasswordFunc: newRealPrompt(dir, buf), + } +} + +func newFileBackendKeyringConfig(name, dir string, buf io.Reader) keyring.Config { + return keyring.Config{ + AllowedBackends: []keyring.BackendType{"file"}, + ServiceName: name, + FileDir: dir, + FilePasswordFunc: newRealPrompt(dir, buf), + } +} + +func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) { + return func(prompt string) (string, error) { keyhashStored := false keyhashFilePath := filepath.Join(dir, "keyhash") @@ -532,12 +559,6 @@ func lkbToKeyringConfig(name, dir string, buf io.Reader, test bool) keyring.Conf return pass, nil } } - - return keyring.Config{ - ServiceName: name, - FileDir: dir, - FilePasswordFunc: realPrompt, - } } func fakePrompt(prompt string) (string, error) { From a97002eb998048855f8d952bb3d74e4a2d0445f2 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 4 Dec 2019 18:19:41 +0100 Subject: [PATCH 02/21] Store keyring and test keyring files under ~/.appcli/{,test-}keyring respectively --- crypto/keys/keyring.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crypto/keys/keyring.go b/crypto/keys/keyring.go index f3c4bebbf96a..28d9aaec8ff1 100644 --- a/crypto/keys/keyring.go +++ b/crypto/keys/keyring.go @@ -26,6 +26,11 @@ import ( "github.com/cosmos/cosmos-sdk/types" ) +const ( + keyringDirName = "keyring" + testKeyringDirName = "keyring-test" +) + var _ Keybase = keyringKeybase{} // keyringKeybase implements the Keybase interface by using the Keyring library @@ -468,7 +473,7 @@ func lkbToKeyringConfig(name, dir string, buf io.Reader, test bool) keyring.Conf return keyring.Config{ AllowedBackends: []keyring.BackendType{"file"}, ServiceName: name, - FileDir: dir, + FileDir: filepath.Join(dir, testKeyringDirName), FilePasswordFunc: fakePrompt, } } @@ -481,11 +486,12 @@ func lkbToKeyringConfig(name, dir string, buf io.Reader, test bool) keyring.Conf } func newFileBackendKeyringConfig(name, dir string, buf io.Reader) keyring.Config { + fileDir := filepath.Join(dir, keyringDirName) return keyring.Config{ AllowedBackends: []keyring.BackendType{"file"}, ServiceName: name, - FileDir: dir, - FilePasswordFunc: newRealPrompt(dir, buf), + FileDir: fileDir, + FilePasswordFunc: newRealPrompt(fileDir, buf), } } From 32c374c01de9ca22e6af298d558738af46a60c35 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 4 Dec 2019 18:28:39 +0100 Subject: [PATCH 03/21] Keybase -> keyring migration is in fact an API and ABI breakage breakage. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7148e122122b..ec7c95a38fc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ if the provided arguments are invalid. * (x/auth) [\#5006](https://github.com/cosmos/cosmos-sdk/pull/5006) The gas required to pass the `AnteHandler` has increased significantly due to modular `AnteHandler` support. Increase GasLimit accordingly. * (rest) [\#5336](https://github.com/cosmos/cosmos-sdk/issues/5336) `MsgEditValidator` uses `description` instead of `Description` as a JSON key. +* (keys) [\#5097](https://github.com/cosmos/cosmos-sdk/pull/5097) Due to the keybase -> keyring transition, keys need to be migrated. See `keys migrate` command for more info. ### Features From 14c1252a796c859cea43f36428c2e4c5df598bca Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 5 Dec 2019 12:27:12 +0100 Subject: [PATCH 04/21] Improve keyring docs --- client/keys/utils.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/keys/utils.go b/client/keys/utils.go index 731ae06587b0..bf8a69374e23 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -47,8 +47,10 @@ func NewKeyringFromHomeFlag(input io.Reader) (keys.Keybase, error) { } // NewKeyBaseFromDir initializes a keyring at a particular dir. -// If the COSMOS_SDK_TEST_KEYRING environment variable is set and not empty it will -// return an on-disk, password-less keyring that could be used for testing purposes. +// If the viper flag flags.FlagKeyringFile is true, it returns an on-disk keyring with +// CLI prompt support only. If the COSMOS_SDK_TEST_KEYRING environment variable is set and not +// empty it will return an on-disk, password-less keyring that could be used for testing purposes. +// Note that COSMOS_SDK_TEST_KEYRING takes precedence over the flags.FlagKeyringFile flag. func NewKeyringFromDir(rootDir string, input io.Reader) (keys.Keybase, error) { if os.Getenv("COSMOS_SDK_TEST_KEYRING") != "" { return keys.NewTestKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir) From 411cb42d96dea04798273a3dac6fdb1a77463e71 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 6 Dec 2019 16:21:31 +0100 Subject: [PATCH 05/21] Replace COSMOS_SDK_TEST_KEYRING env var with a global --keybase-backend flag CC @jackzampolin --- Makefile | 1 - client/config.go | 15 ++++++------ client/flags/flags.go | 50 +++++++++++++++++++++++++++++++++++----- client/keys/add.go | 1 - client/keys/delete.go | 3 --- client/keys/export.go | 5 +--- client/keys/import.go | 5 +--- client/keys/list.go | 1 - client/keys/migrate.go | 1 - client/keys/root.go | 3 +++ client/keys/root_test.go | 8 +++++++ client/keys/show.go | 1 - client/keys/utils.go | 21 ++++++++--------- 13 files changed, 74 insertions(+), 41 deletions(-) diff --git a/Makefile b/Makefile index f02d60c893f9..8d947640f75a 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,6 @@ SIMAPP = ./simapp MOCKS_DIR = $(CURDIR)/tests/mocks export GO111MODULE = on -export COSMOS_SDK_TEST_KEYRING = y all: tools build lint test diff --git a/client/config.go b/client/config.go index df4ea4f079c6..226d056fea06 100644 --- a/client/config.go +++ b/client/config.go @@ -20,10 +20,11 @@ const ( ) var configDefaults = map[string]string{ - "chain-id": "", - "output": "text", - "node": "tcp://localhost:26657", - "broadcast-mode": "sync", + "chain-id": "", + "keyring-backend": "os", + "output": "text", + "node": "tcp://localhost:26657", + "broadcast-mode": "sync", } // ConfigCmd returns a CLI command to interactively create an application CLI @@ -75,7 +76,7 @@ func runConfigCmd(cmd *cobra.Command, args []string) error { // get config value for a given key if getAction { switch key { - case "trace", "trust-node", "indent", "keyring-file": + case "trace", "trust-node", "indent": fmt.Println(tree.GetDefault(key, false).(bool)) default: @@ -98,10 +99,10 @@ func runConfigCmd(cmd *cobra.Command, args []string) error { // set config value for a given key switch key { - case "chain-id", "output", "node", "broadcast-mode": + case "chain-id", "output", "node", "broadcast-mode", "keyring-backend": tree.Set(key, value) - case "trace", "trust-node", "indent", "keyring-file": + case "trace", "trust-node", "indent": boolVal, err := strconv.ParseBool(value) if err != nil { return err diff --git a/client/flags/flags.go b/client/flags/flags.go index e61bbb99f048..150538bd7ff2 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -20,6 +20,12 @@ const ( DefaultGasLimit = 200000 GasFlagAuto = "auto" + // DefaultKeyringBackend + DefaultKeyringBackend = KeyringBackendOS + KeyringBackendOS = "os" + KeyringBackendFile = "file" + KeyringBackendTest = "test" + // BroadcastBlock defines a tx broadcasting mode where the client waits for // the tx to be committed in a block. BroadcastBlock = "block" @@ -54,14 +60,15 @@ const ( FlagRPCWriteTimeout = "write-timeout" FlagOutputDocument = "output-document" // inspired by wget -O FlagSkipConfirmation = "yes" - FlagKeyringFile = "keyring-file" + FlagKeyringBackend = "keyring-backend" ) // LineBreak can be included in a command list to provide a blank line // to help with readability var ( - LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}} - GasFlagVar = GasSetting{Gas: DefaultGasLimit} + LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}} + GasFlagVar = GasSetting{Gas: DefaultGasLimit} + KeyringBackendFlagVar = KeyringBackend{Backend: DefaultKeyringBackend} ) // GetCommands adds common flags to query commands @@ -100,18 +107,18 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it") c.Flags().Bool(FlagGenerateOnly, false, "Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase is not accessible and the node operates offline)") c.Flags().BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation") - c.Flags().Bool(FlagKeyringFile, false, "Use the keyring's encrypted file backend") + // --keyring-backend can accept "os", "file", "test" + c.Flags().Var(&KeyringBackendFlagVar, FlagKeyringBackend, "Select keyring's backend (os|file|test)") // --gas can accept integers and "simulate" c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf( "gas limit to set per-transaction; set to %q to calculate required gas automatically (default %d)", GasFlagAuto, DefaultGasLimit, )) - viper.BindPFlag(FlagTrustNode, c.Flags().Lookup(FlagTrustNode)) viper.BindPFlag(FlagUseLedger, c.Flags().Lookup(FlagUseLedger)) viper.BindPFlag(FlagNode, c.Flags().Lookup(FlagNode)) - viper.BindPFlag(FlagKeyringFile, c.Flags().Lookup(FlagKeyringFile)) + viper.BindPFlag(FlagKeyringBackend, c.Flags().Lookup(FlagKeyringBackend)) c.MarkFlagRequired(FlagChainID) } @@ -170,6 +177,37 @@ func ParseGas(gasStr string) (simulateAndExecute bool, gas uint64, err error) { return } +// Keyring backend flag parsing + +// KeyringBackend encapsulates the possible values passed through the --keyring-backend flag. +type KeyringBackend struct { + Backend string +} + +// Type returns the flag's value type. +func (v *KeyringBackend) Type() string { return "string" } + +// Set parses and sets the value of the --keyring-backend flag. +func (v *KeyringBackend) Set(s string) (err error) { + v.Backend, err = ParseKeyringBackend(s) + return +} + +// String returns a string representation. +func (v *KeyringBackend) String() string { return v.Backend } + +// ParseKeyringBackend parses the value of the keyring backend option. +func ParseKeyringBackend(str string) (string, error) { + switch str { + case "": + return KeyringBackendOS, nil + case KeyringBackendOS, KeyringBackendFile, KeyringBackendTest: + return str, nil + default: + return "", fmt.Errorf("unknown keyring backend %q", str) + } +} + // NewCompletionCmd builds a cobra.Command that generate bash completion // scripts for the given root command. If hidden is true, the command // will not show up in the root command's list of available commands. diff --git a/client/keys/add.go b/client/keys/add.go index 70a81e0ccce4..f55572887b12 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -72,7 +72,6 @@ the flag --nosort is set. cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation") cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation") cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") - cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") return cmd } diff --git a/client/keys/delete.go b/client/keys/delete.go index 0f328fc9ebf6..aadc831fe129 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -4,7 +4,6 @@ import ( "bufio" "errors" - "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto/keys" @@ -35,8 +34,6 @@ private keys stored in a ledger device cannot be deleted with the CLI. "Skip confirmation prompt when deleting offline or ledger key references") cmd.Flags().BoolP(flagForce, "f", false, "Remove the key unconditionally without asking for the passphrase. Deprecated.") - cmd.Flags().Bool(flags.FlagKeyringFile, false, - "Use the keyring's encrypted file backend") return cmd } diff --git a/client/keys/export.go b/client/keys/export.go index d0afab4595e0..dc6be244beec 100644 --- a/client/keys/export.go +++ b/client/keys/export.go @@ -5,20 +5,17 @@ import ( "github.com/spf13/cobra" - "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" ) func exportKeyCommand() *cobra.Command { - cmd := &cobra.Command{ + return &cobra.Command{ Use: "export ", Short: "Export private keys", Long: `Export a private key from the local keybase in ASCII-armored encrypted format.`, Args: cobra.ExactArgs(1), RunE: runExportCmd, } - cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") - return cmd } func runExportCmd(cmd *cobra.Command, args []string) error { diff --git a/client/keys/import.go b/client/keys/import.go index 9ecbc7a7e636..1e754b7852f9 100644 --- a/client/keys/import.go +++ b/client/keys/import.go @@ -6,20 +6,17 @@ import ( "github.com/spf13/cobra" - "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" ) func importKeyCommand() *cobra.Command { - cmd := &cobra.Command{ + return &cobra.Command{ Use: "import ", Short: "Import private keys into the local keybase", Long: "Import a ASCII armored private key into the local keybase.", Args: cobra.ExactArgs(2), RunE: runImportCmd, } - cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") - return cmd } func runImportCmd(cmd *cobra.Command, args []string) error { diff --git a/client/keys/list.go b/client/keys/list.go index 3ed6d67ee556..45d29a942699 100644 --- a/client/keys/list.go +++ b/client/keys/list.go @@ -18,7 +18,6 @@ along with their associated name and address.`, RunE: runListCmd, } cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") - cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") cmd.Flags().BoolP(flagListNames, "n", false, "List names only") return cmd } diff --git a/client/keys/migrate.go b/client/keys/migrate.go index 047c8cf2e494..63f4e33b0262 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -29,7 +29,6 @@ The command asks for every passphrase. If the passphrase is incorrect, it skips RunE: runMigrateCmd, } - cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") cmd.Flags().Bool(flags.FlagDryRun, false, "Do everything which is supposed to be done, but don't write any changes to the keyring.") return cmd } diff --git a/client/keys/root.go b/client/keys/root.go index b95740a2c036..86b8096f5ee0 100644 --- a/client/keys/root.go +++ b/client/keys/root.go @@ -2,6 +2,7 @@ package keys import ( "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/cosmos/cosmos-sdk/client/flags" ) @@ -31,5 +32,7 @@ func Commands() *cobra.Command { parseKeyStringCommand(), migrateCommand(), ) + cmd.PersistentFlags().Var(&flags.KeyringBackendFlagVar, flags.FlagKeyringBackend, "Select keyring's backend (os|file|test)") + viper.BindPFlag(flags.FlagKeyringBackend, cmd.Flags().Lookup(flags.FlagKeyringBackend)) return cmd } diff --git a/client/keys/root_test.go b/client/keys/root_test.go index 6794d725e6f0..efb86fc50c82 100644 --- a/client/keys/root_test.go +++ b/client/keys/root_test.go @@ -1,9 +1,12 @@ package keys import ( + "os" "testing" "github.com/stretchr/testify/assert" + + "github.com/cosmos/cosmos-sdk/client/flags" ) func TestCommands(t *testing.T) { @@ -13,3 +16,8 @@ func TestCommands(t *testing.T) { // Commands are registered assert.Equal(t, 11, len(rootCommands.Commands())) } + +func TestMain(m *testing.M) { + flags.KeyringBackendFlagVar.Set("test") + os.Exit(m.Run()) +} diff --git a/client/keys/show.go b/client/keys/show.go index 3124c64220f7..fa37f372f90a 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -49,7 +49,6 @@ consisting of all the keys provided by name and multisig threshold.`, cmd.Flags().BoolP(FlagDevice, "d", false, "Output the address in a ledger device") cmd.Flags().Uint(flagMultiSigThreshold, 1, "K out of N required signatures") cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") - cmd.Flags().Bool(flags.FlagKeyringFile, false, "Use the keyring's encrypted file backend") return cmd } diff --git a/client/keys/utils.go b/client/keys/utils.go index bf8a69374e23..f6e5ffad4587 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -3,7 +3,6 @@ package keys import ( "fmt" "io" - "os" "path/filepath" "github.com/99designs/keyring" @@ -46,21 +45,19 @@ func NewKeyringFromHomeFlag(input io.Reader) (keys.Keybase, error) { return NewKeyringFromDir(viper.GetString(flags.FlagHome), input) } -// NewKeyBaseFromDir initializes a keyring at a particular dir. -// If the viper flag flags.FlagKeyringFile is true, it returns an on-disk keyring with -// CLI prompt support only. If the COSMOS_SDK_TEST_KEYRING environment variable is set and not -// empty it will return an on-disk, password-less keyring that could be used for testing purposes. -// Note that COSMOS_SDK_TEST_KEYRING takes precedence over the flags.FlagKeyringFile flag. +// NewKeyBaseFromDir initializes a keyring at the given directory. +// If the viper flag flags.FlagKeyringBackend is set to file, it returns an on-disk keyring with +// CLI prompt support only. If flags.FlagKeyringBackend is set to test it will return an on-disk, +// password-less keyring that could be used for testing purposes. func NewKeyringFromDir(rootDir string, input io.Reader) (keys.Keybase, error) { - if os.Getenv("COSMOS_SDK_TEST_KEYRING") != "" { + switch flags.KeyringBackendFlagVar.Backend { + case "test": return keys.NewTestKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir) - } - - if viper.GetBool(flags.FlagKeyringFile) { + case "file": return keys.NewKeyringFile(sdk.GetConfig().GetKeyringServiceName(), rootDir, input) + default: + return keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir, input) } - - return keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir, input) } func getLazyKeyBaseFromDir(rootDir string) (keys.Keybase, error) { From ed89b9c429fc1f866727f326b67d1435bb70c1d9 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 6 Dec 2019 16:47:30 +0100 Subject: [PATCH 06/21] Add tests --- client/flags/flags.go | 10 +++++++--- client/flags/flags_test.go | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 client/flags/flags_test.go diff --git a/client/flags/flags.go b/client/flags/flags.go index 150538bd7ff2..b0a99597c65b 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -188,9 +188,13 @@ type KeyringBackend struct { func (v *KeyringBackend) Type() string { return "string" } // Set parses and sets the value of the --keyring-backend flag. -func (v *KeyringBackend) Set(s string) (err error) { - v.Backend, err = ParseKeyringBackend(s) - return +func (v *KeyringBackend) Set(s string) error { + val, err := ParseKeyringBackend(s) + if err != nil { + return err + } + v.Backend = val + return nil } // String returns a string representation. diff --git a/client/flags/flags_test.go b/client/flags/flags_test.go new file mode 100644 index 000000000000..97d6b6225337 --- /dev/null +++ b/client/flags/flags_test.go @@ -0,0 +1,20 @@ +package flags_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/client/flags" +) + +func TestKeyringBackend(t *testing.T) { + b := flags.KeyringBackend{Backend: "os"} + require.Equal(t, "string", b.Type()) + require.Error(t, b.Set("unknown")) + require.Equal(t, "os", b.String()) + require.NoError(t, b.Set("file")) + require.Equal(t, "file", b.String()) + require.NoError(t, b.Set("")) + require.Equal(t, "os", b.String()) +} From aca702652684b907efb66351b3bfc59af7f0a9c3 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 6 Dec 2019 17:08:19 +0100 Subject: [PATCH 07/21] Cosmetic adjustments --- client/alias.go | 5 +++++ client/flags/flags.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/client/alias.go b/client/alias.go index e2a1caf167a4..eed043c54401 100644 --- a/client/alias.go +++ b/client/alias.go @@ -24,6 +24,7 @@ import ( const ( DefaultGasAdjustment = flags.DefaultGasAdjustment DefaultGasLimit = flags.DefaultGasLimit + DefaultKeyringBackend = flags.DefaultKeyringBackend GasFlagAuto = flags.GasFlagAuto BroadcastBlock = flags.BroadcastBlock BroadcastSync = flags.BroadcastSync @@ -46,12 +47,16 @@ const ( FlagDryRun = flags.FlagDryRun FlagGenerateOnly = flags.FlagGenerateOnly FlagIndentResponse = flags.FlagIndentResponse + FlagKeyringBackend = flags.FlagKeyringBackend FlagListenAddr = flags.FlagListenAddr FlagMaxOpenConnections = flags.FlagMaxOpenConnections FlagRPCReadTimeout = flags.FlagRPCReadTimeout FlagRPCWriteTimeout = flags.FlagRPCWriteTimeout FlagOutputDocument = flags.FlagOutputDocument FlagSkipConfirmation = flags.FlagSkipConfirmation + KeyringBackendFile = flags.KeyringBackendFile + KeyringBackendOS = flags.KeyringBackendOS + KeyringBackendTest = flags.KeyringBackendTest DefaultKeyPass = keys.DefaultKeyPass FlagAddress = keys.FlagAddress FlagPublicKey = keys.FlagPublicKey diff --git a/client/flags/flags.go b/client/flags/flags.go index b0a99597c65b..1a3741351b3f 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -22,8 +22,8 @@ const ( // DefaultKeyringBackend DefaultKeyringBackend = KeyringBackendOS - KeyringBackendOS = "os" KeyringBackendFile = "file" + KeyringBackendOS = "os" KeyringBackendTest = "test" // BroadcastBlock defines a tx broadcasting mode where the client waits for From fd2355e68052e4e325a50efa68541fba2dc208a0 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 6 Dec 2019 18:07:37 +0100 Subject: [PATCH 08/21] Fix gentx --- x/genutil/client/cli/gentx.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/genutil/client/cli/gentx.go b/x/genutil/client/cli/gentx.go index f6a2a334c71b..4e2a4efc0521 100644 --- a/x/genutil/client/cli/gentx.go +++ b/x/genutil/client/cli/gentx.go @@ -23,6 +23,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" kbkeys "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/server" @@ -194,6 +195,7 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm cmd.Flags().String(client.FlagOutputDocument, "", "write the genesis transaction JSON document to the given file instead of the default location") cmd.Flags().AddFlagSet(fsCreateValidator) + cmd.Flags().Var(&flags.KeyringBackendFlagVar, client.FlagKeyringBackend, "Select keyring's backend (os|file|test)") cmd.MarkFlagRequired(client.FlagName) return cmd From abc25e0f6bf3319a435f42200a8b05c71738b269 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 6 Dec 2019 19:36:39 +0100 Subject: [PATCH 09/21] Bind flag --- x/genutil/client/cli/gentx.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/genutil/client/cli/gentx.go b/x/genutil/client/cli/gentx.go index 4e2a4efc0521..1d907ceab52e 100644 --- a/x/genutil/client/cli/gentx.go +++ b/x/genutil/client/cli/gentx.go @@ -196,6 +196,7 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm "write the genesis transaction JSON document to the given file instead of the default location") cmd.Flags().AddFlagSet(fsCreateValidator) cmd.Flags().Var(&flags.KeyringBackendFlagVar, client.FlagKeyringBackend, "Select keyring's backend (os|file|test)") + viper.BindPFlag(flags.FlagKeyringBackend, cmd.Flags().Lookup(flags.FlagKeyringBackend)) cmd.MarkFlagRequired(client.FlagName) return cmd From 563e2f333116c0cda6c8fd54dd3ac7d374793aa2 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sat, 7 Dec 2019 12:50:48 +0100 Subject: [PATCH 10/21] Simplify flag handling --- client/flags/flags.go | 43 +++-------------------------------- client/flags/flags_test.go | 20 ---------------- client/keys/root.go | 2 +- client/keys/root_test.go | 3 ++- client/keys/utils.go | 10 ++++---- x/genutil/client/cli/gentx.go | 2 +- 6 files changed, 13 insertions(+), 67 deletions(-) delete mode 100644 client/flags/flags_test.go diff --git a/client/flags/flags.go b/client/flags/flags.go index 1a3741351b3f..9451500bfc21 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -66,9 +66,8 @@ const ( // LineBreak can be included in a command list to provide a blank line // to help with readability var ( - LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}} - GasFlagVar = GasSetting{Gas: DefaultGasLimit} - KeyringBackendFlagVar = KeyringBackend{Backend: DefaultKeyringBackend} + LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}} + GasFlagVar = GasSetting{Gas: DefaultGasLimit} ) // GetCommands adds common flags to query commands @@ -107,9 +106,8 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it") c.Flags().Bool(FlagGenerateOnly, false, "Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase is not accessible and the node operates offline)") c.Flags().BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation") + c.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|test)") - // --keyring-backend can accept "os", "file", "test" - c.Flags().Var(&KeyringBackendFlagVar, FlagKeyringBackend, "Select keyring's backend (os|file|test)") // --gas can accept integers and "simulate" c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf( "gas limit to set per-transaction; set to %q to calculate required gas automatically (default %d)", @@ -177,41 +175,6 @@ func ParseGas(gasStr string) (simulateAndExecute bool, gas uint64, err error) { return } -// Keyring backend flag parsing - -// KeyringBackend encapsulates the possible values passed through the --keyring-backend flag. -type KeyringBackend struct { - Backend string -} - -// Type returns the flag's value type. -func (v *KeyringBackend) Type() string { return "string" } - -// Set parses and sets the value of the --keyring-backend flag. -func (v *KeyringBackend) Set(s string) error { - val, err := ParseKeyringBackend(s) - if err != nil { - return err - } - v.Backend = val - return nil -} - -// String returns a string representation. -func (v *KeyringBackend) String() string { return v.Backend } - -// ParseKeyringBackend parses the value of the keyring backend option. -func ParseKeyringBackend(str string) (string, error) { - switch str { - case "": - return KeyringBackendOS, nil - case KeyringBackendOS, KeyringBackendFile, KeyringBackendTest: - return str, nil - default: - return "", fmt.Errorf("unknown keyring backend %q", str) - } -} - // NewCompletionCmd builds a cobra.Command that generate bash completion // scripts for the given root command. If hidden is true, the command // will not show up in the root command's list of available commands. diff --git a/client/flags/flags_test.go b/client/flags/flags_test.go deleted file mode 100644 index 97d6b6225337..000000000000 --- a/client/flags/flags_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package flags_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/client/flags" -) - -func TestKeyringBackend(t *testing.T) { - b := flags.KeyringBackend{Backend: "os"} - require.Equal(t, "string", b.Type()) - require.Error(t, b.Set("unknown")) - require.Equal(t, "os", b.String()) - require.NoError(t, b.Set("file")) - require.Equal(t, "file", b.String()) - require.NoError(t, b.Set("")) - require.Equal(t, "os", b.String()) -} diff --git a/client/keys/root.go b/client/keys/root.go index 86b8096f5ee0..5e54a5263ed4 100644 --- a/client/keys/root.go +++ b/client/keys/root.go @@ -32,7 +32,7 @@ func Commands() *cobra.Command { parseKeyStringCommand(), migrateCommand(), ) - cmd.PersistentFlags().Var(&flags.KeyringBackendFlagVar, flags.FlagKeyringBackend, "Select keyring's backend (os|file|test)") + cmd.PersistentFlags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") viper.BindPFlag(flags.FlagKeyringBackend, cmd.Flags().Lookup(flags.FlagKeyringBackend)) return cmd } diff --git a/client/keys/root_test.go b/client/keys/root_test.go index efb86fc50c82..49681b17e95f 100644 --- a/client/keys/root_test.go +++ b/client/keys/root_test.go @@ -4,6 +4,7 @@ import ( "os" "testing" + "github.com/spf13/viper" "github.com/stretchr/testify/assert" "github.com/cosmos/cosmos-sdk/client/flags" @@ -18,6 +19,6 @@ func TestCommands(t *testing.T) { } func TestMain(m *testing.M) { - flags.KeyringBackendFlagVar.Set("test") + viper.Set(flags.FlagKeyringBackend, flags.KeyringBackendTest) os.Exit(m.Run()) } diff --git a/client/keys/utils.go b/client/keys/utils.go index f6e5ffad4587..1096ae6e0790 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -50,14 +50,16 @@ func NewKeyringFromHomeFlag(input io.Reader) (keys.Keybase, error) { // CLI prompt support only. If flags.FlagKeyringBackend is set to test it will return an on-disk, // password-less keyring that could be used for testing purposes. func NewKeyringFromDir(rootDir string, input io.Reader) (keys.Keybase, error) { - switch flags.KeyringBackendFlagVar.Backend { - case "test": + keyringBackend := viper.GetString(flags.FlagKeyringBackend) + switch keyringBackend { + case flags.KeyringBackendTest: return keys.NewTestKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir) - case "file": + case flags.KeyringBackendFile: return keys.NewKeyringFile(sdk.GetConfig().GetKeyringServiceName(), rootDir, input) - default: + case flags.KeyringBackendOS: return keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir, input) } + return nil, fmt.Errorf("unknown keyring backend %q", keyringBackend) } func getLazyKeyBaseFromDir(rootDir string) (keys.Keybase, error) { diff --git a/x/genutil/client/cli/gentx.go b/x/genutil/client/cli/gentx.go index 1d907ceab52e..462969e52ee7 100644 --- a/x/genutil/client/cli/gentx.go +++ b/x/genutil/client/cli/gentx.go @@ -195,7 +195,7 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm cmd.Flags().String(client.FlagOutputDocument, "", "write the genesis transaction JSON document to the given file instead of the default location") cmd.Flags().AddFlagSet(fsCreateValidator) - cmd.Flags().Var(&flags.KeyringBackendFlagVar, client.FlagKeyringBackend, "Select keyring's backend (os|file|test)") + cmd.Flags().String(client.FlagKeyringBackend, client.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") viper.BindPFlag(flags.FlagKeyringBackend, cmd.Flags().Lookup(flags.FlagKeyringBackend)) cmd.MarkFlagRequired(client.FlagName) From 6b925f33fab20f8e6311595e7012a8a2c6e72b5e Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 8 Dec 2019 14:26:29 +0100 Subject: [PATCH 11/21] Add test case --- crypto/keys/keyring_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crypto/keys/keyring_test.go b/crypto/keys/keyring_test.go index 0916e0f46e9e..84cfe3816f34 100644 --- a/crypto/keys/keyring_test.go +++ b/crypto/keys/keyring_test.go @@ -2,6 +2,7 @@ package keys import ( + "strings" "testing" "github.com/stretchr/testify/assert" @@ -323,3 +324,11 @@ func TestLazySeedPhraseKeyRing(t *testing.T) { require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) } + +func TestNewKeyringFile(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + defer cleanup() + buf := strings.NewReader("password\npassword\n") + _, err := NewKeyringFile("test", dir, buf) + require.NoError(t, err) +} From e72641cc10aff9f97e95be2dcd789c3087952ba7 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 8 Dec 2019 14:35:24 +0100 Subject: [PATCH 12/21] Add test case --- client/keys/utils_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 client/keys/utils_test.go diff --git a/client/keys/utils_test.go b/client/keys/utils_test.go new file mode 100644 index 000000000000..85fb7b63a116 --- /dev/null +++ b/client/keys/utils_test.go @@ -0,0 +1,25 @@ +package keys + +import ( + "path/filepath" + "strings" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/tests" +) + +func TestNewKeyringFromDir(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + defer cleanup() + viper.Set(flags.FlagKeyringBackend, flags.KeyringBackendTest) + _, err := NewKeyringFromDir(filepath.Join(dir, "test"), nil) + require.NoError(t, err) + viper.Set(flags.FlagKeyringBackend, flags.KeyringBackendFile) + buf := strings.NewReader("password\npassword\n") + _, err = NewKeyringFromDir(filepath.Join(dir, "test"), buf) + require.NoError(t, err) +} From ed0522585e892acb04336bd6d7f540e3fd6bc66b Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 8 Dec 2019 14:47:47 +0100 Subject: [PATCH 13/21] Update CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc10eda52ac1..f73952c0ac0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,6 +105,11 @@ the following [issue](https://github.com/keybase/go-keychain/issues/47) with the you encounter this issue, you must upgrade your xcode command line tools to version >= `10.2`. You can upgrade via: `sudo rm -rf /Library/Developer/CommandLineTools; xcode-select --install`. Verify the correct version via: `pkgutil --pkg-info=com.apple.pkg.CLTools_Executables`. +* Client commands accept a new `--keyring-backend` option through which users can specify which backend should be used +by the new key store: + - `os`: use OS default credentials storage (default). + - `file`: use encrypted file-based store. + - `test`: use password-less key store. *For testing purposes only. Use it at your own risk.* * (keys) [\#5097](https://github.com/cosmos/cosmos-sdk/pull/5097) New `keys migrate` command to assist users migrate their keys to the new keyring. * (keys) [\#5366](https://github.com/cosmos/cosmos-sdk/pull/5366) `keys list` now accepts a `--list-names` option to list key names only, whilst the `keys delete` From fc190ab95e1a89ca8bebea2aedc81b3cdb47b589 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 8 Dec 2019 14:49:24 +0100 Subject: [PATCH 14/21] Update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f73952c0ac0c..c5edd6040dac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,7 +105,7 @@ the following [issue](https://github.com/keybase/go-keychain/issues/47) with the you encounter this issue, you must upgrade your xcode command line tools to version >= `10.2`. You can upgrade via: `sudo rm -rf /Library/Developer/CommandLineTools; xcode-select --install`. Verify the correct version via: `pkgutil --pkg-info=com.apple.pkg.CLTools_Executables`. -* Client commands accept a new `--keyring-backend` option through which users can specify which backend should be used +* [\#5355](https://github.com/cosmos/cosmos-sdk/pull/5355) Client commands accept a new `--keyring-backend` option through which users can specify which backend should be used by the new key store: - `os`: use OS default credentials storage (default). - `file`: use encrypted file-based store. From 5f777bf15aee541a76f23c78f0e7143a3dfde3af Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 9 Dec 2019 18:17:38 +0100 Subject: [PATCH 15/21] Create README.md --- crypto/keys/README.md | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 crypto/keys/README.md diff --git a/crypto/keys/README.md b/crypto/keys/README.md new file mode 100644 index 000000000000..d0f9dad28fd5 --- /dev/null +++ b/crypto/keys/README.md @@ -0,0 +1,44 @@ +# Keys + +[![API Reference](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys?status.svg)](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys) + +# Keybase API + +## The Keybase interface + +The [Keybase](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#Keybase) interface defines +the methods that a type needs to implement to be used as key storage backend. This package provided +few implementations out-of-the-box. + +## Constructors + +### New + +The [New](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#New) constructor returns +an on-disk implementation backed by LevelDB storage that has been the default implementation used by the SDK until v0.38.0. +Due to [security concerns](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-006-secret-store-replacement.md), we recommend to drop +it in favor of the `NewKeyring` or `NewKeyringFile` constructors. + +### NewInMemory + +The [NewInMemory](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#NewInMemory) constructor returns +an implementation backed by an in-memory LevelDB storage that we've historically used for testing purposes or on-the-fly +key generation and we consider safe for the aforementioned use cases as keys generated are discarded the process terminates +or the type instance is garbage collected. + +### NewKeyring + +The [NewKeyring](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#NewKeyring) constructor returns +an implementation backed by the [Keyring](https://github.com/99designs/keyring) library, whose aim is to provide a common +abstraction and uniform interface between secret stores available for Windows, macOS, and most GNU/Linux distributions. +The instance returned by this constructor will use the operating system's default credentials store, which will then handle +keys storage operations securely. + +### NewKeyringFile, NewTestKeyring + +Both [NewKeyringFile](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#NewKeyringFile) and +[NewTestKeyring](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#NewTestKeyring) constructors return +on-disk implementations backed by the [Keyring](https://github.com/99designs/keyring) `file` backend. +Whilst `NewKeyringFile` returns a secure, encrypted file-based type that requires user's password in order to +function correctly, the implementation returned by `NewTestKeyring` stores keys information in clear text and **must be used +only for testing purposes**. From 810083fed51da9f3dfdd38d457c91c8003e256f6 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 9 Dec 2019 18:25:05 +0100 Subject: [PATCH 16/21] Typo --- crypto/keys/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/keys/README.md b/crypto/keys/README.md index d0f9dad28fd5..2490fd24539c 100644 --- a/crypto/keys/README.md +++ b/crypto/keys/README.md @@ -7,7 +7,7 @@ ## The Keybase interface The [Keybase](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#Keybase) interface defines -the methods that a type needs to implement to be used as key storage backend. This package provided +the methods that a type needs to implement to be used as key storage backend. This package provides few implementations out-of-the-box. ## Constructors From 7fc84fb4d99c289bf20e864d606a591e57b7b74f Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 9 Dec 2019 18:28:32 +0100 Subject: [PATCH 17/21] Fixes --- crypto/keys/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crypto/keys/README.md b/crypto/keys/README.md index 2490fd24539c..1ec2722f0314 100644 --- a/crypto/keys/README.md +++ b/crypto/keys/README.md @@ -17,14 +17,15 @@ few implementations out-of-the-box. The [New](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#New) constructor returns an on-disk implementation backed by LevelDB storage that has been the default implementation used by the SDK until v0.38.0. Due to [security concerns](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-006-secret-store-replacement.md), we recommend to drop -it in favor of the `NewKeyring` or `NewKeyringFile` constructors. +it in favor of the `NewKeyring` or `NewKeyringFile` constructors. We strongly advise to migrate away from this function as **it may be removed in a future +release**. ### NewInMemory The [NewInMemory](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#NewInMemory) constructor returns an implementation backed by an in-memory LevelDB storage that we've historically used for testing purposes or on-the-fly -key generation and we consider safe for the aforementioned use cases as keys generated are discarded the process terminates -or the type instance is garbage collected. +key generation and we consider safe for the aforementioned use cases since the generated keys are discarded when the process +terminates or the type instance is garbage collected. ### NewKeyring From 34ced6d527fdebaacc28092c96eb795bacd53c7f Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 9 Dec 2019 19:41:52 +0100 Subject: [PATCH 18/21] Update crypto/keys/README.md Co-Authored-By: Alexander Bezobchuk --- crypto/keys/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/keys/README.md b/crypto/keys/README.md index 1ec2722f0314..5d9d66b6226e 100644 --- a/crypto/keys/README.md +++ b/crypto/keys/README.md @@ -1,4 +1,4 @@ -# Keys +# Keys API [![API Reference](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys?status.svg)](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys) From c2b248fb4c3026c2eb74bb9d9b7785d6a8ac1c4e Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 9 Dec 2019 19:42:15 +0100 Subject: [PATCH 19/21] Update crypto/keys/README.md Co-Authored-By: Alexander Bezobchuk --- crypto/keys/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/crypto/keys/README.md b/crypto/keys/README.md index 5d9d66b6226e..9901914e03e1 100644 --- a/crypto/keys/README.md +++ b/crypto/keys/README.md @@ -2,7 +2,6 @@ [![API Reference](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys?status.svg)](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys) -# Keybase API ## The Keybase interface From 6b3b8f3ae57089bfcd3dfc36d469bf412f10078e Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 9 Dec 2019 19:44:19 +0100 Subject: [PATCH 20/21] Fix NewInMemory description --- crypto/keys/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/keys/README.md b/crypto/keys/README.md index 1ec2722f0314..c59f7e87884e 100644 --- a/crypto/keys/README.md +++ b/crypto/keys/README.md @@ -23,7 +23,7 @@ release**. ### NewInMemory The [NewInMemory](https://godoc.org/github.com/cosmos/cosmos-sdk/crypto/keys#NewInMemory) constructor returns -an implementation backed by an in-memory LevelDB storage that we've historically used for testing purposes or on-the-fly +an implementation backed by an in-memory, goroutine-safe map that we've historically used for testing purposes or on-the-fly key generation and we consider safe for the aforementioned use cases since the generated keys are discarded when the process terminates or the type instance is garbage collected. From afbb1638eece6ccc45d57e5d2f4c3477a3acd759 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 9 Dec 2019 19:48:11 +0100 Subject: [PATCH 21/21] Add info on where keyring files are stored --- crypto/keys/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crypto/keys/README.md b/crypto/keys/README.md index c59f7e87884e..97b2a87c7672 100644 --- a/crypto/keys/README.md +++ b/crypto/keys/README.md @@ -43,3 +43,6 @@ on-disk implementations backed by the [Keyring](https://github.com/99designs/key Whilst `NewKeyringFile` returns a secure, encrypted file-based type that requires user's password in order to function correctly, the implementation returned by `NewTestKeyring` stores keys information in clear text and **must be used only for testing purposes**. + +`NewKeyringFile` and `NewTestKeyring` store key files in the client home directory's `keyring` +and `keyring-test` subdirectories respectively.