func init() { yubikey.SetYubikeyKeyMode(yubikey.KeymodeNone) regRetriver := passphrase.PromptRetriever() _retriever := func(k, a string, c bool, n int) (string, bool, error) { if k == "Yubikey" { return regRetriver(k, a, c, n) } return testPassphrase, false, nil } // best effort at removing keys here, so nil is fine s, err := yubikey.NewYubiStore(nil, _retriever) if err != nil { for k := range s.ListKeys() { s.RemoveKey(k) } } NewNotaryCommand = func() *cobra.Command { commander := ¬aryCommander{ getRetriever: func() notary.PassRetriever { return _retriever }, } return commander.GetCommand() } }
// Per-test set up deletes all keys on the yubikey func setUp(t *testing.T) { //we're just removing keys here, so nil is fine s, err := yubikey.NewYubiStore(nil, _retriever) require.NoError(t, err) for k := range s.ListKeys() { err := s.RemoveKey(k) require.NoError(t, err) } }
// clear out all keys func init() { yubikey.SetYubikeyKeyMode(0) if !yubikey.IsAccessible() { return } store, err := yubikey.NewYubiStore(nil, nil) if err == nil { for k := range store.ListKeys() { store.RemoveKey(k) } } }
// ensures that the root is actually on the yubikey - this makes sure the // commands are hooked up to interact with the yubikey, rather than right files // on disk func verifyRootKeyOnHardware(t *testing.T, rootKeyID string) { // do not bother verifying if there is no yubikey available if yubikey.IsAccessible() { // //we're just getting keys here, so nil is fine s, err := yubikey.NewYubiStore(nil, _retriever) require.NoError(t, err) privKey, role, err := s.GetKey(rootKeyID) require.NoError(t, err) require.NotNil(t, privKey) require.Equal(t, data.CanonicalRootRole, role) } }
func getKeyStores(baseDir string, retriever notary.PassRetriever) ([]trustmanager.KeyStore, error) { fileKeyStore, err := trustmanager.NewKeyFileStore(baseDir, retriever) if err != nil { return nil, fmt.Errorf("failed to create private key store in directory: %s", baseDir) } keyStores := []trustmanager.KeyStore{fileKeyStore} yubiKeyStore, _ := yubikey.NewYubiStore(fileKeyStore, retriever) if yubiKeyStore != nil { keyStores = []trustmanager.KeyStore{yubiKeyStore, fileKeyStore} } return keyStores, nil }
// NewNotaryRepository is a helper method that returns a new notary repository. // It takes the base directory under where all the trust files will be stored // (usually ~/.docker/trust/). func NewNotaryRepository(baseDir, gun, baseURL string, rt http.RoundTripper, retriever passphrase.Retriever, trustPinning trustpinning.TrustPinConfig) ( *NotaryRepository, error) { fileKeyStore, err := trustmanager.NewKeyFileStore(baseDir, retriever) if err != nil { return nil, fmt.Errorf("failed to create private key store in directory: %s", baseDir) } keyStores := []trustmanager.KeyStore{fileKeyStore} yubiKeyStore, _ := yubikey.NewYubiStore(fileKeyStore, retriever) if yubiKeyStore != nil { keyStores = []trustmanager.KeyStore{yubiKeyStore, fileKeyStore} } return repositoryFromKeystores(baseDir, gun, baseURL, rt, keyStores, trustPinning) }
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 getYubiStore(fileKeyStore trustmanager.KeyStore, ret notary.PassRetriever) (trustmanager.KeyStore, error) { return yubikey.NewYubiStore(fileKeyStore, ret) }