github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/trust/key_generate_test.go (about) 1 package trust 2 3 import ( 4 "encoding/pem" 5 "fmt" 6 "io" 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/v3/assert" 18 is "gotest.tools/v3/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 config.SetDir(t.TempDir()) 39 40 for _, tc := range testCases { 41 cli := test.NewFakeCli(&fakeClient{}) 42 cmd := newKeyGenerateCommand(cli) 43 cmd.SetArgs(tc.args) 44 cmd.SetOut(io.Discard) 45 assert.ErrorContains(t, cmd.Execute(), tc.expectedError) 46 } 47 } 48 49 func TestGenerateKeySuccess(t *testing.T) { 50 pubKeyCWD := t.TempDir() 51 privKeyStorageDir := t.TempDir() 52 53 passwd := "password" 54 cannedPasswordRetriever := passphrase.ConstantRetriever(passwd) 55 // generate a single key 56 keyName := "alice" 57 privKeyFileStore, err := trustmanager.NewKeyFileStore(privKeyStorageDir, cannedPasswordRetriever) 58 assert.NilError(t, err) 59 60 pubKeyPEM, err := generateKeyAndOutputPubPEM(keyName, privKeyFileStore) 61 assert.NilError(t, err) 62 63 assert.Check(t, is.Equal(keyName, pubKeyPEM.Headers["role"])) 64 // the default GUN is empty 65 assert.Check(t, is.Equal("", pubKeyPEM.Headers["gun"])) 66 // assert public key header 67 assert.Check(t, is.Equal("PUBLIC KEY", pubKeyPEM.Type)) 68 69 // check that an appropriate ~/<trust_dir>/private/<key_id>.key file exists 70 expectedPrivKeyDir := filepath.Join(privKeyStorageDir, notary.PrivDir) 71 _, err = os.Stat(expectedPrivKeyDir) 72 assert.NilError(t, err) 73 74 keyFiles, err := os.ReadDir(expectedPrivKeyDir) 75 assert.NilError(t, err) 76 assert.Check(t, is.Len(keyFiles, 1)) 77 privKeyFilePath := filepath.Join(expectedPrivKeyDir, keyFiles[0].Name()) 78 79 // verify the key content 80 privFrom, _ := os.OpenFile(privKeyFilePath, os.O_RDONLY, notary.PrivExecPerms) 81 defer privFrom.Close() 82 fromBytes, _ := io.ReadAll(privFrom) 83 privKeyPEM, _ := pem.Decode(fromBytes) 84 assert.Check(t, is.Equal(keyName, privKeyPEM.Headers["role"])) 85 // the default GUN is empty 86 assert.Check(t, is.Equal("", privKeyPEM.Headers["gun"])) 87 // assert encrypted header 88 assert.Check(t, is.Equal("ENCRYPTED PRIVATE KEY", privKeyPEM.Type)) 89 // check that the passphrase matches 90 _, err = tufutils.ParsePKCS8ToTufKey(privKeyPEM.Bytes, []byte(passwd)) 91 assert.NilError(t, err) 92 93 // check that the public key exists at the correct path if we use the helper: 94 returnedPath, err := writePubKeyPEMToDir(pubKeyPEM, keyName, pubKeyCWD) 95 assert.NilError(t, err) 96 expectedPubKeyPath := filepath.Join(pubKeyCWD, keyName+".pub") 97 assert.Check(t, is.Equal(returnedPath, expectedPubKeyPath)) 98 _, err = os.Stat(expectedPubKeyPath) 99 assert.NilError(t, err) 100 // check that the public key is the only file output in CWD 101 cwdKeyFiles, err := os.ReadDir(pubKeyCWD) 102 assert.NilError(t, err) 103 assert.Check(t, is.Len(cwdKeyFiles, 1)) 104 } 105 106 func TestValidateKeyArgs(t *testing.T) { 107 pubKeyCWD := t.TempDir() 108 109 err := validateKeyArgs("a", pubKeyCWD) 110 assert.NilError(t, err) 111 112 err = validateKeyArgs("a/b", pubKeyCWD) 113 assert.Error(t, err, "key name \"a/b\" must start with lowercase alphanumeric characters and can include \"-\" or \"_\" after the first character") 114 115 err = validateKeyArgs("-", pubKeyCWD) 116 assert.Error(t, err, "key name \"-\" must start with lowercase alphanumeric characters and can include \"-\" or \"_\" after the first character") 117 118 assert.NilError(t, os.WriteFile(filepath.Join(pubKeyCWD, "a.pub"), []byte("abc"), notary.PrivExecPerms)) 119 err = validateKeyArgs("a", pubKeyCWD) 120 assert.Error(t, err, fmt.Sprintf("public key file already exists: \"%s\"", filepath.Join(pubKeyCWD, "a.pub"))) 121 122 err = validateKeyArgs("a", "/random/dir/") 123 assert.Error(t, err, "public key path does not exist: \"/random/dir/\"") 124 }