Beispiel #1
0
func TestRotation(t *testing.T) {
	signer := signed.NewEd25519()
	repo := tuf.NewRepo(signer)
	remote := store.NewMemoryStore(nil)
	cache := store.NewMemoryStore(nil)

	// Generate initial root key and role and add to key DB
	rootKey, err := signer.Create("root", data.ED25519Key)
	assert.NoError(t, err, "Error creating root key")
	rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil)
	assert.NoError(t, err, "Error creating root role")

	originalRoot, err := data.NewRoot(
		map[string]data.PublicKey{rootKey.ID(): rootKey},
		map[string]*data.RootRole{"root": &rootRole.RootRole},
		false,
	)

	repo.Root = originalRoot

	// Generate new key and role.
	replacementKey, err := signer.Create("root", data.ED25519Key)
	assert.NoError(t, err, "Error creating replacement root key")
	replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil)
	assert.NoError(t, err, "Error creating replacement root role")

	// Generate a new root with the replacement key and role
	testRoot, err := data.NewRoot(
		map[string]data.PublicKey{replacementKey.ID(): replacementKey},
		map[string]*data.RootRole{
			data.CanonicalRootRole:      &replacementRole.RootRole,
			data.CanonicalSnapshotRole:  &replacementRole.RootRole,
			data.CanonicalTargetsRole:   &replacementRole.RootRole,
			data.CanonicalTimestampRole: &replacementRole.RootRole,
		},
		false,
	)
	assert.NoError(t, err, "Failed to create new root")

	// Sign testRoot with both old and new keys
	signedRoot, err := testRoot.ToSigned()
	err = signed.Sign(signer, signedRoot, rootKey, replacementKey)
	assert.NoError(t, err, "Failed to sign root")
	var origKeySig bool
	var replKeySig bool
	for _, sig := range signedRoot.Signatures {
		if sig.KeyID == rootKey.ID() {
			origKeySig = true
		} else if sig.KeyID == replacementKey.ID() {
			replKeySig = true
		}
	}
	assert.True(t, origKeySig, "Original root key signature not present")
	assert.True(t, replKeySig, "Replacement root key signature not present")

	client := NewClient(repo, remote, cache)

	err = client.verifyRoot("root", signedRoot, 0)
	assert.NoError(t, err, "Failed to verify key rotated root")
}
Beispiel #2
0
func TestDownloadSnapshotHappy(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	// create and "upload" sample snapshot and timestamp
	signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("snapshot", orig)
	assert.NoError(t, err)

	signedOrig, err = repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)
	orig, err = json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("timestamp", orig)
	assert.NoError(t, err)

	err = client.downloadSnapshot()
	assert.NoError(t, err)
}
Beispiel #3
0
func TestRotationNewSigMissing(t *testing.T) {
	logrus.SetLevel(logrus.DebugLevel)
	kdb := keys.NewDB()
	signer := signed.NewEd25519()
	repo := tuf.NewRepo(kdb, signer)
	remote := store.NewMemoryStore(nil, nil)
	cache := store.NewMemoryStore(nil, nil)

	// Generate initial root key and role and add to key DB
	rootKey, err := signer.Create("root", data.ED25519Key)
	assert.NoError(t, err, "Error creating root key")
	rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil, nil)
	assert.NoError(t, err, "Error creating root role")

	kdb.AddKey(rootKey)
	err = kdb.AddRole(rootRole)
	assert.NoError(t, err, "Error adding root role to db")

	// Generate new key and role. These will appear in the root.json
	// but will not be added to the keyDB.
	replacementKey, err := signer.Create("root", data.ED25519Key)
	assert.NoError(t, err, "Error creating replacement root key")
	replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil, nil)
	assert.NoError(t, err, "Error creating replacement root role")

	assert.NotEqual(t, rootKey.ID(), replacementKey.ID(), "Key IDs are the same")

	// Generate a new root with the replacement key and role
	testRoot, err := data.NewRoot(
		map[string]data.PublicKey{replacementKey.ID(): replacementKey},
		map[string]*data.RootRole{"root": &replacementRole.RootRole},
		false,
	)
	assert.NoError(t, err, "Failed to create new root")

	_, ok := testRoot.Signed.Keys[rootKey.ID()]
	assert.False(t, ok, "Old root key appeared in test root")

	// Sign testRoot with both old and new keys
	signedRoot, err := testRoot.ToSigned()
	err = signed.Sign(signer, signedRoot, rootKey)
	assert.NoError(t, err, "Failed to sign root")
	var origKeySig bool
	var replKeySig bool
	for _, sig := range signedRoot.Signatures {
		if sig.KeyID == rootKey.ID() {
			origKeySig = true
		} else if sig.KeyID == replacementKey.ID() {
			replKeySig = true
		}
	}
	assert.True(t, origKeySig, "Original root key signature not present")
	assert.False(t, replKeySig, "Replacement root key signature was present and shouldn't be")

	client := NewClient(repo, remote, kdb, cache)

	err = client.verifyRoot("root", signedRoot, 0)
	assert.Error(t, err, "Should have errored on verify as replacement signature was missing.")

}
Beispiel #4
0
// If there is no local cache and the remote timestamp is empty, downloading the timestamp
// fails with a store.ErrMetaNotFound
func TestDownloadTimestampNoLocalTimestampRemoteTimestampEmpty(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(map[string][]byte{data.CanonicalTimestampRole: {}})
	client := NewClient(repo, remoteStorage, localStorage)

	err = client.downloadTimestamp()
	assert.Error(t, err)
	assert.IsType(t, &json.SyntaxError{}, err)
}
Beispiel #5
0
// If there is no local cache and also no remote timestamp, downloading the timestamp
// fails with a store.ErrMetaNotFound
func TestDownloadTimestampNoTimestamps(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	err = client.downloadTimestamp()
	assert.Error(t, err)
	notFoundErr, ok := err.(store.ErrMetaNotFound)
	assert.True(t, ok)
	assert.Equal(t, data.CanonicalTimestampRole, notFoundErr.Resource)
}
Beispiel #6
0
func TestDownloadTargetChecksumMismatch(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := testutils.NewCorruptingMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	// create and "upload" sample targets
	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	origSha256 := sha256.Sum256(orig)
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	// create local snapshot with targets file
	snap := data.SignedSnapshot{
		Signed: data.Snapshot{
			Meta: data.Files{
				"targets": data.FileMeta{
					Length: int64(len(orig)),
					Hashes: data.Hashes{
						"sha256": origSha256[:],
					},
				},
			},
		},
	}

	repo.Snapshot = &snap

	err = client.downloadTargets("targets")
	assert.IsType(t, ErrChecksumMismatch{}, err)
}
Beispiel #7
0
func TestChecksumMatch(t *testing.T) {
	repo := tuf.NewRepo(nil, nil)
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, nil, localStorage)

	sampleTargets := data.NewTargets()
	orig, err := json.Marshal(sampleTargets)
	origSha256 := sha256.Sum256(orig)
	assert.NoError(t, err)

	remoteStorage.SetMeta("targets", orig)

	_, _, err = client.downloadSigned("targets", int64(len(orig)), origSha256[:])
	assert.NoError(t, err)
}
Beispiel #8
0
func TestDownloadTimestampHappy(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// create and "upload" sample timestamp
	signedOrig, err := repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("timestamp", orig)
	assert.NoError(t, err)

	err = client.downloadTimestamp()
	assert.NoError(t, err)
}
Beispiel #9
0
// If there is is a local cache and no remote timestamp, we fall back on the cached timestamp
func TestDownloadTimestampLocalTimestampNoRemoteTimestamp(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)

	// add a timestamp to the local cache
	tsSigned, err := repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)
	ts, err := json.Marshal(tsSigned)
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(map[string][]byte{data.CanonicalTimestampRole: ts})

	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	err = client.downloadTimestamp()
	assert.NoError(t, err)
}
Beispiel #10
0
// If there is no local cache and the remote timestamp is invalid, downloading the timestamp
// fails with a store.ErrMetaNotFound
func TestDownloadTimestampNoLocalTimestampRemoteTimestampInvalid(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)

	// add a timestamp to the remote cache
	tsSigned, err := repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)
	tsSigned.Signatures[0].Signature = []byte("12345") // invalidate the signature
	ts, err := json.Marshal(tsSigned)
	assert.NoError(t, err)
	remoteStorage := store.NewMemoryStore(map[string][]byte{data.CanonicalTimestampRole: ts})

	client := NewClient(repo, remoteStorage, localStorage)
	err = client.downloadTimestamp()
	assert.Error(t, err)
	assert.IsType(t, signed.ErrRoleThreshold{}, err)
}
Beispiel #11
0
func TestDownloadSnapshotNoChecksum(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// create and "upload" sample snapshot and timestamp
	signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("snapshot", orig)
	assert.NoError(t, err)

	delete(repo.Timestamp.Signed.Meta["snapshot"].Hashes, "sha256")

	err = client.downloadSnapshot()
	assert.IsType(t, ErrMissingMeta{}, err)
}
Beispiel #12
0
// TestDownloadTargetsNoSnapshot: it's never valid to download any targets
// role (incl. delegations) when a checksum is not available.
func TestDownloadTargetsNoSnapshot(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// create and "upload" sample targets
	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	repo.Snapshot = nil

	err = client.downloadTargets("targets")
	assert.IsType(t, ErrMissingMeta{}, err)
}
Beispiel #13
0
func TestDownloadTargetsHappy(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	// call repo.SignSnapshot to update the targets role in the snapshot
	repo.SignSnapshot(data.DefaultExpires("snapshot"))

	err = client.downloadTargets("targets")
	assert.NoError(t, err)
}
Beispiel #14
0
func TestUpdateDownloadRootHappy(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// create and "upload" sample root, snapshot, and timestamp
	signedOrig, err := repo.SignRoot(data.DefaultExpires("root"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("root", orig)
	assert.NoError(t, err)

	// sign snapshot to make root meta in snapshot get updated
	signedOrig, err = repo.SignSnapshot(data.DefaultExpires("snapshot"))

	err = client.downloadRoot()
	assert.NoError(t, err)
}
Beispiel #15
0
func TestBootstrapDownloadRootHappy(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// create and "upload" sample root
	signedOrig, err := repo.SignRoot(data.DefaultExpires("root"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("root", orig)
	assert.NoError(t, err)

	// unset snapshot as if we're bootstrapping from nothing
	repo.Snapshot = nil

	err = client.downloadRoot()
	assert.NoError(t, err)
}
Beispiel #16
0
// TestDownloadTargetsNoChecksum: it's never valid to download any targets
// role (incl. delegations) when a checksum is not available.
func TestDownloadTargetsNoChecksum(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	// create and "upload" sample targets
	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	delete(repo.Snapshot.Signed.Meta["targets"].Hashes, "sha256")

	err = client.downloadTargets("targets")
	assert.IsType(t, data.ErrMissingMeta{}, err)
}
Beispiel #17
0
// TestDownloadTargetsLarge: Check that we can download very large targets metadata files,
// which may be caused by adding a large number of targets.
// This test is slow, so it will not run in short mode.
func TestDownloadTargetsLarge(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode")
	}

	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	hash := sha256.Sum256([]byte{})
	f := data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	// Add a ton of target files to the targets role to make this targets metadata huge
	// 75,000 targets results in > 5MB (~6.5MB on recent runs)
	for i := 0; i < 75000; i++ {
		_, err = repo.AddTargets(data.CanonicalTargetsRole, data.Files{strconv.Itoa(i): f})
		assert.NoError(t, err)
	}

	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	// call repo.SignSnapshot to update the targets role in the snapshot
	repo.SignSnapshot(data.DefaultExpires("snapshot"))

	// Clear the cache to force an online download
	client.cache.RemoveAll()

	err = client.downloadTargets("targets")
	assert.NoError(t, err)
}
Beispiel #18
0
func TestSizeMismatchShort(t *testing.T) {
	repo := tuf.NewRepo(nil, nil)
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, nil, localStorage)

	sampleTargets := data.NewTargets()
	orig, err := json.Marshal(sampleTargets)
	origSha256 := sha256.Sum256(orig)
	assert.NoError(t, err)
	l := int64(len(orig))

	orig = orig[1:]

	remoteStorage.SetMeta("targets", orig)

	_, _, err = client.downloadSigned("targets", l, origSha256[:])
	// size just limits the data received, the error is caught
	// either during checksum verification or during json deserialization
	assert.IsType(t, ErrChecksumMismatch{}, err)
}
Beispiel #19
0
// TestDownloadSnapshotLarge: Check that we can download very large snapshot metadata files,
// which may be caused by adding a large number of delegations.
// This test is slow, so it will not run in short mode.
func TestDownloadSnapshotLarge(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode")
	}
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	// Add a ton of empty delegation roles to targets to make snapshot data huge
	// This can also be done by adding legitimate delegations but it will be much slower
	// 75,000 delegation roles results in > 5MB (~7.3MB on recent runs)
	for i := 0; i < 75000; i++ {
		newRole := &data.SignedTargets{}
		repo.Targets[fmt.Sprintf("targets/%d", i)] = newRole
	}

	// create and "upload" sample snapshot and timestamp
	signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("snapshot", orig)
	assert.NoError(t, err)

	signedOrig, err = repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)
	orig, err = json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("timestamp", orig)
	assert.NoError(t, err)

	// Clear the cache to force an online download
	client.cache.RemoveAll()

	err = client.downloadSnapshot()
	assert.NoError(t, err)
}
Beispiel #20
0
// TargetMeta returns the file metadata for a file path in the role subtree,
// if it exists. It also returns the role in that subtree in which the target
// was found. If the path doesn't exist in that role subtree, returns
// nil and an empty string.
func TestTargetMeta(t *testing.T) {
	kdb, repo, cs, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, nil, kdb, localStorage)

	delegations := []string{
		"targets/level1",
		"targets/level1/a",
		"targets/level1/a/i",
	}

	k, err := cs.Create("", data.ED25519Key)
	assert.NoError(t, err)

	hash := sha256.Sum256([]byte{})
	f := data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}

	for i, r := range delegations {
		// create role
		role, err := data.NewRole(r, 1, []string{k.ID()}, []string{""}, nil)
		assert.NoError(t, err)

		// add role to repo
		repo.UpdateDelegations(role, []data.PublicKey{k})
		repo.InitTargets(r)

		// add a target to the role
		_, err = repo.AddTargets(r, data.Files{strconv.Itoa(i): f})
		assert.NoError(t, err)
	}

	// returns the right level
	fileMeta, role := client.TargetMeta("targets", "1")
	assert.Equal(t, &f, fileMeta)
	assert.Equal(t, "targets/level1/a", role)

	// looks only in subtree
	fileMeta, role = client.TargetMeta("targets/level1/a", "0")
	assert.Nil(t, fileMeta)
	assert.Equal(t, "", role)

	fileMeta, role = client.TargetMeta("targets/level1/a", "2")
	assert.Equal(t, &f, fileMeta)
	assert.Equal(t, "targets/level1/a/i", role)
}
Beispiel #21
0
func TestUpdateDownloadRootBadChecksum(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// sign snapshot to make sure we have a checksum for root
	_, err := repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)

	// create and "upload" sample root, snapshot, and timestamp
	signedOrig, err := repo.SignRoot(data.DefaultExpires("root"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("root", orig)
	assert.NoError(t, err)

	// don't sign snapshot again to ensure checksum is out of date (bad)

	err = client.downloadRoot()
	assert.IsType(t, ErrChecksumMismatch{}, err)
}
Beispiel #22
0
func TestDownloadSnapshotBadChecksum(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// sign timestamp to ensure it has a checksum for snapshot
	_, err := repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)

	// create and "upload" sample snapshot and timestamp
	signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("snapshot", orig)
	assert.NoError(t, err)

	// by not signing timestamp again we ensure it has the wrong checksum

	err = client.downloadSnapshot()
	assert.IsType(t, ErrChecksumMismatch{}, err)
}
Beispiel #23
0
func TestDownloadTargetChecksumMismatch(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// create and "upload" sample targets
	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	origSha256 := sha256.Sum256(orig)
	orig[0] = '}' // corrupt data, should be a {
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	// create local snapshot with targets file
	// It's necessary to do it this way rather than calling repo.SignSnapshot
	// so that we have the wrong sha256 in the snapshot.
	snap := data.SignedSnapshot{
		Signed: data.Snapshot{
			Meta: data.Files{
				"targets": data.FileMeta{
					Length: int64(len(orig)),
					Hashes: data.Hashes{
						"sha256": origSha256[:],
					},
				},
			},
		},
	}

	repo.Snapshot = &snap

	err = client.downloadTargets("targets")
	assert.IsType(t, ErrChecksumMismatch{}, err)
}
Beispiel #24
0
// NewMetadataSwizzler returns a new swizzler when given a gun,
// mapping of roles to initial metadata bytes, and a cryptoservice
func NewMetadataSwizzler(gun string, initialMetadata map[string][]byte,
	cryptoService signed.CryptoService) *MetadataSwizzler {

	var roles []string
	for roleName := range initialMetadata {
		roles = append(roles, roleName)
	}

	return &MetadataSwizzler{
		Gun:           gun,
		MetadataCache: store.NewMemoryStore(initialMetadata),
		CryptoService: cryptoService,
		Roles:         roles,
	}
}
Beispiel #25
0
func TestUpdateDownloadRootChecksumNotFound(t *testing.T) {
	remoteStore := store.NewMemoryStore(nil)
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStore, localStorage)

	// sign snapshot to make sure we have current checksum for root
	_, err = repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)

	// sign and "upload" sample root
	signedOrig, err := repo.SignRoot(data.DefaultExpires("root"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStore.SetMeta("root", orig)
	assert.NoError(t, err)

	// don't sign snapshot again to ensure checksum is out of date (bad)

	err = client.downloadRoot()
	assert.IsType(t, store.ErrMetaNotFound{}, err)
}
// Update can succeed even if we cannot write any metadata to the repo (assuming
// no data in the repo)
func TestUpdateSucceedsEvenIfCannotWriteNewRepo(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode")
	}

	serverMeta, _, err := testutils.NewRepoMetadata("docker.com/notary", metadataDelegations...)
	require.NoError(t, err)

	ts := readOnlyServer(t, store.NewMemoryStore(serverMeta), http.StatusNotFound, "docker.com/notary")
	defer ts.Close()

	for role := range serverMeta {
		repo := newBlankRepo(t, ts.URL)
		repo.fileStore = &unwritableStore{MetadataStore: repo.fileStore, roleToNotWrite: role}
		_, err := repo.Update(false)

		if role == data.CanonicalRootRole {
			require.Error(t, err) // because checkRoot loads root from cache to check hashes
			continue
		} else {
			require.NoError(t, err)
		}

		for r, expected := range serverMeta {
			actual, err := repo.fileStore.GetMeta(r, -1)
			if r == role {
				require.Error(t, err)
				require.IsType(t, store.ErrMetaNotFound{}, err,
					"expected no data because unable to write for %s", role)
			} else {
				require.NoError(t, err, "problem getting repo metadata for %s", r)
				require.True(t, bytes.Equal(expected, actual),
					"%s: expected to update since only %s was unwritable", r, role)
			}
		}

		os.RemoveAll(repo.baseDir)
	}
}
Beispiel #27
0
func TestUpdateDownloadRootBadChecksum(t *testing.T) {
	remoteStore := testutils.NewCorruptingMemoryStore(nil)

	kdb, repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStore, kdb, localStorage)

	// sign and "upload" sample root
	signedOrig, err := repo.SignRoot(data.DefaultExpires("root"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStore.SetMeta("root", orig)
	assert.NoError(t, err)

	// sign snapshot to make sure we have current checksum for root
	_, err = repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)

	err = client.downloadRoot()
	assert.IsType(t, ErrChecksumMismatch{}, err)
}
// If a repo has corrupt metadata (in that the hash doesn't match the snapshot) or
// missing metadata, an update will replace all of it
func TestUpdateReplacesCorruptOrMissingMetadata(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode")
	}
	serverMeta, cs, err := testutils.NewRepoMetadata("docker.com/notary", metadataDelegations...)
	require.NoError(t, err)

	ts := readOnlyServer(t, store.NewMemoryStore(serverMeta), http.StatusNotFound, "docker.com/notary")
	defer ts.Close()

	repo := newBlankRepo(t, ts.URL)
	defer os.RemoveAll(repo.baseDir)

	_, err = repo.Update(false) // ensure we have all metadata to start with
	require.NoError(t, err)

	// we want to swizzle the local cache, not the server, so create a new one
	repoSwizzler := testutils.NewMetadataSwizzler("docker.com/notary", serverMeta, cs)
	repoSwizzler.MetadataCache = repo.fileStore

	for _, role := range repoSwizzler.Roles {
		for _, expt := range waysToMessUpLocalMetadata {
			text, messItUp := expt.desc, expt.swizzle
			for _, forWrite := range []bool{true, false} {
				require.NoError(t, messItUp(repoSwizzler, role), "could not fuzz %s (%s)", role, text)
				_, err := repo.Update(forWrite)
				require.NoError(t, err)
				for r, expected := range serverMeta {
					actual, err := repo.fileStore.GetMeta(r, -1)
					require.NoError(t, err, "problem getting repo metadata for %s", role)
					require.True(t, bytes.Equal(expected, actual),
						"%s for %s: expected to recover after update", text, role)
				}
			}
		}
	}
}
Beispiel #29
0
func TestCheckRootExpired(t *testing.T) {
	repo := tuf.NewRepo(nil, nil)
	storage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, storage, nil, storage)

	root := &data.SignedRoot{}
	root.Signed.Expires = time.Now().AddDate(-1, 0, 0)

	signedRoot, err := root.ToSigned()
	assert.NoError(t, err)
	rootJSON, err := json.Marshal(signedRoot)
	assert.NoError(t, err)

	rootHash := sha256.Sum256(rootJSON)

	testSnap := &data.SignedSnapshot{
		Signed: data.Snapshot{
			Meta: map[string]data.FileMeta{
				"root": {
					Length: int64(len(rootJSON)),
					Hashes: map[string][]byte{
						"sha256": rootHash[:],
					},
				},
			},
		},
	}
	repo.SetRoot(root)
	repo.SetSnapshot(testSnap)

	storage.SetMeta("root", rootJSON)

	err = client.checkRoot()
	assert.Error(t, err)
	assert.IsType(t, tuf.ErrLocalRootExpired{}, err)
}
Beispiel #30
0
func TestDownloadTargetsDeepHappy(t *testing.T) {
	repo, cs, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	delegations := []string{
		// left subtree
		"targets/level1",
		"targets/level1/a",
		"targets/level1/a/i",
		"targets/level1/a/ii",
		"targets/level1/a/iii",
		// right subtree
		"targets/level2",
		"targets/level2/b",
		"targets/level2/b/i",
		"targets/level2/b/i/0",
		"targets/level2/b/i/1",
	}

	for _, r := range delegations {
		// create role
		k, err := cs.Create(r, data.ED25519Key)
		assert.NoError(t, err)

		// add role to repo
		err = repo.UpdateDelegationKeys(r, []data.PublicKey{k}, []string{}, 1)
		assert.NoError(t, err)
		err = repo.UpdateDelegationPaths(r, []string{""}, []string{}, false)
		assert.NoError(t, err)
		repo.InitTargets(r)
	}

	// can only sign after adding all delegations
	for _, r := range delegations {
		// serialize and store role
		signedOrig, err := repo.SignTargets(r, data.DefaultExpires("targets"))
		assert.NoError(t, err)
		orig, err := json.Marshal(signedOrig)
		assert.NoError(t, err)
		err = remoteStorage.SetMeta(r, orig)
		assert.NoError(t, err)
	}

	// serialize and store targets after adding all delegations
	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	// call repo.SignSnapshot to update the targets role in the snapshot
	repo.SignSnapshot(data.DefaultExpires("snapshot"))

	delete(repo.Targets, "targets")
	for _, r := range delegations {
		delete(repo.Targets, r)
		_, ok := repo.Targets[r]
		assert.False(t, ok)
	}

	err = client.downloadTargets("targets")
	assert.NoError(t, err)

	_, ok := repo.Targets["targets"]
	assert.True(t, ok)

	for _, r := range delegations {
		_, ok = repo.Targets[r]
		assert.True(t, ok)
	}
}