docs: add docs for new trust subcommands

Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 4e797eaa04
Component: cli
This commit is contained in:
Kyle Spiers
2017-10-30 16:53:54 +01:00
committed by Riyaz Faizullabhoy
parent d01ed820ce
commit 222f56b982
6 changed files with 520 additions and 69 deletions
@@ -23,9 +23,9 @@ func newKeyGenerateCommand(dockerCli command.Streams) *cobra.Command {
cmd := &cobra.Command{
Use: "key-generate NAME [NAME...]",
Short: "Generate and load a signing key-pair",
Args: cli.RequiresMinArgs(1),
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return setupPassphraseAndGenerateKeys(dockerCli, args)
return setupPassphraseAndGenerateKeys(dockerCli, args[0])
},
}
return cmd
@@ -36,56 +36,41 @@ var validKeyName = regexp.MustCompile(`^[a-zA-Z0-9\_]+[a-zA-Z0-9\_\-]*$`).MatchS
// validate that all of the key names are unique and are alphanumeric + _ + -
// and that we do not already have public key files in the current dir on disk
func validateKeyArgs(keyNames []string, cwdPath string) error {
uniqueKeyNames := map[string]struct{}{}
for _, keyName := range keyNames {
if !validKeyName(keyName) {
return fmt.Errorf("key name \"%s\" must not contain special characters", keyName)
}
func validateKeyArgs(keyName string, cwdPath string) error {
if !validKeyName(keyName) {
return fmt.Errorf("key name \"%s\" must not contain special characters", keyName)
}
if _, ok := uniqueKeyNames[keyName]; ok {
return fmt.Errorf("key names must be unique, found duplicate key name: \"%s\"", keyName)
}
uniqueKeyNames[keyName] = struct{}{}
pubKeyFileName := keyName + ".pub"
if _, err := os.Stat(filepath.Join(cwdPath, pubKeyFileName)); err == nil {
return fmt.Errorf("public key file already exists: \"%s\"", pubKeyFileName)
}
pubKeyFileName := keyName + ".pub"
if _, err := os.Stat(filepath.Join(cwdPath, pubKeyFileName)); err == nil {
return fmt.Errorf("public key file already exists: \"%s\"", pubKeyFileName)
}
return nil
}
func setupPassphraseAndGenerateKeys(streams command.Streams, keyNames []string) error {
func setupPassphraseAndGenerateKeys(streams command.Streams, keyName string) error {
// always use a fresh passphrase for each key generation
freshPassRetGetter := func() notary.PassRetriever { return trust.GetPassphraseRetriever(streams.In(), streams.Out()) }
cwd, err := os.Getwd()
if err != nil {
return err
}
return generateKeys(streams, keyNames, cwd, freshPassRetGetter)
return validateAndGenerateKey(streams, keyName, cwd, freshPassRetGetter)
}
func generateKeys(streams command.Streams, keyNames []string, workingDir string, passphraseGetter func() notary.PassRetriever) error {
var genKeyErrs []string
if err := validateKeyArgs(keyNames, workingDir); err != nil {
func validateAndGenerateKey(streams command.Streams, keyName string, workingDir string, passphraseGetter func() notary.PassRetriever) error {
if err := validateKeyArgs(keyName, workingDir); err != nil {
return err
}
for _, keyName := range keyNames {
fmt.Fprintf(streams.Out(), "\nGenerating key for %s...\n", keyName)
freshPassRet := passphraseGetter()
if err := generateKey(keyName, workingDir, trust.GetTrustDirectory(), freshPassRet); err != nil {
fmt.Fprintf(streams.Out(), err.Error())
genKeyErrs = append(genKeyErrs, keyName)
} else {
pubFileName := strings.Join([]string{keyName, "pub"}, ".")
fmt.Fprintf(streams.Out(), "Successfully generated and loaded private key. Corresponding public key available: %s\n", pubFileName)
}
fmt.Fprintf(streams.Out(), "\nGenerating key for %s...\n", keyName)
freshPassRet := passphraseGetter()
if err := generateKey(keyName, workingDir, trust.GetTrustDirectory(), freshPassRet); err != nil {
fmt.Fprintf(streams.Out(), err.Error())
return fmt.Errorf("Error generating key for: %s", keyName)
}
pubFileName := strings.Join([]string{keyName, "pub"}, ".")
fmt.Fprintf(streams.Out(), "Successfully generated and loaded private key. Corresponding public key available: %s\n", pubFileName)
if len(genKeyErrs) > 0 {
return fmt.Errorf("Error generating keys for: %s", strings.Join(genKeyErrs, ", "))
}
return nil
}
@@ -24,9 +24,15 @@ func TestTrustKeyGenerateErrors(t *testing.T) {
}{
{
name: "not-enough-args",
expectedError: "requires at least 1 argument",
expectedError: "requires exactly 1 argument",
},
{
name: "too-many-args",
args: []string{"key-1", "key-2"},
expectedError: "requires exactly 1 argument",
},
}
tmpDir, err := ioutil.TempDir("", "docker-key-generate-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
@@ -106,48 +112,19 @@ func TestValidateKeyArgs(t *testing.T) {
assert.NoError(t, err)
defer os.RemoveAll(pubKeyCWD)
err = validateKeyArgs([]string{"a", "b", "C_123", "key-name"}, pubKeyCWD)
err = validateKeyArgs("a", pubKeyCWD)
assert.NoError(t, err)
err = validateKeyArgs([]string{"a", "a"}, pubKeyCWD)
assert.Error(t, err)
assert.Equal(t, err.Error(), "key names must be unique, found duplicate key name: \"a\"")
err = validateKeyArgs([]string{"a/b"}, pubKeyCWD)
err = validateKeyArgs("a/b", pubKeyCWD)
assert.Error(t, err)
assert.Equal(t, err.Error(), "key name \"a/b\" must not contain special characters")
err = validateKeyArgs([]string{"-"}, pubKeyCWD)
err = validateKeyArgs("-", pubKeyCWD)
assert.Error(t, err)
assert.Equal(t, err.Error(), "key name \"-\" must not contain special characters")
assert.NoError(t, ioutil.WriteFile(filepath.Join(pubKeyCWD, "a.pub"), []byte("abc"), notary.PrivExecPerms))
err = validateKeyArgs([]string{"a"}, pubKeyCWD)
err = validateKeyArgs("a", pubKeyCWD)
assert.Error(t, err)
assert.Equal(t, err.Error(), "public key file already exists: \"a.pub\"")
}
func TestGenerateMultipleKeysOutput(t *testing.T) {
pubKeyCWD, err := ioutil.TempDir("", "pub-keys-")
assert.NoError(t, err)
defer os.RemoveAll(pubKeyCWD)
passwd := "password"
cannedPasswordRetriever := func() notary.PassRetriever { return passphrase.ConstantRetriever(passwd) }
cli := test.NewFakeCli(&fakeClient{})
assert.NoError(t, generateKeys(cli, []string{"alice", "bob", "charlie"}, pubKeyCWD, cannedPasswordRetriever))
// Check the stdout prints:
assert.Contains(t, cli.OutBuffer().String(), "\nGenerating key for alice...\n")
assert.Contains(t, cli.OutBuffer().String(), "Successfully generated and loaded private key. Corresponding public key available: alice.pub\n")
assert.Contains(t, cli.OutBuffer().String(), "\nGenerating key for bob...\n")
assert.Contains(t, cli.OutBuffer().String(), "Successfully generated and loaded private key. Corresponding public key available: bob.pub\n")
assert.Contains(t, cli.OutBuffer().String(), "\nGenerating key for charlie...\n")
assert.Contains(t, cli.OutBuffer().String(), "Successfully generated and loaded private key. Corresponding public key available: charlie.pub\n")
// Check that we have three key files:
cwdKeyFiles, err := ioutil.ReadDir(pubKeyCWD)
assert.NoError(t, err)
assert.Len(t, cwdKeyFiles, 3)
}