Пример #1
0
func TestExportNonRootKeyReencrypt(t *testing.T) {
	gun := "docker.com/notary"

	// Temporary directory where test files will be created
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	defer os.RemoveAll(tempBaseDir)
	require.NoError(t, err, "failed to create a temporary directory: %s", err)

	fileStore, err := trustmanager.NewKeyFileStore(tempBaseDir, oldPassphraseRetriever)
	cs := NewCryptoService(fileStore)
	pubKey, err := cs.Create(data.CanonicalSnapshotRole, gun, data.ECDSAKey)
	require.NoError(t, err)

	snapshotKeyID := pubKey.ID()

	tempKeyFile, err := ioutil.TempFile("", "notary-test-export-")
	tempKeyFilePath := tempKeyFile.Name()
	defer os.Remove(tempKeyFilePath)

	err = cs.ExportKeyReencrypt(tempKeyFile, snapshotKeyID, newPassphraseRetriever)
	require.NoError(t, err)
	tempKeyFile.Close()

	// Create new repo to test import
	tempBaseDir2, err := ioutil.TempDir("", "notary-test-")
	defer os.RemoveAll(tempBaseDir2)
	require.NoError(t, err, "failed to create a temporary directory: %s", err)

	fileStore2, err := trustmanager.NewKeyFileStore(tempBaseDir2, newPassphraseRetriever)
	cs2 := NewCryptoService(fileStore2)

	keyReader, err := os.Open(tempKeyFilePath)
	require.NoError(t, err, "could not open key file")

	pemBytes, err := ioutil.ReadAll(keyReader)
	require.NoError(t, err, "could not read key file")

	// Convert to a data.PrivateKey, potentially decrypting the key, and add it to the cryptoservice
	privKey, _, err := trustmanager.GetPasswdDecryptBytes(newPassphraseRetriever, pemBytes, "", "imported "+data.CanonicalSnapshotRole)
	require.NoError(t, err)
	err = cs2.AddKey(data.CanonicalSnapshotRole, gun, privKey)
	require.NoError(t, err)
	keyReader.Close()

	// Look for repo's snapshot key in repo2
	// There should be a file named after the key ID of the snapshot key we
	// imported.
	snapshotKeyFilename := snapshotKeyID + ".key"
	_, err = os.Stat(filepath.Join(tempBaseDir2, notary.PrivDir, notary.NonRootKeysSubdir, "docker.com/notary", snapshotKeyFilename))
	require.NoError(t, err, "missing snapshot key")

	// Should be able to unlock the root key with the new password
	key, alias, err := cs2.GetPrivateKey(snapshotKeyID)
	require.NoError(t, err, "could not unlock snapshot key")
	require.Equal(t, data.CanonicalSnapshotRole, alias)
	require.Equal(t, snapshotKeyID, key.ID())
}
Пример #2
0
func TestImportExportNonRootKey(t *testing.T) {
	gun := "docker.com/notary"

	// Temporary directory where test files will be created
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	defer os.RemoveAll(tempBaseDir)
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)

	fileStore, err := trustmanager.NewKeyFileStore(tempBaseDir, oldPassphraseRetriever)
	cs := NewCryptoService(gun, fileStore)
	pubKey, err := cs.Create(data.CanonicalTargetsRole, data.ECDSAKey)
	assert.NoError(t, err)

	targetsKeyID := pubKey.ID()

	tempKeyFile, err := ioutil.TempFile("", "notary-test-export-")
	tempKeyFilePath := tempKeyFile.Name()
	defer os.Remove(tempKeyFilePath)

	err = cs.ExportKey(tempKeyFile, targetsKeyID, data.CanonicalTargetsRole)
	assert.NoError(t, err)
	tempKeyFile.Close()

	// Create new repo to test import
	tempBaseDir2, err := ioutil.TempDir("", "notary-test-")
	defer os.RemoveAll(tempBaseDir2)
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)

	fileStore2, err := trustmanager.NewKeyFileStore(tempBaseDir2, oldPassphraseRetriever)
	cs2 := NewCryptoService(gun, fileStore2)

	keyReader, err := os.Open(tempKeyFilePath)
	assert.NoError(t, err, "could not open key file")

	pemBytes, err := ioutil.ReadAll(keyReader)
	assert.NoError(t, err, "could not read key file")

	err = cs2.ImportRoleKey(pemBytes, data.CanonicalTargetsRole, oldPassphraseRetriever)
	assert.NoError(t, err)
	keyReader.Close()

	// Look for repo's targets key in repo2
	// There should be a file named after the key ID of the targets key we
	// imported.
	targetsKeyFilename := targetsKeyID + ".key"
	_, err = os.Stat(filepath.Join(tempBaseDir2, "private", "tuf_keys", "docker.com/notary", targetsKeyFilename))
	assert.NoError(t, err, "missing targets key")

	// Check that the key is the same
	key, alias, err := cs2.GetPrivateKey(targetsKeyID)
	assert.NoError(t, err, "could not unlock targets key")
	assert.Equal(t, data.CanonicalTargetsRole, alias)
	assert.Equal(t, targetsKeyID, key.ID())
}
Пример #3
0
func TestImportExportRootKeyReencrypt(t *testing.T) {
	gun := "docker.com/notary"

	// Temporary directory where test files will be created
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	defer os.RemoveAll(tempBaseDir)
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)

	fileStore, err := trustmanager.NewKeyFileStore(tempBaseDir, oldPassphraseRetriever)
	cs := NewCryptoService(gun, fileStore)
	pubKey, err := cs.Create(data.CanonicalRootRole, data.ECDSAKey)
	assert.NoError(t, err)

	rootKeyID := pubKey.ID()

	tempKeyFile, err := ioutil.TempFile("", "notary-test-export-")
	tempKeyFilePath := tempKeyFile.Name()
	defer os.Remove(tempKeyFilePath)

	err = cs.ExportRootKeyReencrypt(tempKeyFile, rootKeyID, newPassphraseRetriever)
	assert.NoError(t, err)
	tempKeyFile.Close()

	// Create new repo to test import
	tempBaseDir2, err := ioutil.TempDir("", "notary-test-")
	defer os.RemoveAll(tempBaseDir2)
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)

	fileStore2, err := trustmanager.NewKeyFileStore(tempBaseDir2, newPassphraseRetriever)
	cs2 := NewCryptoService(gun, fileStore2)

	keyReader, err := os.Open(tempKeyFilePath)
	assert.NoError(t, err, "could not open key file")

	err = cs2.ImportRootKey(keyReader)
	assert.NoError(t, err)
	keyReader.Close()

	// Look for repo's root key in repo2
	// There should be a file named after the key ID of the root key we
	// imported.
	rootKeyFilename := rootKeyID + ".key"
	_, err = os.Stat(filepath.Join(tempBaseDir2, "private", "root_keys", rootKeyFilename))
	assert.NoError(t, err, "missing root key")

	// Should be able to unlock the root key with the new password
	key, alias, err := cs2.GetPrivateKey(rootKeyID)
	assert.NoError(t, err, "could not unlock root key")
	assert.Equal(t, "root", alias)
	assert.Equal(t, rootKeyID, key.ID())
}
Пример #4
0
// ExportKeysByGUN exports all keys associated with a specified GUN to an
// io.Writer in zip format. passphraseRetriever is used to select new passphrases to use to
// encrypt the keys.
func (cs *CryptoService) ExportKeysByGUN(dest io.Writer, gun string, passphraseRetriever passphrase.Retriever) error {
	tempBaseDir, err := ioutil.TempDir("", "notary-key-export-")
	defer os.RemoveAll(tempBaseDir)

	// Create temporary keystore to use as a staging area
	tempKeyStore, err := trustmanager.NewKeyFileStore(tempBaseDir, passphraseRetriever)
	if err != nil {
		return err
	}

	for _, ks := range cs.keyStores {
		if err := moveKeysByGUN(ks, tempKeyStore, gun); err != nil {
			return err
		}
	}

	zipWriter := zip.NewWriter(dest)

	if len(tempKeyStore.ListKeys()) == 0 {
		return ErrNoKeysFoundForGUN
	}

	if err := addKeysToArchive(zipWriter, tempKeyStore); err != nil {
		return err
	}

	zipWriter.Close()

	return nil
}
// Export all the keys of a cryptoservice to a zipfile, and import it into a
// new cryptoService, and return that new cryptoService
func importExportedZip(t *testing.T, original *CryptoService,
	ret passphrase.Retriever, gun string) (*CryptoService, string) {

	// Temporary directory where test files will be created
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)

	ks, err := trustmanager.NewKeyFileStore(tempBaseDir, ret)
	assert.NoError(t, err)
	var cs *CryptoService

	// export keys
	zipFile, err := ioutil.TempFile("", "notary-test-zipFile")
	defer os.RemoveAll(zipFile.Name())
	if gun != "" {
		original.ExportKeysByGUN(zipFile, gun, ret)
		cs = NewCryptoService(gun, ks)
	} else {
		original.ExportAllKeys(zipFile, ret)
		cs = NewCryptoService(original.gun, ks)
	}
	zipFile.Close()

	// import keys into the cryptoservice now
	zipReader, err := zip.OpenReader(zipFile.Name())
	assert.NoError(t, err)
	defer zipReader.Close()

	assert.NoError(t, cs.ImportKeysZip(zipReader.Reader))
	return cs, tempBaseDir
}
Пример #6
0
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)
	}
	return []trustmanager.KeyStore{fileKeyStore}, nil
}
// Zips up the keys in the old repo, and assert that we can import it and use
// said keys.  The 0.1 exported format is just a zip file of all the keys
func TestImport0Dot1Zip(t *testing.T) {
	ks, ret, _ := get0Dot1(t)

	zipFile, err := ioutil.TempFile("", "notary-test-zipFile")
	defer os.RemoveAll(zipFile.Name())
	zipWriter := zip.NewWriter(zipFile)
	require.NoError(t, err)
	require.NoError(t, addKeysToArchive(zipWriter, ks))
	zipWriter.Close()
	zipFile.Close()

	origKeys := make(map[string]string)
	for keyID, keyInfo := range ks.ListKeys() {
		origKeys[keyID] = keyInfo.Role
	}
	require.Len(t, origKeys, 3)

	// now import the zip file into a new cryptoservice

	tempDir, err := ioutil.TempDir("", "notary-test-import")
	defer os.RemoveAll(tempDir)
	require.NoError(t, err)

	ks, err = trustmanager.NewKeyFileStore(tempDir, ret)
	require.NoError(t, err)
	cs := NewCryptoService(ks)

	zipReader, err := zip.OpenReader(zipFile.Name())
	require.NoError(t, err)
	defer zipReader.Close()

	require.NoError(t, cs.ImportKeysZip(zipReader.Reader, passphrase.ConstantRetriever("randompass")))
	assertHasKeys(t, cs, origKeys)
}
Пример #8
0
// 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) (*NotaryRepository, error) {
	trustDir := filepath.Join(baseDir, trustDir)
	rootKeysDir := filepath.Join(baseDir, rootKeysDir)

	privKeyStore, err := trustmanager.NewKeyFileStore(filepath.Join(baseDir, privDir))
	if err != nil {
		return nil, err
	}

	signer := signed.NewSigner(NewCryptoService(gun, privKeyStore))

	nRepo := &NotaryRepository{
		Gun:          gun,
		baseDir:      baseDir,
		baseURL:      baseURL,
		tufRepoPath:  filepath.Join(baseDir, tufDir, gun),
		signer:       signer,
		privKeyStore: privKeyStore,
	}

	if err := nRepo.loadKeys(trustDir, rootKeysDir); err != nil {
		return nil, err
	}

	return nRepo, nil
}
Пример #9
0
func (k *keyCommander) getKeyStores(
	config *viper.Viper, withHardware, hardwareBackup bool) ([]trustmanager.KeyStore, error) {

	retriever := k.getRetriever()

	directory := config.GetString("trust_dir")
	fileKeyStore, err := trustmanager.NewKeyFileStore(directory, retriever)
	if err != nil {
		return nil, fmt.Errorf(
			"Failed to create private key store in directory: %s", directory)
	}

	ks := []trustmanager.KeyStore{fileKeyStore}

	if withHardware {
		var yubiStore trustmanager.KeyStore
		if hardwareBackup {
			yubiStore, err = getYubiStore(fileKeyStore, retriever)
		} else {
			yubiStore, err = getYubiStore(nil, retriever)
		}
		if err == nil && yubiStore != nil {
			// Note that the order is important, since we want to prioritize
			// the yubikey store
			ks = []trustmanager.KeyStore{yubiStore, fileKeyStore}
		}
	}

	return ks, nil
}
Пример #10
0
// ExportKeysByGUN exports all keys associated with a specified GUN to an
// io.Writer in zip format. passphraseRetriever is used to select new passphrases to use to
// encrypt the keys.
func (km *KeyStoreManager) ExportKeysByGUN(dest io.Writer, gun string, passphraseRetriever passphrase.Retriever) error {
	tempBaseDir, err := ioutil.TempDir("", "notary-key-export-")
	defer os.RemoveAll(tempBaseDir)

	privNonRootKeysSubdir := filepath.Join(privDir, nonRootKeysSubdir)

	// Create temporary keystore to use as a staging area
	tempNonRootKeysPath := filepath.Join(tempBaseDir, privNonRootKeysSubdir)
	tempNonRootKeyStore, err := trustmanager.NewKeyFileStore(tempNonRootKeysPath, passphraseRetriever)
	if err != nil {
		return err
	}

	if err := moveKeysByGUN(km.nonRootKeyStore, tempNonRootKeyStore, gun); err != nil {
		return err
	}

	zipWriter := zip.NewWriter(dest)

	if len(tempNonRootKeyStore.ListKeys()) == 0 {
		return ErrNoKeysFoundForGUN
	}

	if err := addKeysToArchive(zipWriter, tempNonRootKeyStore, privNonRootKeysSubdir); err != nil {
		return err
	}

	zipWriter.Close()

	return nil
}
Пример #11
0
// ExportRootKeyReencrypt exports the specified root key to an io.Writer in
// PEM format. The key is reencrypted with a new passphrase.
func (cs *CryptoService) ExportRootKeyReencrypt(dest io.Writer, keyID string, newPassphraseRetriever passphrase.Retriever) error {
	privateKey, role, err := cs.GetPrivateKey(keyID)
	if err != nil {
		return err
	}

	// Create temporary keystore to use as a staging area
	tempBaseDir, err := ioutil.TempDir("", "notary-key-export-")
	defer os.RemoveAll(tempBaseDir)

	tempKeyStore, err := trustmanager.NewKeyFileStore(tempBaseDir, newPassphraseRetriever)
	if err != nil {
		return err
	}

	err = tempKeyStore.AddKey(keyID, role, privateKey)
	if err != nil {
		return err
	}

	pemBytes, err := tempKeyStore.ExportKey(keyID)
	if err != nil {
		return err
	}
	nBytes, err := dest.Write(pemBytes)
	if err != nil {
		return err
	}
	if nBytes != len(pemBytes) {
		return errors.New("Unable to finish writing exported key.")
	}
	return nil
}
Пример #12
0
// ExportAllKeys exports all keys to an io.Writer in zip format.
// newPassphraseRetriever will be used to obtain passphrases to use to encrypt the existing keys.
func (cs *CryptoService) ExportAllKeys(dest io.Writer, newPassphraseRetriever notary.PassRetriever) error {
	tempBaseDir, err := ioutil.TempDir("", "notary-key-export-")
	defer os.RemoveAll(tempBaseDir)

	// Create temporary keystore to use as a staging area
	tempKeyStore, err := trustmanager.NewKeyFileStore(tempBaseDir, newPassphraseRetriever)
	if err != nil {
		return err
	}

	for _, ks := range cs.keyStores {
		if err := moveKeys(ks, tempKeyStore); err != nil {
			return err
		}
	}

	zipWriter := zip.NewWriter(dest)

	if err := addKeysToArchive(zipWriter, tempKeyStore); err != nil {
		return err
	}

	zipWriter.Close()

	return nil
}
// ExportRootKeyReencrypt exports the specified root key to an io.Writer in
// PEM format. The key is reencrypted with a new passphrase.
func (km *KeyStoreManager) ExportRootKeyReencrypt(dest io.Writer, keyID string, newPassphraseRetriever passphrase.Retriever) error {
	privateKey, alias, err := km.rootKeyStore.GetKey(keyID)
	if err != nil {
		return err
	}

	// Create temporary keystore to use as a staging area
	tempBaseDir, err := ioutil.TempDir("", "notary-key-export-")
	defer os.RemoveAll(tempBaseDir)

	privRootKeysSubdir := filepath.Join(privDir, rootKeysSubdir)
	tempRootKeysPath := filepath.Join(tempBaseDir, privRootKeysSubdir)
	tempRootKeyStore, err := trustmanager.NewKeyFileStore(tempRootKeysPath, newPassphraseRetriever)
	if err != nil {
		return err
	}

	err = tempRootKeyStore.AddKey(keyID, alias, privateKey)
	if err != nil {
		return err
	}

	pemBytes, err := tempRootKeyStore.Get(keyID + "_" + alias)
	if err != nil {
		return err
	}

	_, err = dest.Write(pemBytes)
	return err
}
// Zips up the keys in the old repo, and assert that we can import it and use
// said keys.  The 0.1 exported format is just a zip file of all the keys
func TestImport0Dot1Zip(t *testing.T) {
	ks, ret, gun := get0Dot1(t)

	zipFile, err := ioutil.TempFile("", "notary-test-zipFile")
	defer os.RemoveAll(zipFile.Name())
	zipWriter := zip.NewWriter(zipFile)
	assert.NoError(t, err)
	assert.NoError(t, addKeysToArchive(zipWriter, ks))
	zipWriter.Close()
	zipFile.Close()

	origKeys := ks.ListKeys()
	assert.Len(t, origKeys, 3)

	// now import the zip file into a new cryptoservice

	tempDir, err := ioutil.TempDir("", "notary-test-import")
	defer os.RemoveAll(tempDir)
	assert.NoError(t, err)

	ks, err = trustmanager.NewKeyFileStore(tempDir, ret)
	assert.NoError(t, err)
	cs := NewCryptoService(gun, ks)

	zipReader, err := zip.OpenReader(zipFile.Name())
	assert.NoError(t, err)
	defer zipReader.Close()

	assert.NoError(t, cs.ImportKeysZip(zipReader.Reader))
	assertHasKeys(t, cs, origKeys)
}
Пример #15
0
// Generates a Manager in a temporary directory and returns the
// manager and certificates for two keys which have been added to the keystore.
// Also returns the temporary directory so it can be cleaned up.
func filestoreWithTwoCerts(t *testing.T, gun, keyAlg string) (
	string, *Manager, *cryptoservice.CryptoService, []*x509.Certificate) {
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)

	fileKeyStore, err := trustmanager.NewKeyFileStore(tempBaseDir, passphraseRetriever)
	assert.NoError(t, err)

	cryptoService := cryptoservice.NewCryptoService(gun, fileKeyStore)

	// Create a Manager
	certManager, err := NewManager(tempBaseDir)
	assert.NoError(t, err)

	certificates := make([]*x509.Certificate, 2)
	for i := 0; i < 2; i++ {
		pubKey, err := cryptoService.Create("root", keyAlg)
		assert.NoError(t, err)

		key, _, err := fileKeyStore.GetKey(pubKey.ID())
		assert.NoError(t, err)

		cert, err := cryptoservice.GenerateTestingCertificate(key.CryptoSigner(), gun)
		assert.NoError(t, err)

		certificates[i] = cert
	}
	return tempBaseDir, certManager, cryptoService, certificates
}
Пример #16
0
// ExportAllKeys exports all keys to an io.Writer in zip format.
// newPassphraseRetriever will be used to obtain passphrases to use to encrypt the existing keys.
func (km *KeyStoreManager) ExportAllKeys(dest io.Writer, newPassphraseRetriever passphrase.Retriever) error {
	tempBaseDir, err := ioutil.TempDir("", "notary-key-export-")
	defer os.RemoveAll(tempBaseDir)

	// Create temporary keystore to use as a staging area
	tempKeysPath := filepath.Join(tempBaseDir, privDir)
	tempKeyStore, err := trustmanager.NewKeyFileStore(tempKeysPath, newPassphraseRetriever)
	if err != nil {
		return err
	}

	if err := moveKeys(km.KeyStore, tempKeyStore); err != nil {
		return err
	}

	zipWriter := zip.NewWriter(dest)

	if err := addKeysToArchive(zipWriter, tempKeyStore, privDir); err != nil {
		return err
	}

	zipWriter.Close()

	return nil
}
Пример #17
0
// NewKeyStoreManager returns an initialized KeyStoreManager, or an error
// if it fails to create the KeyFileStores or load certificates
func NewKeyStoreManager(baseDir string) (*KeyStoreManager, error) {
	nonRootKeysPath := filepath.Join(baseDir, privDir, nonRootKeysSubdir)
	nonRootKeyStore, err := trustmanager.NewKeyFileStore(nonRootKeysPath)
	if err != nil {
		return nil, err
	}

	// Load the keystore that will hold all of our encrypted Root Private Keys
	rootKeysPath := filepath.Join(baseDir, privDir, rootKeysSubdir)
	rootKeyStore, err := trustmanager.NewKeyFileStore(rootKeysPath)
	if err != nil {
		return nil, err
	}

	trustPath := filepath.Join(baseDir, trustDir)

	// Load all CAs that aren't expired and don't use SHA1
	trustedCAStore, err := trustmanager.NewX509FilteredFileStore(trustPath, func(cert *x509.Certificate) bool {
		return cert.IsCA && cert.BasicConstraintsValid && cert.SubjectKeyId != nil &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return nil, err
	}

	// Load all individual (non-CA) certificates that aren't expired and don't use SHA1
	trustedCertificateStore, err := trustmanager.NewX509FilteredFileStore(trustPath, func(cert *x509.Certificate) bool {
		return !cert.IsCA &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return nil, err
	}

	return &KeyStoreManager{
		rootKeyStore:            rootKeyStore,
		nonRootKeyStore:         nonRootKeyStore,
		trustedCAStore:          trustedCAStore,
		trustedCertificateStore: trustedCertificateStore,
	}, nil
}
func get0Dot1(t *testing.T) (*trustmanager.KeyFileStore, passphrase.Retriever, string) {
	gun := "docker.io/notary0.1/samplerepo"
	ret := passphrase.ConstantRetriever("randompass")

	// produce the zip file
	ks, err := trustmanager.NewKeyFileStore("../fixtures/compatibility/notary0.1", ret)
	assert.NoError(t, err)

	return ks, ret, gun
}
Пример #19
0
// 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)
	}

	return repositoryFromKeystores(baseDir, gun, baseURL, rt,
		[]trustmanager.KeyStore{fileKeyStore}, trustPinning)
}
Пример #20
0
// reads data from the repository in order to fake data being served via
// the ServeMux.
func fakeServerData(t *testing.T, repo *NotaryRepository, mux *http.ServeMux) {
	tempKey, err := data.UnmarshalPrivateKey([]byte(timestampECDSAKeyJSON))
	assert.NoError(t, err)

	savedTUFRepo := repo.tufRepo // in case this is overwritten

	fileStore, err := trustmanager.NewKeyFileStore(repo.baseDir, passphraseRetriever)
	assert.NoError(t, err)
	fileStore.AddKey(
		filepath.Join(filepath.FromSlash(repo.gun), tempKey.ID()),
		"nonroot", tempKey)

	rootJSONFile := filepath.Join(repo.baseDir, "tuf",
		filepath.FromSlash(repo.gun), "metadata", "root.json")
	rootFileBytes, err := ioutil.ReadFile(rootJSONFile)

	signedTargets, err := savedTUFRepo.SignTargets(
		"targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)

	signedSnapshot, err := savedTUFRepo.SignSnapshot(
		data.DefaultExpires("snapshot"))
	assert.NoError(t, err)

	signedTimestamp, err := savedTUFRepo.SignTimestamp(
		data.DefaultExpires("timestamp"))
	assert.NoError(t, err)

	mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/root.json",
		func(w http.ResponseWriter, r *http.Request) {
			assert.NoError(t, err)
			fmt.Fprint(w, string(rootFileBytes))
		})

	mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/timestamp.json",
		func(w http.ResponseWriter, r *http.Request) {
			timestampJSON, _ := json.Marshal(signedTimestamp)
			fmt.Fprint(w, string(timestampJSON))
		})

	mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/snapshot.json",
		func(w http.ResponseWriter, r *http.Request) {
			snapshotJSON, _ := json.Marshal(signedSnapshot)
			fmt.Fprint(w, string(snapshotJSON))
		})

	mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/targets.json",
		func(w http.ResponseWriter, r *http.Request) {
			targetsJSON, _ := json.Marshal(signedTargets)
			fmt.Fprint(w, string(targetsJSON))
		})
}
Пример #21
0
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
}
Пример #22
0
// keyPassphraseChange changes the passphrase for a root key's private key based on ID
func (k *keyCommander) keyPassphraseChange(cmd *cobra.Command, args []string) error {
	if len(args) < 1 {
		cmd.Usage()
		return fmt.Errorf("must specify the key ID of the key to change the passphrase of")
	}

	config, err := k.configGetter()
	if err != nil {
		return err
	}
	ks, err := k.getKeyStores(config, true)
	if err != nil {
		return err
	}

	keyID := args[0]

	// This is an invalid ID
	if len(keyID) != notary.Sha256HexSize {
		return fmt.Errorf("invalid key ID provided: %s", keyID)
	}

	// Find the key's GUN by ID, in case it is a non-root key
	var keyGUN string
	for _, store := range ks {
		for keypath := range store.ListKeys() {
			if filepath.Base(keypath) == keyID {
				keyGUN = filepath.Dir(keypath)
			}
		}
	}
	cs := cryptoservice.NewCryptoService(keyGUN, ks...)
	privKey, role, err := cs.GetPrivateKey(keyID)
	if err != nil {
		return fmt.Errorf("could not retrieve local key for key ID provided: %s", keyID)
	}

	// Must use a different passphrase retriever to avoid caching the
	// unlocking passphrase and reusing that.
	passChangeRetriever := k.getRetriever()
	keyStore, err := trustmanager.NewKeyFileStore(config.GetString("trust_dir"), passChangeRetriever)
	err = keyStore.AddKey(filepath.Join(keyGUN, keyID), role, privKey)
	if err != nil {
		return err
	}

	cmd.Println("")
	cmd.Printf("Successfully updated passphrase for key ID: %s", keyID)
	cmd.Println("")
	return nil
}
Пример #23
0
// ExportAllKeys exports all keys to an io.Writer in zip format.
// outputPassphrase is the new passphrase to use to encrypt the existing keys.
// If blank, the keys will not be encrypted. Note that keys which are already
// encrypted are not re-encrypted. They will be included in the zip with their
// original encryption.
func (km *KeyStoreManager) ExportAllKeys(dest io.Writer, outputPassphrase string) error {
	tempBaseDir, err := ioutil.TempDir("", "notary-key-export-")
	defer os.RemoveAll(tempBaseDir)

	// Create temporary keystores to use as a staging area
	tempNonRootKeysPath := filepath.Join(tempBaseDir, privDir, nonRootKeysSubdir)
	tempNonRootKeyStore, err := trustmanager.NewKeyFileStore(tempNonRootKeysPath)
	if err != nil {
		return err
	}

	tempRootKeysPath := filepath.Join(tempBaseDir, privDir, rootKeysSubdir)
	tempRootKeyStore, err := trustmanager.NewKeyFileStore(tempRootKeysPath)
	if err != nil {
		return err
	}

	if err := moveKeysWithNewPassphrase(km.rootKeyStore, tempRootKeyStore, outputPassphrase); err != nil {
		return err
	}
	if err := moveKeysWithNewPassphrase(km.nonRootKeyStore, tempNonRootKeyStore, outputPassphrase); err != nil {
		return err
	}

	zipWriter := zip.NewWriter(dest)

	if err := addKeysToArchive(zipWriter, tempRootKeyStore, tempBaseDir); err != nil {
		return err
	}
	if err := addKeysToArchive(zipWriter, tempNonRootKeyStore, tempBaseDir); err != nil {
		return err
	}

	zipWriter.Close()

	return nil
}
Пример #24
0
// 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) (
	*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.NewYubiKeyStore(fileKeyStore, retriever)
	if yubiKeyStore != nil {
		keyStores = append(keyStores, yubiKeyStore)
	}

	return repositoryFromKeystores(baseDir, gun, baseURL, rt, keyStores)
}
Пример #25
0
// 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 notary.PassRetriever, 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)
}
Пример #26
0
func getKeyStores(cmd *cobra.Command, directory string,
	ret passphrase.Retriever, withHardware bool) []trustmanager.KeyStore {

	fileKeyStore, err := trustmanager.NewKeyFileStore(directory, ret)
	if err != nil {
		fatalf("Failed to create private key store in directory: %s", directory)
	}

	ks := []trustmanager.KeyStore{fileKeyStore}

	if withHardware {
		yubiStore, err := getYubiKeyStore(fileKeyStore, ret)
		if err == nil && yubiStore != nil {
			// Note that the order is important, since we want to prioritize
			// the yubikey store
			ks = []trustmanager.KeyStore{yubiStore, fileKeyStore}
		}
	}

	return ks
}
Пример #27
0
// 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) (*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)
	}

	keyStoreManager, err := keystoremanager.NewKeyStoreManager(baseDir)
	yubiKeyStore, _ := yubikey.NewYubiKeyStore(fileKeyStore, retriever)
	var cryptoService signed.CryptoService
	if yubiKeyStore == nil {
		cryptoService = cryptoservice.NewCryptoService(gun, fileKeyStore)
	} else {
		cryptoService = cryptoservice.NewCryptoService(gun, yubiKeyStore, fileKeyStore)
	}

	nRepo := &NotaryRepository{
		gun:             gun,
		baseDir:         baseDir,
		baseURL:         baseURL,
		tufRepoPath:     filepath.Join(baseDir, tufDir, filepath.FromSlash(gun)),
		CryptoService:   cryptoService,
		roundTrip:       rt,
		KeyStoreManager: keyStoreManager,
	}

	fileStore, err := store.NewFilesystemStore(
		nRepo.tufRepoPath,
		"metadata",
		"json",
		"",
	)
	if err != nil {
		return nil, err
	}
	nRepo.fileStore = fileStore

	return nRepo, nil
}
func TestImportExport0Dot1GUNKeys(t *testing.T) {
	ks, ret, gun := get0Dot1(t)

	// remove root from expected key list, because root is not exported when
	// we export by gun
	expectedKeys := make(map[string]string)
	for keyID, role := range ks.ListKeys() {
		if role != data.CanonicalRootRole {
			expectedKeys[keyID] = role
		}
	}

	// make some other temp directory to create new keys in
	tempDir, err := ioutil.TempDir("", "notary-tests-keystore")
	defer os.RemoveAll(tempDir)
	assert.NoError(t, err)

	otherKS, err := trustmanager.NewKeyFileStore(tempDir, ret)
	assert.NoError(t, err)
	cs := NewCryptoService("some/other/gun", otherKS, ks)

	// create a keys that is not of the same GUN, and be sure it's in this
	// CryptoService
	otherPubKey, err := cs.Create(data.CanonicalTargetsRole, data.ECDSAKey)
	assert.NoError(t, err)

	k, _, err := cs.GetPrivateKey(otherPubKey.ID())
	assert.NoError(t, err)
	assert.NotNil(t, k)

	// export/import, and ensure that the other-gun key is not in the new
	// CryptoService
	newCS, tempDir := importExportedZip(t, cs, ret, gun)
	defer os.RemoveAll(tempDir)

	assertHasKeys(t, newCS, expectedKeys)

	_, _, err = newCS.GetPrivateKey(otherPubKey.ID())
	assert.Error(t, err)
}
Пример #29
0
// NewKeyStoreManager returns an initialized KeyStoreManager, or an error
// if it fails to create the KeyFileStores or load certificates
func NewKeyStoreManager(baseDir string, passphraseRetriever passphrase.Retriever) (*KeyStoreManager, error) {
	keysPath := filepath.Join(baseDir, privDir)
	keyStore, err := trustmanager.NewKeyFileStore(keysPath, passphraseRetriever)
	if err != nil {
		return nil, err
	}

	trustPath := filepath.Join(baseDir, trustDir)

	// Load all CAs that aren't expired and don't use SHA1
	trustedCAStore, err := trustmanager.NewX509FilteredFileStore(trustPath, func(cert *x509.Certificate) bool {
		return cert.IsCA && cert.BasicConstraintsValid && cert.SubjectKeyId != nil &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return nil, err
	}

	// Load all individual (non-CA) certificates that aren't expired and don't use SHA1
	trustedCertificateStore, err := trustmanager.NewX509FilteredFileStore(trustPath, func(cert *x509.Certificate) bool {
		return !cert.IsCA &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return nil, err
	}

	return &KeyStoreManager{
		KeyStore:                keyStore,
		trustedCAStore:          trustedCAStore,
		trustedCertificateStore: trustedCertificateStore,
	}, nil
}
Пример #30
0
func (r *NotaryRepository) loadKeys(trustDir, rootKeysDir string) error {
	// Load all CAs that aren't expired and don't use SHA1
	caStore, err := trustmanager.NewX509FilteredFileStore(trustDir, func(cert *x509.Certificate) bool {
		return cert.IsCA && cert.BasicConstraintsValid && cert.SubjectKeyId != nil &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return err
	}

	// Load all individual (non-CA) certificates that aren't expired and don't use SHA1
	certificateStore, err := trustmanager.NewX509FilteredFileStore(trustDir, func(cert *x509.Certificate) bool {
		return !cert.IsCA &&
			time.Now().Before(cert.NotAfter) &&
			cert.SignatureAlgorithm != x509.SHA1WithRSA &&
			cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
			cert.SignatureAlgorithm != x509.ECDSAWithSHA1
	})
	if err != nil {
		return err
	}

	// Load the keystore that will hold all of our encrypted Root Private Keys
	rootKeyStore, err := trustmanager.NewKeyFileStore(rootKeysDir)
	if err != nil {
		return err
	}

	r.caStore = caStore
	r.certificateStore = certificateStore
	r.rootKeyStore = rootKeyStore

	return nil
}