Example #1
0
func (m *memoryStore) WalkStagedTargets(paths []string, targetsFn targetsWalkFunc) error {
	if len(paths) == 0 {
		for path, dat := range m.files {
			meta, err := data.NewFileMeta(bytes.NewReader(dat), "sha256")
			if err != nil {
				return err
			}
			if err = targetsFn(path, meta); err != nil {
				return err
			}
		}
		return nil
	}

	for _, path := range paths {
		dat, ok := m.files[path]
		if !ok {
			return ErrMetaNotFound{Resource: path}
		}
		meta, err := data.NewFileMeta(bytes.NewReader(dat), "sha256")
		if err != nil {
			return err
		}
		if err = targetsFn(path, meta); err != nil {
			return err
		}
	}
	return nil
}
Example #2
0
func TestGetSnapshotCurrValid(t *testing.T) {
	store := storage.NewMemStorage()
	crypto := signed.NewEd25519()

	_, err := GetOrCreateSnapshotKey("gun", store, crypto, data.ED25519Key)

	newData := []byte{2}
	currMeta, err := data.NewFileMeta(bytes.NewReader(newData), "sha256")
	assert.NoError(t, err)

	snapshot := &data.SignedSnapshot{
		Signed: data.Snapshot{
			Expires: data.DefaultExpires(data.CanonicalSnapshotRole),
			Meta: data.Files{
				data.CanonicalRootRole: currMeta,
			},
		},
	}
	snapJSON, _ := json.Marshal(snapshot)

	// test when db is missing the role data
	store.UpdateCurrent("gun", storage.MetaUpdate{Role: "snapshot", Version: 0, Data: snapJSON})
	_, err = GetOrCreateSnapshot("gun", store, crypto)
	assert.NoError(t, err)

	// test when db has the role data
	store.UpdateCurrent("gun", storage.MetaUpdate{Role: "root", Version: 0, Data: newData})
	_, err = GetOrCreateSnapshot("gun", store, crypto)
	assert.NoError(t, err)

	// test when db role data is expired
	store.UpdateCurrent("gun", storage.MetaUpdate{Role: "root", Version: 1, Data: []byte{3}})
	_, err = GetOrCreateSnapshot("gun", store, crypto)
	assert.NoError(t, err)
}
Example #3
0
// 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
}
Example #4
0
// No matter what order timestamp and snapshot is loaded, if the snapshot's checksum doesn't match
// what's in the timestamp, the builder will error and refuse to load the latest piece of metadata
// whether that is snapshot (because it was loaded after timestamp) or timestamp (because builder
// retroactive checks the loaded snapshot's checksum).  Timestamp ONLY checks the snapshot checksum.
func TestTimestampPreAndPostChecksumming(t *testing.T) {
	gun := "docker.com/notary"
	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)
	for _, roleName := range append(data.BaseRoles, "targets/other") {
		// add a wrong checksum for every role, including timestamp itself
		repo.Timestamp.Signed.Meta[roleName] = fakeChecksum
	}
	// this will overwrite the snapshot checksum with the right one
	meta, err := testutils.SignAndSerialize(repo)
	require.NoError(t, err)
	// ensure that the fake meta for other roles weren't destroyed by signing the timestamp
	require.Len(t, repo.Timestamp.Signed.Meta, 5)

	snapJSON := append(meta[data.CanonicalSnapshotRole], ' ')

	// --- load timestamp first
	builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
	require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
	// timestamp doesn't fail, even though its checksum for root is wrong according to timestamp
	require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 1, false))
	// loading the snapshot in fails, because of the checksum the timestamp has
	err = builder.Load(data.CanonicalSnapshotRole, snapJSON, 1, false)
	require.Error(t, err)
	require.IsType(t, data.ErrMismatchedChecksum{}, err)
	require.True(t, builder.IsLoaded(data.CanonicalTimestampRole))
	require.False(t, builder.IsLoaded(data.CanonicalSnapshotRole))
	// all the other metadata can be loaded in, even though the checksums are wrong according to timestamp
	for _, roleName := range []string{data.CanonicalTargetsRole, "targets/other"} {
		require.NoError(t, builder.Load(roleName, meta[roleName], 1, false))
	}

	// --- load snapshot first
	builder = tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
	for _, roleName := range append(data.BaseRoles, "targets/other") {
		switch roleName {
		case data.CanonicalTimestampRole:
			continue
		case data.CanonicalSnapshotRole:
			require.NoError(t, builder.Load(roleName, snapJSON, 1, false))
		default:
			require.NoError(t, builder.Load(roleName, meta[roleName], 1, false))
		}
	}
	// timestamp fails because the snapshot checksum is wrong
	err = builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 1, false)
	require.Error(t, err)
	checksumErr, ok := err.(data.ErrMismatchedChecksum)
	require.True(t, ok)
	require.Contains(t, checksumErr.Error(), "checksum for snapshot did not match")
	require.False(t, builder.IsLoaded(data.CanonicalTimestampRole))
	require.True(t, builder.IsLoaded(data.CanonicalSnapshotRole))
}
Example #5
0
func snapshotExpired(ts *data.SignedTimestamp, snapshot []byte) bool {
	meta, err := data.NewFileMeta(bytes.NewReader(snapshot), "sha256")
	if err != nil {
		// if we can't generate FileMeta from the current snapshot, we should
		// continue to serve the old timestamp if it isn't time expired
		// because we won't be able to generate a new one.
		return false
	}
	hash := meta.Hashes["sha256"]
	return !bytes.Equal(hash, ts.Signed.Meta["snapshot"].Hashes["sha256"])
}
Example #6
0
// UpdateTimestamp updates the snapshot meta in the timestamp based on the Signed object
func (tr *Repo) UpdateTimestamp(s *data.Signed) error {
	jsonData, err := json.Marshal(s)
	if err != nil {
		return err
	}
	meta, err := data.NewFileMeta(bytes.NewReader(jsonData), data.NotaryDefaultHashes...)
	if err != nil {
		return err
	}
	tr.Timestamp.Signed.Meta[data.CanonicalSnapshotRole] = meta
	tr.Timestamp.Dirty = true
	return nil
}
Example #7
0
// UpdateSnapshot updates the FileMeta for the given role based on the Signed object
func (tr *Repo) UpdateSnapshot(role string, s *data.Signed) error {
	jsonData, err := json.Marshal(s)
	if err != nil {
		return err
	}
	meta, err := data.NewFileMeta(bytes.NewReader(jsonData), data.NotaryDefaultHashes...)
	if err != nil {
		return err
	}
	tr.Snapshot.Signed.Meta[role] = meta
	tr.Snapshot.Dirty = true
	return nil
}
Example #8
0
// NewTarget is a helper method that returns a Target
func NewTarget(targetName string, targetPath string) (*Target, error) {
	b, err := ioutil.ReadFile(targetPath)
	if err != nil {
		return nil, err
	}

	meta, err := data.NewFileMeta(bytes.NewBuffer(b))
	if err != nil {
		return nil, err
	}

	return &Target{Name: targetName, Hashes: meta.Hashes, Length: meta.Length}, nil
}
Example #9
0
// UpdateTimestamp updates the snapshot meta in the timestamp based on the Signed object
func (tr *Repo) UpdateTimestamp(s *data.Signed) error {
	jsonData, err := json.MarshalCanonical(s)
	if err != nil {
		return err
	}
	meta, err := data.NewFileMeta(bytes.NewReader(jsonData), "sha256")
	if err != nil {
		return err
	}
	tr.Timestamp.Signed.Meta["snapshot"] = meta
	tr.Timestamp.Dirty = true
	return nil
}
Example #10
0
func TestBuilderLoadInvalidDelegations(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{})

	// modify targets/a to remove the signature and update the snapshot
	// (we're not going to load the timestamp so no need to modify)
	targetsAJSON := meta["targets/a"]
	targetsA := data.Signed{}
	err = json.Unmarshal(targetsAJSON, &targetsA)
	require.NoError(t, err)
	targetsA.Signatures = make([]data.Signature, 0)
	targetsAJSON, err = json.Marshal(&targetsA)
	require.NoError(t, err)
	meta["targets/a"] = targetsAJSON
	delete(tufRepo.Targets, "targets/a")

	snap := tufRepo.Snapshot
	m, err := data.NewFileMeta(
		bytes.NewReader(targetsAJSON),
		"sha256", "sha512",
	)
	require.NoError(t, err)
	snap.AddMeta("targets/a", m)

	// load snapshot directly into repo to bypass signature check (we've invalidated
	// the signature by modifying it)
	tufRepo.Snapshot = snap

	// load targets/a
	require.Error(
		t,
		builder.Load(
			"targets/a",
			meta["targets/a"],
			1,
			false,
		),
	)

	_, invalid, err := builder.Finish()
	require.NoError(t, err)
	_, ok := invalid.Targets["targets/a"]
	require.True(t, ok)
}
Example #11
0
// UpdateSnapshotHashes updates the snapshot to reflect the latest hash changes, to
// ensure that failure isn't because the snapshot has the wrong hash.
func (m *MetadataSwizzler) UpdateSnapshotHashes(roles ...string) error {
	var (
		metaBytes      []byte
		snapshotSigned *data.Signed
		err            error
	)
	if metaBytes, err = m.MetadataCache.GetSized(data.CanonicalSnapshotRole, store.NoSizeLimit); err != nil {
		return err
	}

	snapshot := data.SignedSnapshot{}
	if err = json.Unmarshal(metaBytes, &snapshot); err != nil {
		return err
	}

	// just rebuild everything if roles is not specified
	if len(roles) == 0 {
		roles = m.Roles
	}

	for _, role := range roles {
		if role != data.CanonicalSnapshotRole && role != data.CanonicalTimestampRole {
			if metaBytes, err = m.MetadataCache.GetSized(role, store.NoSizeLimit); err != nil {
				return err
			}

			meta, err := data.NewFileMeta(bytes.NewReader(metaBytes), data.NotaryDefaultHashes...)
			if err != nil {
				return err
			}

			snapshot.Signed.Meta[role] = meta
		}
	}

	if snapshotSigned, err = snapshot.ToSigned(); err != nil {
		return err
	}
	pubKeys, err := getPubKeys(m.CryptoService, snapshotSigned, data.CanonicalSnapshotRole)
	if err == nil {
		metaBytes, err = serializeMetadata(m.CryptoService, snapshotSigned, data.CanonicalSnapshotRole, pubKeys...)
	}

	if err != nil {
		return err
	}
	return m.MetadataCache.Set(data.CanonicalSnapshotRole, metaBytes)
}
Example #12
0
// UpdateTimestampHash updates the timestamp to reflect the latest snapshot changes, to
// ensure that failure isn't because the timestamp has the wrong hash.
func (m *MetadataSwizzler) UpdateTimestampHash() error {
	var (
		metaBytes       []byte
		timestamp       = &data.SignedTimestamp{}
		timestampSigned *data.Signed
		err             error
	)
	if metaBytes, err = m.MetadataCache.GetSized(data.CanonicalTimestampRole, store.NoSizeLimit); err != nil {
		return err
	}
	// we can't just create a new timestamp, because then the expiry would be
	// different
	if err = json.Unmarshal(metaBytes, timestamp); err != nil {
		return err
	}

	if metaBytes, err = m.MetadataCache.GetSized(data.CanonicalSnapshotRole, store.NoSizeLimit); err != nil {
		return err
	}

	snapshotMeta, err := data.NewFileMeta(bytes.NewReader(metaBytes), data.NotaryDefaultHashes...)
	if err != nil {
		return err
	}

	timestamp.Signed.Meta[data.CanonicalSnapshotRole] = snapshotMeta

	timestampSigned, err = timestamp.ToSigned()
	if err != nil {
		return err
	}
	pubKeys, err := getPubKeys(m.CryptoService, timestampSigned, data.CanonicalTimestampRole)
	if err == nil {
		metaBytes, err = serializeMetadata(m.CryptoService, timestampSigned, data.CanonicalTimestampRole, pubKeys...)
	}

	if err != nil {
		return err
	}
	return m.MetadataCache.Set(data.CanonicalTimestampRole, metaBytes)
}