diff --git a/PENDING.md b/PENDING.md index 3a7a6d2f74db..a905c1939ef6 100644 --- a/PENDING.md +++ b/PENDING.md @@ -19,6 +19,7 @@ FEATURES * Gaia REST API (`gaiacli advanced rest-server`) * Gaia CLI (`gaiacli`) + - [\#2961](https://github.com/cosmos/cosmos-sdk/issues/2961) Add --force flag to gaiacli keys delete command to skip passphrase check and force key deletion unconditionally. * Gaia diff --git a/client/keys/delete.go b/client/keys/delete.go index c53385f1a47c..e3fac4b7fb51 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -19,7 +19,8 @@ import ( ) const ( - flagYes = "yes" + flagYes = "yes" + flagForce = "force" ) func deleteKeyCommand() *cobra.Command { @@ -39,6 +40,8 @@ gaiacli. cmd.Flags().BoolP(flagYes, "y", false, "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") return cmd } @@ -62,20 +65,24 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error { return err } } - if err := kb.Delete(name, ""); err != nil { + if err := kb.Delete(name, "", true); err != nil { return err } fmt.Fprintln(os.Stderr, "Public key reference deleted") return nil } - oldpass, err := client.GetPassword( - "DANGER - enter password to permanently delete key:", buf) - if err != nil { - return err + // skip passphrase check if run with --force + skipPass := viper.GetBool(flagForce) + var oldpass string + if !skipPass { + if oldpass, err = client.GetPassword( + "DANGER - enter password to permanently delete key:", buf); err != nil { + return err + } } - err = kb.Delete(name, oldpass) + err = kb.Delete(name, oldpass, skipPass) if err != nil { return err } @@ -113,7 +120,7 @@ func DeleteKeyRequestHandler(w http.ResponseWriter, r *http.Request) { return } - err = kb.Delete(name, m.Password) + err = kb.Delete(name, m.Password, false) if keyerror.IsErrKeyNotFound(err) { w.WriteHeader(http.StatusNotFound) w.Write([]byte(err.Error())) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 25818025a894..882644cc6e7a 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -616,8 +616,8 @@ func getTestingHomeDirs() (string, string) { func initializeFixtures(t *testing.T) (chainID, servAddr, port string) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "") os.RemoveAll(filepath.Join(gaiadHome, "config", "gentx")) - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass) - executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s --force foo", gaiacliHome)) + executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s --force bar", gaiacliHome)) executeWriteCheckErr(t, fmt.Sprintf("gaiacli keys add --home=%s foo", gaiacliHome), app.DefaultKeyPass, app.DefaultKeyPass) executeWriteCheckErr(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass, app.DefaultKeyPass) fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf( diff --git a/crypto/keys/keybase.go b/crypto/keys/keybase.go index a5ec66893d00..982a4e7266ae 100644 --- a/crypto/keys/keybase.go +++ b/crypto/keys/keybase.go @@ -371,13 +371,13 @@ func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) { // passphrases don't match. // Passphrase is ignored when deleting references to // offline and Ledger / HW wallet keys. -func (kb dbKeybase) Delete(name, passphrase string) error { +func (kb dbKeybase) Delete(name, passphrase string, skipPass bool) error { // verify we have the proper password before deleting info, err := kb.Get(name) if err != nil { return err } - if linfo, ok := info.(localInfo); ok { + if linfo, ok := info.(localInfo); ok && !skipPass { if _, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase); err != nil { return err } diff --git a/crypto/keys/keybase_test.go b/crypto/keys/keybase_test.go index c8c65609ea8f..3c7f9806043e 100644 --- a/crypto/keys/keybase_test.go +++ b/crypto/keys/keybase_test.go @@ -73,9 +73,9 @@ func TestKeyManagement(t *testing.T) { require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) // deleting a key removes it - err = cstore.Delete("bad name", "foo") + err = cstore.Delete("bad name", "foo", false) require.NotNil(t, err) - err = cstore.Delete(n1, p1) + err = cstore.Delete(n1, p1, false) require.NoError(t, err) keyS, err = cstore.List() require.NoError(t, err) @@ -96,14 +96,14 @@ func TestKeyManagement(t *testing.T) { require.Equal(t, 2, len(keyS)) // delete the offline key - err = cstore.Delete(o1, "") + err = cstore.Delete(o1, "", false) require.NoError(t, err) keyS, err = cstore.List() require.NoError(t, err) require.Equal(t, 1, len(keyS)) - // addr cache gets nuked - err = cstore.Delete(n2, p2) + // addr cache gets nuked - and test skip flag + err = cstore.Delete(n2, "", true) require.NoError(t, err) require.False(t, db.Has(addrKey(i2.GetAddress()))) } @@ -336,7 +336,7 @@ func TestSeedPhrase(t *testing.T) { assert.NotEmpty(t, mnemonic) // now, let us delete this key - err = cstore.Delete(n1, p1) + err = cstore.Delete(n1, p1, false) require.Nil(t, err, "%+v", err) _, err = cstore.Get(n1) require.NotNil(t, err) diff --git a/crypto/keys/types.go b/crypto/keys/types.go index eeb4fdfcf0ce..b4b328516f02 100644 --- a/crypto/keys/types.go +++ b/crypto/keys/types.go @@ -14,7 +14,7 @@ type Keybase interface { List() ([]Info, error) Get(name string) (Info, error) GetByAddress(address types.AccAddress) (Info, error) - Delete(name, passphrase string) error + Delete(name, passphrase string, skipPass bool) error // Sign some bytes, looking up the private key to use Sign(name, passphrase string, msg []byte) ([]byte, crypto.PubKey, error)