Beispiel #1
0
// Non-roles and delegation keys can't be rotated with the command line
func TestRotateKeyInvalidRoles(t *testing.T) {
	setUp(t)
	invalids := []string{
		"notevenARole",
		"targets/a",
	}
	for _, role := range invalids {
		for _, serverManaged := range []bool{true, false} {
			k := &keyCommander{
				configGetter:           func() (*viper.Viper, error) { return viper.New(), nil },
				getRetriever:           func() notary.PassRetriever { return passphrase.ConstantRetriever("pass") },
				rotateKeyRole:          role,
				rotateKeyServerManaged: serverManaged,
			}
			commands := []string{"gun", role}
			if serverManaged {
				commands = append(commands, "-r")
			}
			err := k.keysRotate(&cobra.Command{}, commands)
			require.Error(t, err)
			require.Contains(t, err.Error(),
				fmt.Sprintf("does not currently permit rotating the %s key", role))
		}
	}
}
// 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)
}
// 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 notary.PassRetriever, gun string) (*CryptoService, string) {

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

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

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

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

	require.NoError(t, cs.ImportKeysZip(zipReader.Reader, passphrase.ConstantRetriever("randompass")))
	return cs, tempBaseDir
}
Beispiel #4
0
// The command line uses NotaryRepository's RotateKey - this is just testing
// that the correct config variables are passed for the client to request a key
// from the remote server.
func TestRotateKeyRemoteServerManagesKey(t *testing.T) {
	// Temporary directory where test files will be created
	tempBaseDir, err := ioutil.TempDir("/tmp", "notary-test-")
	defer os.RemoveAll(tempBaseDir)
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)
	gun := "docker.com/notary"

	ret := passphrase.ConstantRetriever("pass")

	ts, initialKeys := setUpRepo(t, tempBaseDir, gun, ret)
	defer ts.Close()

	k := &keyCommander{
		configGetter: func() (*viper.Viper, error) {
			v := viper.New()
			v.SetDefault("trust_dir", tempBaseDir)
			v.SetDefault("remote_server.url", ts.URL)
			return v, nil
		},
		getRetriever:           func() passphrase.Retriever { return ret },
		rotateKeyRole:          data.CanonicalSnapshotRole,
		rotateKeyServerManaged: true,
	}
	err = k.keysRotate(&cobra.Command{}, []string{gun})
	assert.NoError(t, err)

	repo, err := client.NewNotaryRepository(tempBaseDir, gun, ts.URL, nil, ret)
	assert.NoError(t, err, "error creating repo: %s", err)

	cl, err := repo.GetChangelist()
	assert.NoError(t, err, "unable to get changelist: %v", err)
	assert.Len(t, cl.List(), 1)
	// no keys have been created, since a remote key was specified
	assert.Equal(t, initialKeys, repo.CryptoService.ListAllKeys())
}
Beispiel #5
0
// Given a list of key stores, the keys should be pretty-printed with their
// roles, locations, IDs, and guns first in sorted order in the key store
func TestPrettyPrintRootAndSigningKeys(t *testing.T) {
	ret := passphrase.ConstantRetriever("pass")
	keyStores := []trustmanager.KeyStore{
		trustmanager.NewKeyMemoryStore(ret),
		&otherMemoryStore{KeyMemoryStore: *trustmanager.NewKeyMemoryStore(ret)},
	}

	longNameShortened := "..." + strings.Repeat("z", 37)

	keys := make([]data.PrivateKey, 4)
	for i := 0; i < 4; i++ {
		key, err := trustmanager.GenerateED25519Key(rand.Reader)
		require.NoError(t, err)
		keys[i] = key
	}

	root := data.CanonicalRootRole

	// add keys to the key stores
	require.NoError(t, keyStores[0].AddKey(trustmanager.KeyInfo{Role: root, Gun: ""}, keys[0]))
	require.NoError(t, keyStores[1].AddKey(trustmanager.KeyInfo{Role: root, Gun: ""}, keys[0]))
	require.NoError(t, keyStores[0].AddKey(trustmanager.KeyInfo{Role: data.CanonicalTargetsRole, Gun: strings.Repeat("/a", 30)}, keys[1]))
	require.NoError(t, keyStores[1].AddKey(trustmanager.KeyInfo{Role: data.CanonicalSnapshotRole, Gun: "short/gun"}, keys[1]))
	require.NoError(t, keyStores[0].AddKey(trustmanager.KeyInfo{Role: "targets/a", Gun: ""}, keys[3]))
	require.NoError(t, keyStores[0].AddKey(trustmanager.KeyInfo{Role: "invalidRole", Gun: ""}, keys[2]))

	expected := [][]string{
		// root always comes first
		{root, keys[0].ID(), keyStores[0].Name()},
		{root, keys[0].ID(), longNameShortened},
		// these have no gun, so they come first
		{"invalidRole", keys[2].ID(), keyStores[0].Name()},
		{"targets/a", keys[3].ID(), keyStores[0].Name()},
		// these have guns, and are sorted then by guns
		{data.CanonicalTargetsRole, "..." + strings.Repeat("/a", 11), keys[1].ID(), keyStores[0].Name()},
		{data.CanonicalSnapshotRole, "short/gun", keys[1].ID(), longNameShortened},
	}

	var b bytes.Buffer
	prettyPrintKeys(keyStores, &b)
	text, err := ioutil.ReadAll(&b)
	require.NoError(t, err)

	lines := strings.Split(strings.TrimSpace(string(text)), "\n")
	require.Len(t, lines, len(expected)+2)

	// starts with headers
	require.True(t, reflect.DeepEqual(strings.Fields(lines[0]),
		[]string{"ROLE", "GUN", "KEY", "ID", "LOCATION"}))
	require.Equal(t, "----", lines[1][:4])

	for i, line := range lines[2:] {
		// we are purposely not putting spaces in test data so easier to split
		splitted := strings.Fields(line)
		for j, v := range splitted {
			require.Equal(t, expected[i][j], strings.TrimSpace(v))
		}
	}
}
func init() {
	NewNotaryCommand = func() *cobra.Command {
		commander := &notaryCommander{
			getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
		}
		return commander.GetCommand()
	}
}
// We can read and publish from notary0.1 repos
func Test0Dot1RepoFormat(t *testing.T) {
	// make a temporary directory and copy the fixture into it, since updating
	// and publishing will modify the files
	tmpDir, err := ioutil.TempDir("", "notary-backwards-compat-test")
	defer os.RemoveAll(tmpDir)
	require.NoError(t, err)
	require.NoError(t, recursiveCopy("../fixtures/compatibility/notary0.1", tmpDir))

	gun := "docker.com/notary0.1/samplerepo"
	passwd := "randompass"

	ts := fullTestServer(t)
	defer ts.Close()

	repo, err := NewFileCachedNotaryRepository(tmpDir, gun, ts.URL, http.DefaultTransport,
		passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
	require.NoError(t, err, "error creating repo: %s", err)

	// targets should have 1 target, and it should be readable offline
	targets, err := repo.ListTargets()
	require.NoError(t, err)
	require.Len(t, targets, 1)
	require.Equal(t, "LICENSE", targets[0].Name)

	// ok, now that everything has been loaded, verify that the fixture is valid
	requireValidFixture(t, repo)

	// delete the timestamp metadata, since the server will ignore the uploaded
	// one and try to create a new one from scratch, which will be the wrong version
	require.NoError(t, repo.cache.Remove(data.CanonicalTimestampRole))

	// rotate the timestamp key, since the server doesn't have that one
	err = repo.RotateKey(data.CanonicalTimestampRole, true)
	require.NoError(t, err)

	require.NoError(t, repo.Publish())

	targets, err = repo.ListTargets()
	require.NoError(t, err)
	require.Len(t, targets, 2)

	// Also check that we can add/remove keys by rotating keys
	oldTargetsKeys := repo.CryptoService.ListKeys(data.CanonicalTargetsRole)
	require.NoError(t, repo.RotateKey(data.CanonicalTargetsRole, false))
	require.NoError(t, repo.Publish())
	newTargetsKeys := repo.CryptoService.ListKeys(data.CanonicalTargetsRole)

	require.Len(t, oldTargetsKeys, 1)
	require.Len(t, newTargetsKeys, 1)
	require.NotEqual(t, oldTargetsKeys[0], newTargetsKeys[0])

	// rotate the snapshot key to the server and ensure that the server can re-generate the snapshot
	// and we can download the snapshot
	require.NoError(t, repo.RotateKey(data.CanonicalSnapshotRole, true))
	require.NoError(t, repo.Publish())
	err = repo.Update(false)
	require.NoError(t, err)
}
Beispiel #8
0
// The command line uses NotaryRepository's RotateKey - this is just testing
// that multiple keys can be rotated at once locally
func TestRotateKeyBothKeys(t *testing.T) {
	setUp(t)
	// Temporary directory where test files will be created
	tempBaseDir, err := ioutil.TempDir("/tmp", "notary-test-")
	defer os.RemoveAll(tempBaseDir)
	require.NoError(t, err, "failed to create a temporary directory: %s", err)
	gun := "docker.com/notary"

	ret := passphrase.ConstantRetriever("pass")

	ts, initialKeys := setUpRepo(t, tempBaseDir, gun, ret)
	defer ts.Close()

	k := &keyCommander{
		configGetter: func() (*viper.Viper, error) {
			v := viper.New()
			v.SetDefault("trust_dir", tempBaseDir)
			v.SetDefault("remote_server.url", ts.URL)
			return v, nil
		},
		getRetriever: func() notary.PassRetriever { return ret },
	}
	require.NoError(t, k.keysRotate(&cobra.Command{}, []string{gun, data.CanonicalTargetsRole}))
	require.NoError(t, k.keysRotate(&cobra.Command{}, []string{gun, data.CanonicalSnapshotRole}))

	repo, err := client.NewNotaryRepository(tempBaseDir, gun, ts.URL, nil, ret, trustpinning.TrustPinConfig{})
	require.NoError(t, err, "error creating repo: %s", err)

	cl, err := repo.GetChangelist()
	require.NoError(t, err, "unable to get changelist: %v", err)
	require.Len(t, cl.List(), 0)

	// two new keys have been created, and the old keys should still be gone
	newKeys := repo.CryptoService.ListAllKeys()
	// there should be 3 keys - snapshot, targets, and root
	require.Len(t, newKeys, 3)

	// the old snapshot/targets keys should be gone
	for keyID, role := range initialKeys {
		r, ok := newKeys[keyID]
		switch r {
		case data.CanonicalSnapshotRole, data.CanonicalTargetsRole:
			require.False(t, ok, "original key %s still there", keyID)
		case data.CanonicalRootRole:
			require.Equal(t, role, r)
			require.True(t, ok, "old root key has changed")
		}
	}

	found := make(map[string]bool)
	for _, role := range newKeys {
		found[role] = true
	}
	require.True(t, found[data.CanonicalTargetsRole], "targets key was not created")
	require.True(t, found[data.CanonicalSnapshotRole], "snapshot key was not created")
	require.True(t, found[data.CanonicalRootRole], "root key was removed somehow")
}
Beispiel #9
0
func TestSignRootOldKeyCertMissing(t *testing.T) {
	gun := "docker/test-sign-root"
	referenceTime := time.Now()

	cs := cryptoservice.NewCryptoService(trustmanager.NewKeyMemoryStore(
		passphrase.ConstantRetriever("password")))

	rootPublicKey, err := cs.Create(data.CanonicalRootRole, gun, data.ECDSAKey)
	require.NoError(t, err)
	rootPrivateKey, _, err := cs.GetPrivateKey(rootPublicKey.ID())
	require.NoError(t, err)
	oldRootCert, err := cryptoservice.GenerateCertificate(rootPrivateKey, gun, referenceTime.AddDate(-9, 0, 0),
		referenceTime.AddDate(1, 0, 0))
	require.NoError(t, err)
	oldRootCertKey := trustmanager.CertToKey(oldRootCert)

	repo := initRepoWithRoot(t, cs, oldRootCertKey)

	// Create a first signature, using the old key.
	signedRoot, err := repo.SignRoot(data.DefaultExpires(data.CanonicalRootRole))
	require.NoError(t, err)
	verifySignatureList(t, signedRoot, oldRootCertKey)
	err = verifyRootSignatureAgainstKey(t, signedRoot, oldRootCertKey)
	require.NoError(t, err)

	// Create a new certificate
	newRootCert, err := cryptoservice.GenerateCertificate(rootPrivateKey, gun, referenceTime, referenceTime.AddDate(10, 0, 0))
	require.NoError(t, err)
	newRootCertKey := trustmanager.CertToKey(newRootCert)
	require.NotEqual(t, oldRootCertKey.ID(), newRootCertKey.ID())

	// Only trust the new certificate
	err = repo.ReplaceBaseKeys(data.CanonicalRootRole, newRootCertKey)
	require.NoError(t, err)
	updatedRootRole, err := repo.GetBaseRole(data.CanonicalRootRole)
	require.NoError(t, err)
	updatedRootKeyIDs := updatedRootRole.ListKeyIDs()
	require.Equal(t, 1, len(updatedRootKeyIDs))
	require.Equal(t, newRootCertKey.ID(), updatedRootKeyIDs[0])

	// Now forget all about the old certificate: drop it from the Root carried keys
	delete(repo.Root.Signed.Keys, oldRootCertKey.ID())
	repo2 := NewRepo(cs)
	repo2.Root = repo.Root
	repo2.originalRootRole = updatedRootRole

	// Create a second signature
	signedRoot, err = repo2.SignRoot(data.DefaultExpires(data.CanonicalRootRole))
	require.NoError(t, err)
	verifySignatureList(t, signedRoot, newRootCertKey) // Without oldRootCertKey

	// Verify that the signature can be verified when trusting the new certificate
	err = verifyRootSignatureAgainstKey(t, signedRoot, newRootCertKey)
	require.NoError(t, err)
	err = verifyRootSignatureAgainstKey(t, signedRoot, oldRootCertKey)
	require.Error(t, err)
}
Beispiel #10
0
func TestChangeKeyPassphraseInvalidID(t *testing.T) {
	k := &keyCommander{
		configGetter: func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
	}
	err := k.keyPassphraseChange(&cobra.Command{}, []string{"too_short"})
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "invalid key ID provided")
}
Beispiel #11
0
func TestChangeKeyPassphraseInvalidNumArgs(t *testing.T) {
	k := &keyCommander{
		configGetter: func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
	}
	err := k.keyPassphraseChange(&cobra.Command{}, []string{})
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "must specify the key ID")
}
Beispiel #12
0
// Given a list of key stores, the keys should be pretty-printed with their
// roles, locations, IDs, and guns first in sorted order in the key store
func TestPrettyPrintRootAndSigningKeys(t *testing.T) {
	ret := passphrase.ConstantRetriever("pass")
	keyStores := []trustmanager.KeyStore{
		trustmanager.NewKeyMemoryStore(ret),
		&otherMemoryStore{KeyMemoryStore: *trustmanager.NewKeyMemoryStore(ret)},
	}

	longNameShortened := "..." + strings.Repeat("z", 37)

	// just use the same key for testing
	key, err := trustmanager.GenerateED25519Key(rand.Reader)
	assert.NoError(t, err)

	root := data.CanonicalRootRole

	// add keys to the key stores
	err = keyStores[0].AddKey(key.ID(), root, key)
	assert.NoError(t, err)

	err = keyStores[1].AddKey(key.ID(), root, key)
	assert.NoError(t, err)

	err = keyStores[0].AddKey(strings.Repeat("a/", 30)+key.ID(), "targets", key)
	assert.NoError(t, err)

	err = keyStores[1].AddKey("short/gun/"+key.ID(), "snapshot", key)
	assert.NoError(t, err)

	expected := [][]string{
		{root, key.ID(), keyStores[0].Name()},
		{root, key.ID(), longNameShortened},
		{"targets", "..." + strings.Repeat("/a", 11), key.ID(), keyStores[0].Name()},
		{"snapshot", "short/gun", key.ID(), longNameShortened},
	}

	var b bytes.Buffer
	prettyPrintKeys(keyStores, &b)
	text, err := ioutil.ReadAll(&b)
	assert.NoError(t, err)

	lines := strings.Split(strings.TrimSpace(string(text)), "\n")
	assert.Len(t, lines, len(expected)+2)

	// starts with headers
	assert.True(t, reflect.DeepEqual(strings.Fields(lines[0]),
		[]string{"ROLE", "GUN", "KEY", "ID", "LOCATION"}))
	assert.Equal(t, "----", lines[1][:4])

	for i, line := range lines[2:] {
		// we are purposely not putting spaces in test data so easier to split
		splitted := strings.Fields(line)
		for j, v := range splitted {
			assert.Equal(t, expected[i][j], strings.TrimSpace(v))
		}
	}
}
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
}
Beispiel #14
0
func TestChangeKeyPassphraseNonexistentID(t *testing.T) {
	k := &keyCommander{
		configGetter: func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
	}
	// Valid ID size, but does not exist as a key ID
	err := k.keyPassphraseChange(&cobra.Command{}, []string{strings.Repeat("x", notary.Sha256HexSize)})
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "could not retrieve local key for key ID provided")
}
func newBlankRepo(t *testing.T, url string) *NotaryRepository {
	// Temporary directory where test files will be created
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	require.NoError(t, err, "failed to create a temporary directory: %s", err)

	repo, err := NewNotaryRepository(tempBaseDir, "docker.com/notary", url,
		http.DefaultTransport, passphrase.ConstantRetriever("pass"))
	require.NoError(t, err)
	return repo
}
Beispiel #16
0
// rotate key must be provided with a gun
func TestRotateKeyNoGUN(t *testing.T) {
	k := &keyCommander{
		configGetter:  func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever:  func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
		rotateKeyRole: data.CanonicalTargetsRole,
	}
	err := k.keysRotate(&cobra.Command{}, []string{})
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Must specify a GUN")
}
Beispiel #17
0
// The command line uses NotaryRepository's RotateKey - this is just testing
// that the correct config variables are passed for the client to rotate
// both the targets and snapshot key, and create them locally
func TestRotateKeyBothKeys(t *testing.T) {
	// Temporary directory where test files will be created
	tempBaseDir, err := ioutil.TempDir("/tmp", "notary-test-")
	defer os.RemoveAll(tempBaseDir)
	assert.NoError(t, err, "failed to create a temporary directory: %s", err)
	gun := "docker.com/notary"

	ret := passphrase.ConstantRetriever("pass")

	ts, initialKeys := setUpRepo(t, tempBaseDir, gun, ret)
	// we won't need this anymore since we are creating keys locally
	ts.Close()

	k := &keyCommander{
		configGetter: func() (*viper.Viper, error) {
			v := viper.New()
			v.SetDefault("trust_dir", tempBaseDir)
			// won't need a remote server URL, since we are creating local keys
			return v, nil
		},
		getRetriever: func() passphrase.Retriever { return ret },
	}
	err = k.keysRotate(&cobra.Command{}, []string{gun})
	assert.NoError(t, err)

	repo, err := client.NewNotaryRepository(tempBaseDir, gun, ts.URL, nil, ret)
	assert.NoError(t, err, "error creating repo: %s", err)

	cl, err := repo.GetChangelist()
	assert.NoError(t, err, "unable to get changelist: %v", err)
	assert.Len(t, cl.List(), 2)

	// two new keys have been created, and the old keys should still be there
	newKeys := repo.CryptoService.ListAllKeys()
	for keyID, role := range initialKeys {
		r, ok := newKeys[keyID]
		assert.True(t, ok, "original key %s missing", keyID)
		assert.Equal(t, role, r)
		delete(newKeys, keyID)
	}
	// there should be 2 keys left
	assert.Len(t, newKeys, 2)
	// one for each role
	var targetsFound, snapshotFound bool
	for _, role := range newKeys {
		switch role {
		case data.CanonicalTargetsRole:
			targetsFound = true
		case data.CanonicalSnapshotRole:
			snapshotFound = true
		}
	}
	assert.True(t, targetsFound, "targets key was not created")
	assert.True(t, snapshotFound, "snapshot key was not created")
}
Beispiel #18
0
// CopyKeys copies keys of a particular role to a new cryptoservice, and returns that cryptoservice
func CopyKeys(t *testing.T, from signed.CryptoService, roles ...string) signed.CryptoService {
	memKeyStore := trustmanager.NewKeyMemoryStore(passphrase.ConstantRetriever("pass"))
	for _, role := range roles {
		for _, keyID := range from.ListKeys(role) {
			key, _, err := from.GetPrivateKey(keyID)
			require.NoError(t, err)
			memKeyStore.AddKey(trustmanager.KeyInfo{Role: role}, key)
		}
	}
	return cryptoservice.NewCryptoService(memKeyStore)
}
func Test0Dot3Migration(t *testing.T) {
	// make a temporary directory and copy the fixture into it, since updating
	// and publishing will modify the files
	tmpDir, err := ioutil.TempDir("", "notary-backwards-compat-test")
	defer os.RemoveAll(tmpDir)
	require.NoError(t, err)
	require.NoError(t, recursiveCopy("../fixtures/compatibility/notary0.3", tmpDir))

	gun := "docker.com/notary0.3/samplerepo"
	passwd := "randompass"

	ts := fullTestServer(t)
	defer ts.Close()

	_, err = NewFileCachedNotaryRepository(tmpDir, gun, ts.URL, http.DefaultTransport,
		passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
	require.NoError(t, err, "error creating repo: %s", err)

	// check that root_keys and tuf_keys are gone and that all corect keys are present and have the correct headers
	files, _ := ioutil.ReadDir(filepath.Join(tmpDir, notary.PrivDir))
	require.Equal(t, files[0].Name(), "041b64dab281324ef2b62fd2d04f4758269e120ff063b7bc78709272821a0a02.key")
	targKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "041b64dab281324ef2b62fd2d04f4758269e120ff063b7bc78709272821a0a02.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer targKey.Close()
	targBytes, _ := ioutil.ReadAll(targKey)
	targString := string(targBytes)
	require.Contains(t, targString, "gun: docker.com/notary0.3/tst")
	require.Contains(t, targString, "role: targets")
	require.Equal(t, files[1].Name(), "85559599cf3cf681ff193f432a7ca6d128182bd1cfa8ede2c70761deac8bc2dc.key")
	snapKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "85559599cf3cf681ff193f432a7ca6d128182bd1cfa8ede2c70761deac8bc2dc.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer snapKey.Close()
	snapBytes, _ := ioutil.ReadAll(snapKey)
	snapString := string(snapBytes)
	require.Contains(t, snapString, "gun: docker.com/notary0.3/tst")
	require.Contains(t, snapString, "role: snapshot")
	require.Equal(t, files[2].Name(), "f4eaf871a74aa3b3a0ff95cef2455a1e4d461639f5625418e76756fc5c948690.key")
	rootKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "f4eaf871a74aa3b3a0ff95cef2455a1e4d461639f5625418e76756fc5c948690.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer rootKey.Close()
	rootBytes, _ := ioutil.ReadAll(rootKey)
	rootString := string(rootBytes)
	require.Contains(t, rootString, "role: root")
	require.NotContains(t, rootString, "gun")
	require.Equal(t, files[3].Name(), "fa842f66cac2dc898677a8660789dcff0e3b0b93b73f8952491f6493199936d3.key")
	delKey, err := os.OpenFile(filepath.Join(tmpDir, notary.PrivDir, "fa842f66cac2dc898677a8660789dcff0e3b0b93b73f8952491f6493199936d3.key"), os.O_RDONLY, notary.PrivExecPerms)
	require.NoError(t, err)
	defer delKey.Close()
	delBytes, _ := ioutil.ReadAll(delKey)
	delString := string(delBytes)
	require.Contains(t, delString, "role: targets/releases")
	require.NotContains(t, delString, "gun")
	require.Len(t, files, 4)
}
Beispiel #20
0
// the default location for the config file is in ~/.notary/config.json - even if it doesn't exist.
func TestNotaryConfigFileDefault(t *testing.T) {
	commander := &notaryCommander{
		getRetriever: func() notary.PassRetriever { return passphrase.ConstantRetriever("pass") },
	}

	config, err := commander.parseConfig()
	require.NoError(t, err)
	configFileUsed := config.ConfigFileUsed()
	require.True(t, strings.HasSuffix(configFileUsed,
		filepath.Join(".notary", "config.json")), "Unknown config file: %s", configFileUsed)
}
Beispiel #21
0
func TestGetImporters(t *testing.T) {
	if !yubikey.IsAccessible() {
		t.Skip("Must have Yubikey access.")
	}
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	require.NoError(t, err)
	defer os.RemoveAll(tempBaseDir)
	importers, err := getImporters(tempBaseDir, passphrase.ConstantRetriever("pass"))
	require.NoError(t, err)
	require.Len(t, importers, 2)
}
Beispiel #22
0
func TestKeyImportNoGUNForSnapshotPEM(t *testing.T) {
	k := &keyCommander{
		configGetter: func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
	}
	tempFileName := generateTempTestKeyFile(t, "snapshot")
	defer os.Remove(tempFileName)

	err := k.keysImport(&cobra.Command{}, []string{tempFileName})
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Must specify GUN")
}
Beispiel #23
0
func TestKeyImportNoRole(t *testing.T) {
	k := &keyCommander{
		configGetter: func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
	}
	tempFileName := generateTempTestKeyFile(t, "")
	defer os.Remove(tempFileName)

	err := k.keysImport(&cobra.Command{}, []string{tempFileName})
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Could not infer role, and no role was specified for key")
}
Beispiel #24
0
// Cannot rotate a targets key and require that the server manage it
func TestRotateKeyTargetCannotBeServerManaged(t *testing.T) {
	k := &keyCommander{
		configGetter:           func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever:           func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
		rotateKeyRole:          data.CanonicalTargetsRole,
		rotateKeyServerManaged: true,
	}
	err := k.keysRotate(&cobra.Command{}, []string{"gun"})
	assert.Error(t, err)
	assert.Contains(t, err.Error(),
		"remote signing/key management is only supported for the snapshot key")
}
Beispiel #25
0
// Cannot rotate a timestamp key and require that it is locally managed
func TestRotateKeyTimestampCannotBeLocallyManaged(t *testing.T) {
	setUp(t)
	k := &keyCommander{
		configGetter:           func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever:           func() notary.PassRetriever { return passphrase.ConstantRetriever("pass") },
		rotateKeyRole:          data.CanonicalTimestampRole,
		rotateKeyServerManaged: false,
	}
	err := k.keysRotate(&cobra.Command{}, []string{"gun", data.CanonicalTimestampRole})
	require.Error(t, err)
	require.IsType(t, client.ErrInvalidLocalRole{}, err)
}
Beispiel #26
0
// The command line uses NotaryRepository's RotateKey - this is just testing
// that the correct config variables are passed for the client to request a key
// from the remote server.
func TestRotateKeyRemoteServerManagesKey(t *testing.T) {
	for _, role := range []string{data.CanonicalSnapshotRole, data.CanonicalTimestampRole} {
		setUp(t)
		// Temporary directory where test files will be created
		tempBaseDir, err := ioutil.TempDir("/tmp", "notary-test-")
		defer os.RemoveAll(tempBaseDir)
		require.NoError(t, err, "failed to create a temporary directory: %s", err)
		gun := "docker.com/notary"

		ret := passphrase.ConstantRetriever("pass")

		ts, initialKeys := setUpRepo(t, tempBaseDir, gun, ret)
		defer ts.Close()
		require.Len(t, initialKeys, 3)

		k := &keyCommander{
			configGetter: func() (*viper.Viper, error) {
				v := viper.New()
				v.SetDefault("trust_dir", tempBaseDir)
				v.SetDefault("remote_server.url", ts.URL)
				return v, nil
			},
			getRetriever:           func() notary.PassRetriever { return ret },
			rotateKeyServerManaged: true,
		}
		require.NoError(t, k.keysRotate(&cobra.Command{}, []string{gun, role, "-r"}))

		repo, err := client.NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, ret, trustpinning.TrustPinConfig{})
		require.NoError(t, err, "error creating repo: %s", err)

		cl, err := repo.GetChangelist()
		require.NoError(t, err, "unable to get changelist: %v", err)
		require.Len(t, cl.List(), 0, "expected the changes to have been published")

		finalKeys := repo.CryptoService.ListAllKeys()
		// no keys have been created, since a remote key was specified
		if role == data.CanonicalSnapshotRole {
			require.Len(t, finalKeys, 2)
			for k, r := range initialKeys {
				if r != data.CanonicalSnapshotRole {
					_, ok := finalKeys[k]
					require.True(t, ok)
				}
			}
		} else {
			require.Len(t, finalKeys, 3)
			for k := range initialKeys {
				_, ok := finalKeys[k]
				require.True(t, ok)
			}
		}
	}
}
Beispiel #27
0
func TestKeyImportNoGUNForTargetsPEM(t *testing.T) {
	setUp(t)
	k := &keyCommander{
		configGetter: func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever: func() notary.PassRetriever { return passphrase.ConstantRetriever("pass") },
	}
	tempFileName := generateTempTestKeyFile(t, "targets")
	defer os.Remove(tempFileName)

	err := k.keysImport(&cobra.Command{}, []string{tempFileName})
	require.Error(t, err)
	require.Contains(t, err.Error(), "Must specify GUN")
}
Beispiel #28
0
func TestKeyImportMismatchingRoles(t *testing.T) {
	k := &keyCommander{
		configGetter:   func() (*viper.Viper, error) { return viper.New(), nil },
		getRetriever:   func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
		keysImportRole: "targets",
	}
	tempFileName := generateTempTestKeyFile(t, "snapshot")
	defer os.Remove(tempFileName)

	err := k.keysImport(&cobra.Command{}, []string{tempFileName})
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "does not match role")
}
Beispiel #29
0
// If there are no keys in any of the key stores, a message that there are no
// signing keys should be displayed.
func TestPrettyPrintZeroKeys(t *testing.T) {
	ret := passphrase.ConstantRetriever("pass")
	emptyKeyStore := trustmanager.NewKeyMemoryStore(ret)

	var b bytes.Buffer
	prettyPrintKeys([]trustmanager.KeyStore{emptyKeyStore}, &b)
	text, err := ioutil.ReadAll(&b)
	assert.NoError(t, err)

	lines := strings.Split(strings.TrimSpace(string(text)), "\n")
	assert.Len(t, lines, 1)
	assert.Equal(t, "No signing keys found.", lines[0])
}
Beispiel #30
0
func setupServerHandler(metaStore storage.MetaStore) http.Handler {
	ctx := context.WithValue(context.Background(), "metaStore", metaStore)

	ctx = context.WithValue(ctx, "keyAlgorithm", data.ECDSAKey)

	// Eat the logs instead of spewing them out
	var b bytes.Buffer
	l := logrus.New()
	l.Out = &b
	ctx = ctxu.WithLogger(ctx, logrus.NewEntry(l))

	cryptoService := cryptoservice.NewCryptoService(trustmanager.NewKeyMemoryStore(passphrase.ConstantRetriever("pass")))
	return server.RootHandler(nil, ctx, cryptoService, nil, nil, nil)
}