// Creates metadata in the following manner: // - the snapshot has bad checksums for itself and for timestamp, to show that those aren't checked // - snapshot has valid checksums for root, targets, and targets/other // - snapshot doesn't have a checksum for targets/other/other, but targets/other/other is a valid // delegation role in targets/other and there is metadata for targets/other/other that is correctly // signed func setupSnapshotChecksumming(t *testing.T, gun string) map[string][]byte { repo, _, err := testutils.EmptyRepo(gun, "targets/other", "targets/other/other") require.NoError(t, err) // add invalid checkums for all the other roles to timestamp too, and show that // cached items aren't checksummed against this fakeChecksum, err := data.NewFileMeta(bytes.NewBuffer([]byte("fake")), notary.SHA256, notary.SHA512) require.NoError(t, err) // fake the snapshot and timestamp checksums repo.Snapshot.Signed.Meta[data.CanonicalSnapshotRole] = fakeChecksum repo.Snapshot.Signed.Meta[data.CanonicalTimestampRole] = fakeChecksum meta, err := testutils.SignAndSerialize(repo) require.NoError(t, err) // ensure that the fake metadata for other roles wasn't destroyed by signing require.Len(t, repo.Snapshot.Signed.Meta, 5) // create delegation metadata that should not be in snapshot, but has a valid role and signature _, err = repo.InitTargets("targets/other/other") require.NoError(t, err) s, err := repo.SignTargets("targets/other/other", data.DefaultExpires(data.CanonicalTargetsRole)) require.NoError(t, err) meta["targets/other/other"], err = json.Marshal(s) require.NoError(t, err) return meta }
// If applying a change fails due to a prefix error, changeTargetMeta fails outright func TestChangeTargetMetaFailsIfPrefixError(t *testing.T) { repo, cs, err := testutils.EmptyRepo("docker.com/notary") require.NoError(t, err) newKey, err := cs.Create("targets/level1", "docker.com/notary", data.ED25519Key) require.NoError(t, err) err = repo.UpdateDelegationKeys("targets/level1", []data.PublicKey{newKey}, []string{}, 1) require.NoError(t, err) err = repo.UpdateDelegationPaths("targets/level1", []string{"pathprefix"}, []string{}, false) require.NoError(t, err) hash := sha256.Sum256([]byte{}) f := &data.FileMeta{ Length: 1, Hashes: map[string][]byte{ "sha256": hash[:], }, } fjson, err := json.Marshal(f) require.NoError(t, err) err = changeTargetMeta(repo, &changelist.TUFChange{ Actn: changelist.ActionCreate, Role: "targets/level1", ChangeType: "target", ChangePath: "notPathPrefix", Data: fjson, }) require.Error(t, err) // no target in targets or targets/latest require.Empty(t, repo.Targets[data.CanonicalTargetsRole].Signed.Targets) require.Empty(t, repo.Targets["targets/level1"].Signed.Targets) }
// Applying a delegation whose parent doesn't exist fails. func TestApplyTargetsDelegationParentDoesntExist(t *testing.T) { repo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) // make sure a key exists for the previous level, so it's not a missing // key error, but we don't care about this key _, err = cs.Create("targets/level1", data.ED25519Key) assert.NoError(t, err) newKey, err := cs.Create("targets/level1/level2", data.ED25519Key) assert.NoError(t, err) // create delegation kl := data.KeyList{newKey} td := &changelist.TufDelegation{ NewThreshold: 1, AddKeys: kl, } tdJSON, err := json.Marshal(td) assert.NoError(t, err) ch := changelist.NewTufChange( changelist.ActionCreate, "targets/level1/level2", changelist.TypeTargetsDelegation, "", tdJSON, ) err = applyTargetsChange(repo, ch) assert.Error(t, err) assert.IsType(t, data.ErrInvalidRole{}, err) }
func TestApplyTargetsDelegationCreateInvalid(t *testing.T) { _, repo, cs := testutils.EmptyRepo() newKey, err := cs.Create("targets/level1", data.ED25519Key) assert.NoError(t, err) // create delegation kl := data.KeyList{newKey} td := &changelist.TufDelegation{ NewThreshold: 1, AddKeys: kl, AddPaths: []string{"level1"}, AddPathHashPrefixes: []string{"abc"}, } tdJSON, err := json.Marshal(td) assert.NoError(t, err) ch := changelist.NewTufChange( changelist.ActionCreate, "targets/level1", changelist.TypeTargetsDelegation, "", tdJSON, ) err = applyTargetsChange(repo, ch) assert.Error(t, err) }
// Ensures that the httpstore can interpret the errors returned from the server func TestValidationErrorFormat(t *testing.T) { ctx := context.WithValue( context.Background(), "metaStore", storage.NewMemStorage()) ctx = context.WithValue(ctx, "keyAlgorithm", data.ED25519Key) handler := RootHandler(nil, ctx, signed.NewEd25519()) server := httptest.NewServer(handler) defer server.Close() client, err := store.NewHTTPStore( fmt.Sprintf("%s/v2/gun/_trust/tuf/", server.URL), "", "json", "", "key", http.DefaultTransport, ) _, repo, _ := testutils.EmptyRepo() r, tg, sn, ts, err := testutils.Sign(repo) assert.NoError(t, err) rs, _, _, _, err := testutils.Serialize(r, tg, sn, ts) assert.NoError(t, err) err = client.SetMultiMeta(map[string][]byte{data.CanonicalRootRole: rs}) assert.Error(t, err) assert.IsType(t, validation.ErrBadRoot{}, err) }
func TestValidateSnapshotGenerate(t *testing.T) { kdb, repo, cs := testutils.EmptyRepo() store := storage.NewMemStorage() snapRole := kdb.GetRole(data.CanonicalSnapshotRole) for _, id := range snapRole.KeyIDs { k := kdb.GetKey(id) assert.NotNil(t, k) err := store.SetKey("testGUN", data.CanonicalSnapshotRole, k.Algorithm(), k.Public()) assert.NoError(t, err) } r, tg, sn, ts, err := testutils.Sign(repo) assert.NoError(t, err) root, targets, _, _, err := getUpdates(r, tg, sn, ts) assert.NoError(t, err) updates := []storage.MetaUpdate{targets} store.UpdateCurrent("testGUN", root) copyTimestampKey(t, kdb, store, "testGUN") updates, err = validateUpdate(cs, "testGUN", updates, store) assert.NoError(t, err) }
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) }
func TestValidateSnapshotGeneratePrevCorrupt(t *testing.T) { gun := "docker.com/notary" repo, cs, err := testutils.EmptyRepo(gun) require.NoError(t, err) store := storage.NewMemStorage() snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole) require.NoError(t, err) for _, k := range snapRole.Keys { err := store.SetKey(gun, data.CanonicalSnapshotRole, k.Algorithm(), k.Public()) require.NoError(t, err) } r, tg, sn, ts, err := testutils.Sign(repo) require.NoError(t, err) root, targets, snapshot, _, err := getUpdates(r, tg, sn, ts) require.NoError(t, err) updates := []storage.MetaUpdate{root, targets} // corrupt the JSON structure of prev snapshot snapshot.Data = snapshot.Data[1:] // set the current snapshot in the store manually so we find it when generating // the next version store.UpdateCurrent(gun, snapshot) serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole) _, err = validateUpdate(serverCrypto, gun, updates, store) require.Error(t, err) require.IsType(t, &json.SyntaxError{}, err) }
// Store is broken when getting the current snapshot func TestValidateSnapshotGenerateStoreGetCurrentSnapshotBroken(t *testing.T) { gun := "docker.com/notary" repo, cs, err := testutils.EmptyRepo(gun) require.NoError(t, err) store := getFailStore{ MetaStore: storage.NewMemStorage(), errsToReturn: map[string]error{data.CanonicalSnapshotRole: data.ErrNoSuchRole{}}, } snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole) require.NoError(t, err) for _, k := range snapRole.Keys { err := store.SetKey(gun, data.CanonicalSnapshotRole, k.Algorithm(), k.Public()) require.NoError(t, err) } r, tg, sn, ts, err := testutils.Sign(repo) require.NoError(t, err) root, targets, _, _, err := getUpdates(r, tg, sn, ts) require.NoError(t, err) updates := []storage.MetaUpdate{root, targets} serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole) _, err = validateUpdate(serverCrypto, gun, updates, store) require.Error(t, err) require.IsType(t, data.ErrNoSuchRole{}, err) }
func TestValidatePrevTimestamp(t *testing.T) { gun := "docker.com/notary" repo, cs, err := testutils.EmptyRepo(gun) require.NoError(t, err) r, tg, sn, ts, err := testutils.Sign(repo) require.NoError(t, err) root, targets, snapshot, timestamp, err := getUpdates(r, tg, sn, ts) require.NoError(t, err) updates := []storage.MetaUpdate{root, targets, snapshot} store := storage.NewMemStorage() store.UpdateCurrent(gun, timestamp) serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole) updates, err = validateUpdate(serverCrypto, gun, updates, store) require.NoError(t, err) // we generated our own timestamp, and did not take the other timestamp, // but all other metadata should come from updates var foundTimestamp bool for _, update := range updates { if update.Role == data.CanonicalTimestampRole { foundTimestamp = true oldTimestamp, newTimestamp := &data.SignedTimestamp{}, &data.SignedTimestamp{} require.NoError(t, json.Unmarshal(timestamp.Data, oldTimestamp)) require.NoError(t, json.Unmarshal(update.Data, newTimestamp)) require.Equal(t, oldTimestamp.Signed.Version+1, newTimestamp.Signed.Version) } } require.True(t, foundTimestamp) }
// We cannot validate a new root if the old root is corrupt, because there might // have been a root key rotation. func TestValidateOldRootCorruptRootRole(t *testing.T) { gun := "docker.com/notary" repo, cs, err := testutils.EmptyRepo(gun) require.NoError(t, err) store := storage.NewMemStorage() r, tg, sn, ts, err := testutils.Sign(repo) require.NoError(t, err) root, targets, snapshot, timestamp, err := getUpdates(r, tg, sn, ts) require.NoError(t, err) // so a valid root, but missing the root role signedRoot, err := data.RootFromSigned(r) require.NoError(t, err) delete(signedRoot.Signed.Roles, data.CanonicalRootRole) badRootJSON, err := json.Marshal(signedRoot) require.NoError(t, err) badRoot := storage.MetaUpdate{ Version: root.Version, Role: root.Role, Data: badRootJSON, } store.UpdateCurrent(gun, badRoot) updates := []storage.MetaUpdate{root, targets, snapshot, timestamp} serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole) _, err = validateUpdate(serverCrypto, gun, updates, store) require.Error(t, err) require.IsType(t, data.ErrInvalidMetadata{}, err) }
func TestValidateTargetsModifiedHash(t *testing.T) { gun := "docker.com/notary" repo, cs, err := testutils.EmptyRepo(gun) require.NoError(t, err) store := storage.NewMemStorage() r, tg, sn, ts, err := testutils.Sign(repo) require.NoError(t, err) snap, err := data.SnapshotFromSigned(sn) require.NoError(t, err) snap.Signed.Meta["targets"].Hashes["sha256"][0] = snap.Signed.Meta["targets"].Hashes["sha256"][0] ^ 0xff sn, err = snap.ToSigned() require.NoError(t, err) root, targets, snapshot, timestamp, err := getUpdates(r, tg, sn, ts) require.NoError(t, err) updates := []storage.MetaUpdate{root, targets, snapshot, timestamp} serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole) _, err = validateUpdate(serverCrypto, gun, updates, store) require.Error(t, err) require.IsType(t, validation.ErrBadSnapshot{}, err) }
func TestValidateRootCanContainOnlyx509KeysWithRightGun(t *testing.T) { gun := "docker.com/notary" repo, cs, err := testutils.EmptyRepo("wrong/gun") require.NoError(t, err) serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole) // if the root has the wrong gun, the server will fail to validate r, tg, sn, ts, err := testutils.Sign(repo) require.NoError(t, err) root, targets, snapshot, timestamp, err := getUpdates(r, tg, sn, ts) require.NoError(t, err) _, err = validateUpdate(serverCrypto, gun, []storage.MetaUpdate{root, targets, snapshot, timestamp}, storage.NewMemStorage()) require.Error(t, err) require.IsType(t, validation.ErrBadRoot{}, err) // create regular non-x509 keys - change the root keys to one that is not // an x509 key - it should also fail to validate newRootKey, err := cs.Create(data.CanonicalRootRole, gun, data.ECDSAKey) require.NoError(t, err) require.NoError(t, repo.ReplaceBaseKeys(data.CanonicalRootRole, newRootKey)) r, tg, sn, ts, err = testutils.Sign(repo) require.NoError(t, err) root, targets, snapshot, timestamp, err = getUpdates(r, tg, sn, ts) require.NoError(t, err) _, err = validateUpdate(serverCrypto, gun, []storage.MetaUpdate{root, targets, snapshot, timestamp}, storage.NewMemStorage()) require.Error(t, err) require.IsType(t, validation.ErrBadRoot{}, err) }
// ### Snapshot size mismatch negative tests ### func TestValidateRootModifiedSize(t *testing.T) { gun := "docker.com/notary" repo, cs, err := testutils.EmptyRepo(gun) require.NoError(t, err) store := storage.NewMemStorage() r, tg, sn, ts, err := testutils.Sign(repo) require.NoError(t, err) // add another copy of the signature so the hash is different r.Signatures = append(r.Signatures, r.Signatures[0]) root, targets, snapshot, timestamp, err := getUpdates(r, tg, sn, ts) require.NoError(t, err) // flip all the bits in the first byte root.Data[0] = root.Data[0] ^ 0xff updates := []storage.MetaUpdate{root, targets, snapshot, timestamp} serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole) _, err = validateUpdate(serverCrypto, gun, updates, store) require.Error(t, err) require.IsType(t, validation.ErrBadRoot{}, err) }
func TestCreateSnapshotNoKeyInCrypto(t *testing.T) { store := storage.NewMemStorage() repo, _, err := testutils.EmptyRepo("gun") require.NoError(t, err) sgnd, err := repo.SignRoot(data.DefaultExpires(data.CanonicalRootRole)) require.NoError(t, err) rootJSON, err := json.Marshal(sgnd) require.NoError(t, err) // create an expired snapshot sgnd, err = repo.SignSnapshot(time.Now().AddDate(-1, -1, -1)) require.True(t, repo.Snapshot.Signed.Expires.Before(time.Now())) require.NoError(t, err) snapshotJSON, err := json.Marshal(sgnd) require.NoError(t, err) // set all the metadata so we know the failure to sign is just because of the key require.NoError(t, store.UpdateCurrent("gun", storage.MetaUpdate{Role: data.CanonicalRootRole, Version: 0, Data: rootJSON})) require.NoError(t, store.UpdateCurrent("gun", storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 0, Data: snapshotJSON})) hashBytes := sha256.Sum256(snapshotJSON) hashHex := hex.EncodeToString(hashBytes[:]) // pass it a new cryptoservice without the key _, _, err = GetOrCreateSnapshot("gun", hashHex, store, signed.NewEd25519()) require.Error(t, err) require.IsType(t, signed.ErrInsufficientSignatures{}, err) }
func TestValidateSnapshotGenerate(t *testing.T) { gun := "docker.com/notary" repo, cs, err := testutils.EmptyRepo(gun) require.NoError(t, err) store := storage.NewMemStorage() snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole) require.NoError(t, err) for _, k := range snapRole.Keys { err := store.SetKey(gun, data.CanonicalSnapshotRole, k.Algorithm(), k.Public()) require.NoError(t, err) } r, tg, sn, ts, err := testutils.Sign(repo) require.NoError(t, err) root, targets, _, _, err := getUpdates(r, tg, sn, ts) require.NoError(t, err) updates := []storage.MetaUpdate{targets} store.UpdateCurrent(gun, root) serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole) _, err = validateUpdate(serverCrypto, gun, updates, store) require.NoError(t, err) }
func TestValidateSnapshotGeneratePrevCorrupt(t *testing.T) { kdb, repo, cs := testutils.EmptyRepo() store := storage.NewMemStorage() snapRole := kdb.GetRole(data.CanonicalSnapshotRole) for _, id := range snapRole.KeyIDs { k := kdb.GetKey(id) assert.NotNil(t, k) err := store.SetKey("testGUN", data.CanonicalSnapshotRole, k.Algorithm(), k.Public()) assert.NoError(t, err) } r, tg, sn, ts, err := testutils.Sign(repo) assert.NoError(t, err) root, targets, snapshot, _, err := getUpdates(r, tg, sn, ts) assert.NoError(t, err) updates := []storage.MetaUpdate{root, targets} // corrupt the JSON structure of prev snapshot snapshot.Data = snapshot.Data[1:] // set the current snapshot in the store manually so we find it when generating // the next version store.UpdateCurrent("testGUN", snapshot) copyTimestampKey(t, kdb, store, "testGUN") updates, err = validateUpdate(cs, "testGUN", updates, store) assert.Error(t, err) }
// If the timestamp role has a threshold > 1, validation fails. func TestValidateRootInvalidTimestampThreshold(t *testing.T) { gun := "docker.com/notary" oldRepo, cs, err := testutils.EmptyRepo(gun) require.NoError(t, err) tsKey2, err := testutils.CreateKey(cs, gun, "timestamp2", data.ECDSAKey) require.NoError(t, err) oldRepo.AddBaseKeys(data.CanonicalTimestampRole, tsKey2) tsRole, ok := oldRepo.Root.Signed.Roles[data.CanonicalTimestampRole] require.True(t, ok) tsRole.Threshold = 2 r, tg, sn, ts, err := testutils.Sign(oldRepo) require.NoError(t, err) root, targets, snapshot, _, err := getUpdates(r, tg, sn, ts) require.NoError(t, err) store := storage.NewMemStorage() updates := []storage.MetaUpdate{root, targets, snapshot} serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole) _, err = validateUpdate(serverCrypto, gun, updates, store) require.Error(t, err) require.IsType(t, validation.ErrBadRoot{}, err) }
// If there is no timestamp key in the store, validation fails. This could // happen if pushing an existing repository from one server to another that // does not have the repo. func TestValidateRootNoTimestampKey(t *testing.T) { _, oldRepo, cs := testutils.EmptyRepo() r, tg, sn, ts, err := testutils.Sign(oldRepo) assert.NoError(t, err) root, targets, snapshot, _, err := getUpdates(r, tg, sn, ts) assert.NoError(t, err) store := storage.NewMemStorage() updates := []storage.MetaUpdate{root, targets, snapshot} // sanity check - no timestamp keys for the GUN _, _, err = store.GetKey("testGUN", data.CanonicalTimestampRole) assert.Error(t, err) assert.IsType(t, &storage.ErrNoKey{}, err) // do not copy the targets key to the storage, and try to update the root _, err = validateUpdate(cs, "testGUN", updates, store) assert.Error(t, err) assert.IsType(t, validation.ErrBadRoot{}, err) // there should still be no timestamp keys - one should not have been // created _, _, err = store.GetKey("testGUN", data.CanonicalTimestampRole) assert.Error(t, err) }
func TestValidateSnapshotGenerate(t *testing.T) { repo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) store := storage.NewMemStorage() snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole) assert.NoError(t, err) for _, k := range snapRole.Keys { err := store.SetKey("testGUN", data.CanonicalSnapshotRole, k.Algorithm(), k.Public()) assert.NoError(t, err) } r, tg, sn, ts, err := testutils.Sign(repo) assert.NoError(t, err) root, targets, _, _, err := getUpdates(r, tg, sn, ts) assert.NoError(t, err) updates := []storage.MetaUpdate{targets} store.UpdateCurrent("testGUN", root) copyTimestampKey(t, repo, store, "testGUN") updates, err = validateUpdate(cs, "testGUN", updates, store) assert.NoError(t, err) }
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) }
func TestValidateTargetsModifiedHash(t *testing.T) { repo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) store := storage.NewMemStorage() r, tg, sn, ts, err := testutils.Sign(repo) assert.NoError(t, err) snap, err := data.SnapshotFromSigned(sn) assert.NoError(t, err) snap.Signed.Meta["targets"].Hashes["sha256"][0] = snap.Signed.Meta["targets"].Hashes["sha256"][0] ^ 0xff sn, err = snap.ToSigned() assert.NoError(t, err) root, targets, snapshot, timestamp, err := getUpdates(r, tg, sn, ts) assert.NoError(t, err) updates := []storage.MetaUpdate{root, targets, snapshot, timestamp} copyTimestampKey(t, repo, store, "testGUN") _, err = validateUpdate(cs, "testGUN", updates, store) assert.Error(t, err) assert.IsType(t, validation.ErrBadSnapshot{}, err) }
// Ensures that the httpstore can interpret the errors returned from the server func TestValidationErrorFormat(t *testing.T) { ctx := context.WithValue( context.Background(), notary.CtxKeyMetaStore, storage.NewMemStorage()) ctx = context.WithValue(ctx, notary.CtxKeyKeyAlgo, data.ED25519Key) handler := RootHandler(ctx, nil, signed.NewEd25519(), nil, nil, nil) server := httptest.NewServer(handler) defer server.Close() client, err := store.NewHTTPStore( fmt.Sprintf("%s/v2/docker.com/notary/_trust/tuf/", server.URL), "", "json", "key", http.DefaultTransport, ) require.NoError(t, err) repo, _, err := testutils.EmptyRepo("docker.com/notary") require.NoError(t, err) r, tg, sn, ts, err := testutils.Sign(repo) require.NoError(t, err) rs, rt, _, _, err := testutils.Serialize(r, tg, sn, ts) require.NoError(t, err) // No snapshot is passed, and the server doesn't have the snapshot key, // so ErrBadHierarchy err = client.SetMulti(map[string][]byte{ data.CanonicalRootRole: rs, data.CanonicalTargetsRole: rt, }) require.Error(t, err) require.IsType(t, validation.ErrBadHierarchy{}, err) }
func TestValidateNoRoot(t *testing.T) { _, repo, _ := testutils.EmptyRepo() store := storage.NewMemStorage() r, tg, sn, ts, err := testutils.Sign(repo) assert.NoError(t, err) _, targets, snapshot, timestamp, err := testutils.Serialize(r, tg, sn, ts) assert.NoError(t, err) updates := []storage.MetaUpdate{ { Role: "targets", Version: 1, Data: targets, }, { Role: "snapshot", Version: 1, Data: snapshot, }, { Role: "timestamp", Version: 1, Data: timestamp, }, } err = validateUpdate("testGUN", updates, store) assert.Error(t, err) assert.IsType(t, ErrValidation{}, err) }
func TestApplyTargetsDelegationInvalidRole(t *testing.T) { repo, cs, err := testutils.EmptyRepo("docker.com/notary") require.NoError(t, err) newKey, err := cs.Create("targets/level1", "docker.com/notary", data.ED25519Key) require.NoError(t, err) // create delegation kl := data.KeyList{newKey} td := &changelist.TUFDelegation{ NewThreshold: 1, AddKeys: kl, AddPaths: []string{"level1"}, } tdJSON, err := json.Marshal(td) require.NoError(t, err) ch := changelist.NewTUFChange( changelist.ActionCreate, "bad role", changelist.TypeTargetsDelegation, "", tdJSON, ) err = applyTargetsChange(repo, nil, ch) require.Error(t, err) }
func TestValidateSnapshotMissing(t *testing.T) { _, repo, _ := testutils.EmptyRepo() store := storage.NewMemStorage() r, tg, sn, ts, err := testutils.Sign(repo) assert.NoError(t, err) root, targets, _, _, err := testutils.Serialize(r, tg, sn, ts) assert.NoError(t, err) updates := []storage.MetaUpdate{ { Role: "root", Version: 1, Data: root, }, { Role: "targets", Version: 1, Data: targets, }, } err = validateUpdate("testGUN", updates, store) assert.Error(t, err) assert.IsType(t, ErrBadHierarchy{}, err) }
func TestApplyTargetsDelegationInvalidJSONContent(t *testing.T) { repo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) newKey, err := cs.Create("targets/level1", data.ED25519Key) assert.NoError(t, err) // create delegation kl := data.KeyList{newKey} td := &changelist.TufDelegation{ NewThreshold: 1, AddKeys: kl, AddPaths: []string{"level1"}, } tdJSON, err := json.Marshal(td) assert.NoError(t, err) ch := changelist.NewTufChange( changelist.ActionCreate, "targets/level1", changelist.TypeTargetsDelegation, "", tdJSON[1:], ) err = applyTargetsChange(repo, ch) assert.Error(t, err) }
// If the root is missing or corrupt, no snapshot can be generated func TestCannotMakeNewSnapshotIfNoRoot(t *testing.T) { repo, crypto, err := testutils.EmptyRepo("gun") require.NoError(t, err) // create an expired snapshot _, err = repo.SignSnapshot(time.Now().AddDate(-1, -1, -1)) require.True(t, repo.Snapshot.Signed.Expires.Before(time.Now())) require.NoError(t, err) snapshotJSON, err := json.Marshal(repo.Snapshot) require.NoError(t, err) for _, rootJSON := range [][]byte{nil, []byte("invalid JSON")} { store := storage.NewMemStorage() if rootJSON != nil { require.NoError(t, store.UpdateCurrent("gun", storage.MetaUpdate{Role: data.CanonicalRootRole, Version: 0, Data: rootJSON})) } require.NoError(t, store.UpdateCurrent("gun", storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 1, Data: snapshotJSON})) hashBytes := sha256.Sum256(snapshotJSON) hashHex := hex.EncodeToString(hashBytes[:]) _, _, err := GetOrCreateSnapshot("gun", hashHex, store, crypto) require.Error(t, err, "GetSnapshot errored") if rootJSON == nil { // missing metadata require.IsType(t, storage.ErrNotFound{}, err) } else { require.IsType(t, &json.SyntaxError{}, err) } } }
// If applying a change fails due to a prefix error, it does not fall back // on the parent. func TestChangeTargetMetaDoesntFallbackIfPrefixError(t *testing.T) { repo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) newKey, err := cs.Create("targets/level1", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole("targets/level1", 1, []string{newKey.ID()}, []string{"pathprefix"}) assert.NoError(t, err) repo.UpdateDelegations(r, []data.PublicKey{newKey}) hash := sha256.Sum256([]byte{}) f := &data.FileMeta{ Length: 1, Hashes: map[string][]byte{ "sha256": hash[:], }, } fjson, err := json.Marshal(f) assert.NoError(t, err) err = changeTargetMeta(repo, &changelist.TufChange{ Actn: changelist.ActionCreate, Role: "targets/level1", ChangeType: "target", ChangePath: "notPathPrefix", Data: fjson, }) assert.Error(t, err) // no target in targets or targets/latest assert.Empty(t, repo.Targets[data.CanonicalTargetsRole].Signed.Targets) assert.Empty(t, repo.Targets["targets/level1"].Signed.Targets) }
func TestBuilderLoadInvalidDelegationsOldVersion(t *testing.T) { gun := "docker.com/notary" tufRepo, _, err := testutils.EmptyRepo(gun, "targets/a", "targets/a/b", "targets/b") require.NoError(t, err) meta, err := testutils.SignAndSerialize(tufRepo) require.NoError(t, err) builder := tuf.NewBuilderFromRepo(gun, tufRepo, trustpinning.TrustPinConfig{}) delete(tufRepo.Targets, "targets/a") // load targets/a with high min-version so this one is too old err = builder.Load( "targets/a", meta["targets/a"], 10, false, ) require.Error(t, err) require.IsType(t, signed.ErrLowVersion{}, err) _, invalid, err := builder.Finish() require.NoError(t, err) _, ok := invalid.Targets["targets/a"] require.False(t, ok) }