github.com/itscaro/cli@v0.0.0-20190705081621-c9db0fe93829/cli/command/trust/key_generate_test.go (about)

     1  package trust
     2  
     3  import (
     4  	"encoding/pem"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  
    11  	"github.com/docker/cli/cli/config"
    12  	"github.com/docker/cli/internal/test"
    13  	"github.com/theupdateframework/notary"
    14  	"github.com/theupdateframework/notary/passphrase"
    15  	"github.com/theupdateframework/notary/trustmanager"
    16  	tufutils "github.com/theupdateframework/notary/tuf/utils"
    17  	"gotest.tools/assert"
    18  	is "gotest.tools/assert/cmp"
    19  )
    20  
    21  func TestTrustKeyGenerateErrors(t *testing.T) {
    22  	testCases := []struct {
    23  		name          string
    24  		args          []string
    25  		expectedError string
    26  	}{
    27  		{
    28  			name:          "not-enough-args",
    29  			expectedError: "requires exactly 1 argument",
    30  		},
    31  		{
    32  			name:          "too-many-args",
    33  			args:          []string{"key-1", "key-2"},
    34  			expectedError: "requires exactly 1 argument",
    35  		},
    36  	}
    37  
    38  	tmpDir, err := ioutil.TempDir("", "docker-key-generate-test-")
    39  	assert.NilError(t, err)
    40  	defer os.RemoveAll(tmpDir)
    41  	config.SetDir(tmpDir)
    42  
    43  	for _, tc := range testCases {
    44  		cli := test.NewFakeCli(&fakeClient{})
    45  		cmd := newKeyGenerateCommand(cli)
    46  		cmd.SetArgs(tc.args)
    47  		cmd.SetOutput(ioutil.Discard)
    48  		assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
    49  	}
    50  }
    51  
    52  func TestGenerateKeySuccess(t *testing.T) {
    53  	pubKeyCWD, err := ioutil.TempDir("", "pub-keys-")
    54  	assert.NilError(t, err)
    55  	defer os.RemoveAll(pubKeyCWD)
    56  
    57  	privKeyStorageDir, err := ioutil.TempDir("", "priv-keys-")
    58  	assert.NilError(t, err)
    59  	defer os.RemoveAll(privKeyStorageDir)
    60  
    61  	passwd := "password"
    62  	cannedPasswordRetriever := passphrase.ConstantRetriever(passwd)
    63  	// generate a single key
    64  	keyName := "alice"
    65  	privKeyFileStore, err := trustmanager.NewKeyFileStore(privKeyStorageDir, cannedPasswordRetriever)
    66  	assert.NilError(t, err)
    67  
    68  	pubKeyPEM, err := generateKeyAndOutputPubPEM(keyName, privKeyFileStore)
    69  	assert.NilError(t, err)
    70  
    71  	assert.Check(t, is.Equal(keyName, pubKeyPEM.Headers["role"]))
    72  	// the default GUN is empty
    73  	assert.Check(t, is.Equal("", pubKeyPEM.Headers["gun"]))
    74  	// assert public key header
    75  	assert.Check(t, is.Equal("PUBLIC KEY", pubKeyPEM.Type))
    76  
    77  	// check that an appropriate ~/<trust_dir>/private/<key_id>.key file exists
    78  	expectedPrivKeyDir := filepath.Join(privKeyStorageDir, notary.PrivDir)
    79  	_, err = os.Stat(expectedPrivKeyDir)
    80  	assert.NilError(t, err)
    81  
    82  	keyFiles, err := ioutil.ReadDir(expectedPrivKeyDir)
    83  	assert.NilError(t, err)
    84  	assert.Check(t, is.Len(keyFiles, 1))
    85  	privKeyFilePath := filepath.Join(expectedPrivKeyDir, keyFiles[0].Name())
    86  
    87  	// verify the key content
    88  	privFrom, _ := os.OpenFile(privKeyFilePath, os.O_RDONLY, notary.PrivExecPerms)
    89  	defer privFrom.Close()
    90  	fromBytes, _ := ioutil.ReadAll(privFrom)
    91  	privKeyPEM, _ := pem.Decode(fromBytes)
    92  	assert.Check(t, is.Equal(keyName, privKeyPEM.Headers["role"]))
    93  	// the default GUN is empty
    94  	assert.Check(t, is.Equal("", privKeyPEM.Headers["gun"]))
    95  	// assert encrypted header
    96  	assert.Check(t, is.Equal("ENCRYPTED PRIVATE KEY", privKeyPEM.Type))
    97  	// check that the passphrase matches
    98  	_, err = tufutils.ParsePKCS8ToTufKey(privKeyPEM.Bytes, []byte(passwd))
    99  	assert.NilError(t, err)
   100  
   101  	// check that the public key exists at the correct path if we use the helper:
   102  	returnedPath, err := writePubKeyPEMToDir(pubKeyPEM, keyName, pubKeyCWD)
   103  	assert.NilError(t, err)
   104  	expectedPubKeyPath := filepath.Join(pubKeyCWD, keyName+".pub")
   105  	assert.Check(t, is.Equal(returnedPath, expectedPubKeyPath))
   106  	_, err = os.Stat(expectedPubKeyPath)
   107  	assert.NilError(t, err)
   108  	// check that the public key is the only file output in CWD
   109  	cwdKeyFiles, err := ioutil.ReadDir(pubKeyCWD)
   110  	assert.NilError(t, err)
   111  	assert.Check(t, is.Len(cwdKeyFiles, 1))
   112  }
   113  
   114  func TestValidateKeyArgs(t *testing.T) {
   115  	pubKeyCWD, err := ioutil.TempDir("", "pub-keys-")
   116  	assert.NilError(t, err)
   117  	defer os.RemoveAll(pubKeyCWD)
   118  
   119  	err = validateKeyArgs("a", pubKeyCWD)
   120  	assert.NilError(t, err)
   121  
   122  	err = validateKeyArgs("a/b", pubKeyCWD)
   123  	assert.Error(t, err, "key name \"a/b\" must start with lowercase alphanumeric characters and can include \"-\" or \"_\" after the first character")
   124  
   125  	err = validateKeyArgs("-", pubKeyCWD)
   126  	assert.Error(t, err, "key name \"-\" must start with lowercase alphanumeric characters and can include \"-\" or \"_\" after the first character")
   127  
   128  	assert.NilError(t, ioutil.WriteFile(filepath.Join(pubKeyCWD, "a.pub"), []byte("abc"), notary.PrivExecPerms))
   129  	err = validateKeyArgs("a", pubKeyCWD)
   130  	assert.Error(t, err, fmt.Sprintf("public key file already exists: \"%s\"", filepath.Join(pubKeyCWD, "a.pub")))
   131  
   132  	err = validateKeyArgs("a", "/random/dir/")
   133  	assert.Error(t, err, "public key path does not exist: \"/random/dir/\"")
   134  }