passwd command and tests

Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
This commit is contained in:
Riyaz Faizullabhoy 2016-01-20 17:30:14 -08:00
parent a5df40762d
commit 9c59af1397
3 changed files with 110 additions and 0 deletions

View File

@ -844,6 +844,36 @@ func TestLogLevelFlags(t *testing.T) {
assert.Equal(t, "debug", logrus.GetLevel().String())
}
func TestClientKeyPassphraseChange(t *testing.T) {
// -- setup --
setUp(t)
tempDir := tempDirWithConfig(t, "{}")
defer os.RemoveAll(tempDir)
server := setupServer()
defer server.Close()
// -- tests --
_, err := runCommand(t, tempDir, "-s", server.URL, "init", "gun1")
assert.NoError(t, err)
// we should have three keys stored locally in total: root, targets, snapshot
rootIDs, _ := assertNumKeys(t, tempDir, 1, 2, true)
// only one rootID, try changing the private key passphrase
rootID := rootIDs[0]
_, err = runCommand(t, tempDir, "-s", server.URL, "key", "passwd", rootID)
assert.NoError(t, err)
// make sure we can init a new repo with this key
_, err = runCommand(t, tempDir, "-s", server.URL, "init", "gun2")
assert.NoError(t, err)
// assert that the root key ID didn't change
rootIDs, _ = assertNumKeys(t, tempDir, 1, 4, true)
assert.Equal(t, rootID, rootIDs[0])
}
func tempDirWithConfig(t *testing.T, config string) string {
tempDir, err := ioutil.TempDir("/tmp", "repo")
assert.NoError(t, err)

View File

@ -104,6 +104,12 @@ var cmdKeyRemoveTemplate = usageTemplate{
Long: "Removes the key with the given keyID. If the key is stored in more than one location, you will be asked which one to remove.",
}
var cmdKeyPasswdTemplate = usageTemplate{
Use: "passwd [ keyID ]",
Short: "Changes the passphrase for the root key with the given keyID.",
Long: "Changes the passphrase for the root key with the given keyID. Will require validation of the old passphrase.",
}
type keyCommander struct {
// these need to be set
configGetter func() *viper.Viper
@ -123,6 +129,7 @@ func (k *keyCommander) GetCommand() *cobra.Command {
cmd.AddCommand(cmdKeysRestoreTemplate.ToCommand(k.keysRestore))
cmd.AddCommand(cmdKeyImportRootTemplate.ToCommand(k.keysImportRoot))
cmd.AddCommand(cmdKeyRemoveTemplate.ToCommand(k.keyRemove))
cmd.AddCommand(cmdKeyPasswdTemplate.ToCommand(k.keyPassphraseChange))
cmdKeysBackup := cmdKeysBackupTemplate.ToCommand(k.keysBackup)
cmdKeysBackup.Flags().StringVarP(
@ -484,6 +491,47 @@ func (k *keyCommander) keyRemove(cmd *cobra.Command, args []string) error {
return err
}
// keyPassphraseChange changes the passphrase for a root key's private key based on ID
func (k *keyCommander) keyPassphraseChange(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("must specify the key ID of the root key to change the passphrase of")
}
config := k.configGetter()
ks, err := k.getKeyStores(config, true)
if err != nil {
return err
}
keyID := args[0]
// This is an invalid ID
if len(keyID) != notary.Sha256HexSize {
return fmt.Errorf("invalid key ID provided: %s", keyID)
}
// We only allow for changing the root key, so use no gun
cs := cryptoservice.NewCryptoService("", ks...)
privKey, role, err := cs.GetPrivateKey(keyID)
if err != nil {
return fmt.Errorf("could not retrieve local root key for key ID provided: %s", keyID)
}
// Must use a different passphrase retriever to avoid caching the
// unlocking passphrase and reusing that.
passChangeRetriever := getRetriever()
keyStore, err := trustmanager.NewKeyFileStore(config.GetString("trust_dir"), passChangeRetriever)
err = keyStore.AddKey(keyID, role, privKey)
if err != nil {
return err
}
cmd.Println("")
cmd.Printf("Successfully updated passphrase for key ID: %s", keyID)
cmd.Println("")
return nil
}
func (k *keyCommander) getKeyStores(
config *viper.Viper, withHardware bool) ([]trustmanager.KeyStore, error) {

View File

@ -12,6 +12,7 @@ import (
"testing"
"github.com/docker/go/canonical/json"
"github.com/docker/notary"
"github.com/docker/notary/client"
"github.com/docker/notary/passphrase"
"github.com/docker/notary/trustmanager"
@ -401,3 +402,34 @@ func TestRotateKeyBothKeys(t *testing.T) {
assert.True(t, targetsFound, "targets key was not created")
assert.True(t, snapshotFound, "snapshot key was not created")
}
func TestChangeKeyPassphraseInvalidID(t *testing.T) {
k := &keyCommander{
configGetter: viper.New,
retriever: passphrase.ConstantRetriever("pass"),
}
err := k.keyPassphraseChange(&cobra.Command{}, []string{"too_short"})
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid key ID provided")
}
func TestChangeKeyPassphraseInvalidNumArgs(t *testing.T) {
k := &keyCommander{
configGetter: viper.New,
retriever: passphrase.ConstantRetriever("pass"),
}
err := k.keyPassphraseChange(&cobra.Command{}, []string{})
assert.Error(t, err)
assert.Contains(t, err.Error(), "must specify the key ID")
}
func TestChangeKeyPassphraseNonexistentID(t *testing.T) {
k := &keyCommander{
configGetter: viper.New,
retriever: passphrase.ConstantRetriever("pass"),
}
// Valid ID size, but does not exist as a key ID
err := k.keyPassphraseChange(&cobra.Command{}, []string{strings.Repeat("x", notary.Sha256HexSize)})
assert.Error(t, err)
assert.Contains(t, err.Error(), "could not retrieve local root key for key ID provided")
}