// NewKeyFileStore returns a new KeyFileStore creating a private directory to // hold the keys. func NewKeyFileStore(baseDir string, p notary.PassRetriever) (*GenericKeyStore, error) { fileStore, err := store.NewPrivateKeyFileStorage(baseDir, notary.KeyExtension) if err != nil { return nil, err } return NewGenericKeyStore(fileStore, p), nil }
func getImporters(baseDir string, _ notary.PassRetriever) ([]utils.Importer, error) { fileStore, err := store.NewPrivateKeyFileStorage(baseDir, notary.KeyExtension) if err != nil { return nil, err } return []utils.Importer{fileStore}, nil }
func TestExportKeysByID(t *testing.T) { setUp(t) tempBaseDir, err := ioutil.TempDir("", "notary-test-") require.NoError(t, err) defer os.RemoveAll(tempBaseDir) output, err := ioutil.TempFile("", "notary-test-import-") require.NoError(t, err) defer os.RemoveAll(output.Name()) k := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", tempBaseDir) return v, nil }, } k.outFile = output.Name() err = output.Close() // close so export can open require.NoError(t, err) k.exportKeyIDs = []string{"one", "three"} b := &pem.Block{} b.Bytes = make([]byte, 1000) rand.Read(b.Bytes) b2 := &pem.Block{} b2.Bytes = make([]byte, 1000) rand.Read(b2.Bytes) c := &pem.Block{} c.Bytes = make([]byte, 1000) rand.Read(c.Bytes) bBytes := pem.EncodeToMemory(b) b2Bytes := pem.EncodeToMemory(b2) cBytes := pem.EncodeToMemory(c) fileStore, err := store.NewPrivateKeyFileStorage(tempBaseDir, notary.KeyExtension) require.NoError(t, err) err = fileStore.Set("one", bBytes) require.NoError(t, err) err = fileStore.Set("two", b2Bytes) require.NoError(t, err) err = fileStore.Set("three", cBytes) require.NoError(t, err) err = k.exportKeys(&cobra.Command{}, nil) require.NoError(t, err) outRes, err := ioutil.ReadFile(k.outFile) require.NoError(t, err) block, rest := pem.Decode(outRes) require.Equal(t, b.Bytes, block.Bytes) require.Equal(t, "one", block.Headers["path"]) block, rest = pem.Decode(rest) require.Equal(t, c.Bytes, block.Bytes) require.Equal(t, "three", block.Headers["path"]) require.Len(t, rest, 0) }
func (k *keyCommander) exportKeys(cmd *cobra.Command, args []string) error { var ( out io.Writer err error ) if len(args) > 0 { cmd.Usage() return fmt.Errorf("export does not take any positional arguments") } config, err := k.configGetter() if err != nil { return err } if k.outFile == "" { out = cmd.Out() } else { f, err := os.OpenFile(k.outFile, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, notary.PrivExecPerms) if err != nil { return err } defer f.Close() out = f } directory := config.GetString("trust_dir") fileStore, err := store.NewPrivateKeyFileStorage(directory, notary.KeyExtension) if err != nil { return err } if len(k.exportGUNs) > 0 { if len(k.exportKeyIDs) > 0 { return fmt.Errorf("Only the --gun or --key flag may be provided, not a mix of the two flags") } for _, gun := range k.exportGUNs { return utils.ExportKeysByGUN(out, fileStore, gun) } } else if len(k.exportKeyIDs) > 0 { return utils.ExportKeysByID(out, fileStore, k.exportKeyIDs) } // export everything keys := fileStore.ListFiles() for _, k := range keys { err := utils.ExportKeys(out, fileStore, k) if err != nil { return err } } return nil }
func getImporters(baseDir string, ret notary.PassRetriever) ([]utils.Importer, error) { var importers []utils.Importer if yubikey.IsAccessible() { yubiStore, err := getYubiStore(nil, ret) if err == nil { importers = append( importers, yubikey.NewImporter(yubiStore, ret), ) } } fileStore, err := store.NewPrivateKeyFileStorage(baseDir, notary.KeyExtension) if err == nil { importers = append( importers, fileStore, ) } else if len(importers) == 0 { return nil, err // couldn't initialize any stores } return importers, nil }
func TestImportWithYubikey(t *testing.T) { if !yubikey.IsAccessible() { t.Skip("Must have Yubikey access.") } setUp(t) tempBaseDir, err := ioutil.TempDir("", "notary-test-") require.NoError(t, err) defer os.RemoveAll(tempBaseDir) input, err := ioutil.TempFile("", "notary-test-import-") require.NoError(t, err) defer os.RemoveAll(input.Name()) k := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", tempBaseDir) return v, nil }, getRetriever: func() notary.PassRetriever { return passphrase.ConstantRetriever("pass") }, } memStore := store.NewMemoryStore(nil) ks := trustmanager.NewGenericKeyStore(memStore, k.getRetriever()) cs := cryptoservice.NewCryptoService(ks) pubK, err := cs.Create(data.CanonicalRootRole, "ankh", data.ECDSAKey) require.NoError(t, err) bID := pubK.ID() // need to check presence in yubikey later bytes, err := memStore.Get(pubK.ID()) require.NoError(t, err) b, _ := pem.Decode(bytes) b.Headers["path"] = "ankh" require.Equal(t, "root", b.Headers["role"]) pubK, err = cs.Create(data.CanonicalTargetsRole, "morpork", data.ECDSAKey) require.NoError(t, err) cID := pubK.ID() bytes, err = memStore.Get(pubK.ID()) require.NoError(t, err) c, _ := pem.Decode(bytes) c.Headers["path"] = "morpork" bBytes := pem.EncodeToMemory(b) cBytes := pem.EncodeToMemory(c) input.Write(bBytes) input.Write(cBytes) file := input.Name() err = input.Close() // close so import can open require.NoError(t, err) err = k.importKeys(&cobra.Command{}, []string{file}) require.NoError(t, err) yks, err := yubikey.NewYubiStore(nil, k.getRetriever()) require.NoError(t, err) _, _, err = yks.GetKey(bID) require.NoError(t, err) _, _, err = yks.GetKey(cID) require.Error(t, err) // c is non-root, should not be in yubikey fileStore, err := store.NewPrivateKeyFileStorage(tempBaseDir, notary.KeyExtension) require.NoError(t, err) _, err = fileStore.Get("ankh") require.Error(t, err) // b should only be in yubikey, not in filestore cResult, err := fileStore.Get("morpork") require.NoError(t, err) block, rest := pem.Decode(cResult) require.Equal(t, c.Bytes, block.Bytes) require.Len(t, rest, 0) }
func TestExportKeysByGUN(t *testing.T) { setUp(t) tempBaseDir, err := ioutil.TempDir("", "notary-test-") require.NoError(t, err) defer os.RemoveAll(tempBaseDir) output, err := ioutil.TempFile("", "notary-test-import-") require.NoError(t, err) defer os.RemoveAll(output.Name()) k := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", tempBaseDir) return v, nil }, } k.outFile = output.Name() err = output.Close() // close so export can open require.NoError(t, err) k.exportGUNs = []string{"ankh"} keyHeaders := make(map[string]string) keyHeaders["gun"] = "ankh" keyHeaders["role"] = "snapshot" b := &pem.Block{ Headers: keyHeaders, } b.Bytes = make([]byte, 1000) rand.Read(b.Bytes) b2 := &pem.Block{ Headers: keyHeaders, } b2.Bytes = make([]byte, 1000) rand.Read(b2.Bytes) otherHeaders := make(map[string]string) otherHeaders["gun"] = "morpork" otherHeaders["role"] = "snapshot" c := &pem.Block{ Headers: otherHeaders, } c.Bytes = make([]byte, 1000) rand.Read(c.Bytes) bBytes := pem.EncodeToMemory(b) b2Bytes := pem.EncodeToMemory(b2) cBytes := pem.EncodeToMemory(c) fileStore, err := store.NewPrivateKeyFileStorage(tempBaseDir, notary.KeyExtension) require.NoError(t, err) // we have to manually prepend the NonRootKeysSubdir because // KeyStore would be expected to do this for us. err = fileStore.Set( "12345", bBytes, ) require.NoError(t, err) err = fileStore.Set( "23456", b2Bytes, ) require.NoError(t, err) err = fileStore.Set( "34567", cBytes, ) require.NoError(t, err) err = k.exportKeys(&cobra.Command{}, nil) require.NoError(t, err) outRes, err := ioutil.ReadFile(k.outFile) require.NoError(t, err) block, rest := pem.Decode(outRes) require.Equal(t, b.Bytes, block.Bytes) require.Equal( t, "12345", block.Headers["path"], ) block, rest = pem.Decode(rest) require.Equal(t, b2.Bytes, block.Bytes) require.Equal( t, "23456", block.Headers["path"], ) require.Len(t, rest, 0) }
func TestExportKeys(t *testing.T) { setUp(t) tempBaseDir, err := ioutil.TempDir("", "notary-test-") require.NoError(t, err) defer os.RemoveAll(tempBaseDir) output, err := ioutil.TempFile("", "notary-test-import-") require.NoError(t, err) defer os.RemoveAll(output.Name()) k := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", tempBaseDir) return v, nil }, } k.outFile = output.Name() err = output.Close() // close so export can open require.NoError(t, err) keyHeaders := make(map[string]string) keyHeaders["gun"] = "discworld" b := &pem.Block{ Headers: keyHeaders, } b.Bytes = make([]byte, 1000) rand.Read(b.Bytes) c := &pem.Block{ Headers: keyHeaders, } c.Bytes = make([]byte, 1000) rand.Read(c.Bytes) bBytes := pem.EncodeToMemory(b) cBytes := pem.EncodeToMemory(c) require.NoError(t, err) fileStore, err := store.NewPrivateKeyFileStorage(tempBaseDir, notary.KeyExtension) require.NoError(t, err) err = fileStore.Set("ankh", bBytes) require.NoError(t, err) err = fileStore.Set("morpork", cBytes) require.NoError(t, err) err = k.exportKeys(&cobra.Command{}, nil) require.NoError(t, err) outRes, err := ioutil.ReadFile(k.outFile) require.NoError(t, err) block, rest := pem.Decode(outRes) require.Equal(t, b.Bytes, block.Bytes) require.Equal(t, "ankh", block.Headers["path"]) require.Equal(t, "discworld", block.Headers["gun"]) block, rest = pem.Decode(rest) require.Equal(t, c.Bytes, block.Bytes) require.Equal(t, "morpork", block.Headers["path"]) require.Equal(t, "discworld", block.Headers["gun"]) require.Len(t, rest, 0) // test no outFile uses stdout (or our replace buffer) k.outFile = "" cmd := &cobra.Command{} out := bytes.NewBuffer(make([]byte, 0, 3000)) cmd.SetOutput(out) err = k.exportKeys(cmd, nil) require.NoError(t, err) bufOut, err := ioutil.ReadAll(out) require.NoError(t, err) require.Equal(t, outRes, bufOut) // should be identical output to file earlier }
func TestExportImportKeysNoYubikey(t *testing.T) { setUp(t) exportTempDir, err := ioutil.TempDir("", "notary-test-") require.NoError(t, err) defer os.RemoveAll(exportTempDir) tempfile, err := ioutil.TempFile("", "notary-test-import-") require.NoError(t, err) tempfile.Close() defer os.RemoveAll(tempfile.Name()) exportCommander := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", exportTempDir) return v, nil }, getRetriever: func() notary.PassRetriever { return passphrase.ConstantRetriever("pass") }, } exportCommander.outFile = tempfile.Name() exportStore, err := store.NewPrivateKeyFileStorage(exportTempDir, notary.KeyExtension) require.NoError(t, err) ks := trustmanager.NewGenericKeyStore(exportStore, exportCommander.getRetriever()) cs := cryptoservice.NewCryptoService(ks) pubK, err := cs.Create(data.CanonicalRootRole, "ankh", data.ECDSAKey) require.NoError(t, err) bID := pubK.ID() bOrigBytes, err := exportStore.Get(bID) require.NoError(t, err) bOrig, _ := pem.Decode(bOrigBytes) pubK, err = cs.Create(data.CanonicalTargetsRole, "morpork", data.ECDSAKey) require.NoError(t, err) cID := pubK.ID() cOrigBytes, err := exportStore.Get(cID) require.NoError(t, err) cOrig, _ := pem.Decode(cOrigBytes) exportCommander.exportKeys(&cobra.Command{}, nil) importTempDir, err := ioutil.TempDir("", "notary-test-") require.NoError(t, err) defer os.RemoveAll(importTempDir) importCommander := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", importTempDir) return v, nil }, getRetriever: func() notary.PassRetriever { return passphrase.ConstantRetriever("pass") }, } err = importCommander.importKeys(&cobra.Command{}, []string{tempfile.Name()}) require.NoError(t, err) importStore, err := store.NewPrivateKeyFileStorage(importTempDir, notary.KeyExtension) require.NoError(t, err) bResult, err := importStore.Get(bID) require.NoError(t, err) cResult, err := importStore.Get(cID) require.NoError(t, err) block, rest := pem.Decode(bResult) require.Equal(t, bOrig.Bytes, block.Bytes) require.Len(t, rest, 0) block, rest = pem.Decode(cResult) require.Equal(t, cOrig.Bytes, block.Bytes) require.Len(t, rest, 0) }
func TestImportKeysNoYubikey(t *testing.T) { setUp(t) tempBaseDir, err := ioutil.TempDir("", "notary-test-") require.NoError(t, err) defer os.RemoveAll(tempBaseDir) input, err := ioutil.TempFile("", "notary-test-import-") require.NoError(t, err) defer os.RemoveAll(input.Name()) k := &keyCommander{ configGetter: func() (*viper.Viper, error) { v := viper.New() v.SetDefault("trust_dir", tempBaseDir) return v, nil }, getRetriever: func() notary.PassRetriever { return passphrase.ConstantRetriever("pass") }, } memStore := store.NewMemoryStore(nil) ks := trustmanager.NewGenericKeyStore(memStore, k.getRetriever()) cs := cryptoservice.NewCryptoService(ks) pubK, err := cs.Create(data.CanonicalRootRole, "ankh", data.ECDSAKey) require.NoError(t, err) bytes, err := memStore.Get(pubK.ID()) require.NoError(t, err) b, _ := pem.Decode(bytes) b.Headers["path"] = "ankh" pubK, err = cs.Create(data.CanonicalTargetsRole, "morpork", data.ECDSAKey) require.NoError(t, err) bytes, err = memStore.Get(pubK.ID()) require.NoError(t, err) c, _ := pem.Decode(bytes) c.Headers["path"] = "morpork" bBytes := pem.EncodeToMemory(b) cBytes := pem.EncodeToMemory(c) input.Write(bBytes) input.Write(cBytes) file := input.Name() err = input.Close() // close so import can open require.NoError(t, err) err = k.importKeys(&cobra.Command{}, []string{file}) require.NoError(t, err) fileStore, err := store.NewPrivateKeyFileStorage(tempBaseDir, notary.KeyExtension) require.NoError(t, err) bResult, err := fileStore.Get("ankh") require.NoError(t, err) cResult, err := fileStore.Get("morpork") require.NoError(t, err) block, rest := pem.Decode(bResult) require.Equal(t, b.Bytes, block.Bytes) require.Len(t, rest, 0) block, rest = pem.Decode(cResult) require.Equal(t, c.Bytes, block.Bytes) require.Len(t, rest, 0) }