Beispiel #1
0
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)
}
Beispiel #2
0
// NewSnapshot initilizes a SignedSnapshot with a given top level root
// and targets objects
func NewSnapshot(root *Signed, targets *Signed) (*SignedSnapshot, error) {
	logrus.Debug("generating new snapshot...")
	targetsJSON, err := json.Marshal(targets)
	if err != nil {
		logrus.Debug("Error Marshalling Targets")
		return nil, err
	}
	rootJSON, err := json.Marshal(root)
	if err != nil {
		logrus.Debug("Error Marshalling Root")
		return nil, err
	}
	rootMeta, err := NewFileMeta(bytes.NewReader(rootJSON), NotaryDefaultHashes...)
	if err != nil {
		return nil, err
	}
	targetsMeta, err := NewFileMeta(bytes.NewReader(targetsJSON), NotaryDefaultHashes...)
	if err != nil {
		return nil, err
	}
	return &SignedSnapshot{
		Signatures: make([]Signature, 0),
		Signed: Snapshot{
			SignedCommon: SignedCommon{
				Type:    TUFTypes[CanonicalSnapshotRole],
				Version: 0,
				Expires: DefaultExpires(CanonicalSnapshotRole),
			},
			Meta: Files{
				CanonicalRootRole:    rootMeta,
				CanonicalTargetsRole: targetsMeta,
			},
		},
	}, nil
}
Beispiel #3
0
// 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)
		}
	}
}
Beispiel #4
0
// If there is no previous snapshot or the previous snapshot is corrupt, then
// even if everything else is in place, getting the snapshot fails
func TestGetSnapshotNoPreviousSnapshot(t *testing.T) {
	repo, crypto, 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)

	for _, snapshotJSON := range [][]byte{nil, []byte("invalid JSON")} {
		store := storage.NewMemStorage()

		// so we know it's not a failure in getting root
		require.NoError(t,
			store.UpdateCurrent("gun", storage.MetaUpdate{Role: data.CanonicalRootRole, Version: 0, Data: rootJSON}))

		if snapshotJSON != nil {
			require.NoError(t,
				store.UpdateCurrent("gun",
					storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 0, Data: snapshotJSON}))
		}

		hashBytes := sha256.Sum256(snapshotJSON)
		hashHex := hex.EncodeToString(hashBytes[:])

		_, _, err = GetOrCreateSnapshot("gun", hashHex, store, crypto)
		require.Error(t, err, "GetSnapshot should have failed")
		if snapshotJSON == nil {
			require.IsType(t, storage.ErrNotFound{}, err)
		} else {
			require.IsType(t, &json.SyntaxError{}, err)
		}
	}
}
Beispiel #5
0
func TestCreateTimestampNoKeyInCrypto(t *testing.T) {
	store := storage.NewMemStorage()
	repo, _, err := testutils.EmptyRepo("gun")
	require.NoError(t, err)

	meta, err := testutils.SignAndSerialize(repo)
	require.NoError(t, err)

	// create an expired timestamp
	_, err = repo.SignTimestamp(time.Now().AddDate(-1, -1, -1))
	require.True(t, repo.Timestamp.Signed.Expires.Before(time.Now()))
	require.NoError(t, err)
	timestampJSON, err := json.Marshal(repo.Timestamp)
	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: meta[data.CanonicalRootRole]}))
	require.NoError(t, store.UpdateCurrent("gun",
		storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 0, Data: meta[data.CanonicalSnapshotRole]}))
	require.NoError(t, store.UpdateCurrent("gun",
		storage.MetaUpdate{Role: data.CanonicalTimestampRole, Version: 1, Data: timestampJSON}))

	// pass it a new cryptoservice without the key
	_, _, err = GetOrCreateTimestamp("gun", store, signed.NewEd25519())
	require.Error(t, err)
	require.IsType(t, signed.ErrInsufficientSignatures{}, err)
}
Beispiel #6
0
// 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)
}
Beispiel #7
0
func TestGetTimestampOldTimestampExpired(t *testing.T) {
	store := storage.NewMemStorage()
	repo, crypto, err := testutils.EmptyRepo("gun")
	require.NoError(t, err)

	meta, err := testutils.SignAndSerialize(repo)
	require.NoError(t, err)

	// create an expired timestamp
	_, err = repo.SignTimestamp(time.Now().AddDate(-1, -1, -1))
	require.True(t, repo.Timestamp.Signed.Expires.Before(time.Now()))
	require.NoError(t, err)
	timestampJSON, err := json.Marshal(repo.Timestamp)
	require.NoError(t, err)

	// set all the metadata
	require.NoError(t, store.UpdateCurrent("gun",
		storage.MetaUpdate{Role: data.CanonicalRootRole, Version: 0, Data: meta[data.CanonicalRootRole]}))
	require.NoError(t, store.UpdateCurrent("gun",
		storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 0, Data: meta[data.CanonicalSnapshotRole]}))
	require.NoError(t, store.UpdateCurrent("gun",
		storage.MetaUpdate{Role: data.CanonicalTimestampRole, Version: 1, Data: timestampJSON}))

	_, gottenTimestamp, err := GetOrCreateTimestamp("gun", store, crypto)
	require.NoError(t, err, "GetTimestamp errored")

	require.False(t, bytes.Equal(timestampJSON, gottenTimestamp),
		"Timestamp was not regenerated when old one was expired")

	signedMeta := &data.SignedMeta{}
	require.NoError(t, json.Unmarshal(gottenTimestamp, signedMeta))
	// the new metadata is not expired
	require.True(t, signedMeta.Signed.Expires.After(time.Now()))
}
Beispiel #8
0
// Serialize takes the Signed objects for the 4 top level roles and serializes them all to JSON
func Serialize(sRoot, sTargets, sSnapshot, sTimestamp *data.Signed) (root, targets, snapshot, timestamp []byte, err error) {
	root, err = json.Marshal(sRoot)
	if err != nil {
		return nil, nil, nil, nil, err
	}
	targets, err = json.Marshal(sTargets)
	if err != nil {
		return nil, nil, nil, nil, err
	}
	snapshot, err = json.Marshal(sSnapshot)
	if err != nil {
		return nil, nil, nil, nil, err
	}
	timestamp, err = json.Marshal(sTimestamp)
	if err != nil {
		return nil, nil, nil, nil, err
	}
	return
}
Beispiel #9
0
// If the root or snapshot is missing or corrupt, no timestamp can be generated
func TestCannotMakeNewTimestampIfNoRootOrSnapshot(t *testing.T) {
	repo, crypto, err := testutils.EmptyRepo("gun")
	require.NoError(t, err)

	meta, err := testutils.SignAndSerialize(repo)
	require.NoError(t, err)

	// create an expired timestamp
	_, err = repo.SignTimestamp(time.Now().AddDate(-1, -1, -1))
	require.True(t, repo.Timestamp.Signed.Expires.Before(time.Now()))
	require.NoError(t, err)
	timestampJSON, err := json.Marshal(repo.Timestamp)
	require.NoError(t, err)

	rootJSON := meta[data.CanonicalRootRole]
	snapJSON := meta[data.CanonicalSnapshotRole]

	invalids := []struct {
		test map[string][]byte
		err  error
	}{
		{
			test: map[string][]byte{data.CanonicalRootRole: rootJSON, data.CanonicalSnapshotRole: []byte("invalid JSON")},
			err:  storage.ErrNotFound{},
		},
		{
			test: map[string][]byte{data.CanonicalRootRole: []byte("invalid JSON"), data.CanonicalSnapshotRole: snapJSON},
			err:  &json.SyntaxError{},
		},
		{
			test: map[string][]byte{data.CanonicalRootRole: rootJSON},
			err:  storage.ErrNotFound{},
		},
		{
			test: map[string][]byte{data.CanonicalSnapshotRole: snapJSON},
			err:  storage.ErrNotFound{},
		},
	}

	for _, test := range invalids {
		dataToSet := test.test
		store := storage.NewMemStorage()
		for roleName, jsonBytes := range dataToSet {
			require.NoError(t, store.UpdateCurrent("gun",
				storage.MetaUpdate{Role: roleName, Version: 0, Data: jsonBytes}))
		}
		require.NoError(t, store.UpdateCurrent("gun",
			storage.MetaUpdate{Role: data.CanonicalTimestampRole, Version: 1, Data: timestampJSON}))

		_, _, err := GetOrCreateTimestamp("gun", store, crypto)
		require.Error(t, err, "GetTimestamp errored")
		require.IsType(t, test.err, err)
	}
}
Beispiel #10
0
func TestGetSnapshotOldSnapshotExpired(t *testing.T) {
	store := storage.NewMemStorage()
	repo, crypto, 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
	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[:])

	_, gottenSnapshot, err := GetOrCreateSnapshot("gun", hashHex, store, crypto)
	require.NoError(t, err, "GetSnapshot errored")

	require.False(t, bytes.Equal(snapshotJSON, gottenSnapshot),
		"Snapshot was not regenerated when old one was expired")

	signedMeta := &data.SignedMeta{}
	require.NoError(t, json.Unmarshal(gottenSnapshot, signedMeta))
	// the new metadata is not expired
	require.True(t, signedMeta.Signed.Expires.After(time.Now()))
}
Beispiel #11
0
// GenerateTimestamp generates a new timestamp given a previous (optional) timestamp
// We can't just load the previous timestamp, because it may have been signed by a different
// timestamp key (maybe from a previous root version)
func (rb *repoBuilder) GenerateTimestamp(prev *data.SignedTimestamp) ([]byte, int, error) {
	switch {
	case rb.repo.cryptoService == nil:
		return nil, 0, ErrInvalidBuilderInput{msg: "cannot generate timestamp without a cryptoservice"}
	case rb.IsLoaded(data.CanonicalTimestampRole):
		return nil, 0, ErrInvalidBuilderInput{msg: "timestamp has already been loaded"}
	}

	// SignTimestamp always serializes the loaded snapshot and signs in the data, so we must always
	// have the snapshot loaded first
	if err := rb.checkPrereqsLoaded([]string{data.CanonicalRootRole, data.CanonicalSnapshotRole}); err != nil {
		return nil, 0, err
	}

	switch prev {
	case nil:
		if err := rb.repo.InitTimestamp(); err != nil {
			rb.repo.Timestamp = nil
			return nil, 0, err
		}
	default:
		if err := data.IsValidTimestampStructure(prev.Signed); err != nil {
			return nil, 0, err
		}
		rb.repo.Timestamp = prev
	}

	sgnd, err := rb.repo.SignTimestamp(data.DefaultExpires(data.CanonicalTimestampRole))
	if err != nil {
		rb.repo.Timestamp = nil
		return nil, 0, err
	}

	sgndJSON, err := json.Marshal(sgnd)
	if err != nil {
		rb.repo.Timestamp = nil
		return nil, 0, err
	}

	// The snapshot should have been loaded (and not checksummed, since a timestamp
	// cannot have been loaded), so it is awaiting checksumming. Since this
	// timestamp was generated using the snapshot awaiting checksumming, we can
	// remove it from rb.loadedNotChecksummed. There should be no other items
	// awaiting checksumming now since loading/generating a snapshot should have
	// cleared out everything else in `loadNotChecksummed`.
	delete(rb.loadedNotChecksummed, data.CanonicalSnapshotRole)

	return sgndJSON, rb.repo.Timestamp.Signed.Version, nil
}
Beispiel #12
0
// If it's a 400, translateStatusToError attempts to parse the body into
// an error.  If successful (and a recognized error) that error is returned.
func TestTranslateErrorsParse400Errors(t *testing.T) {
	origErr := validation.ErrBadRoot{Msg: "bad"}

	serialObj, err := validation.NewSerializableError(origErr)
	require.NoError(t, err)
	serialization, err := json.Marshal(serialObj)
	require.NoError(t, err)
	errorBody := bytes.NewBuffer([]byte(fmt.Sprintf(
		`{"errors": [{"otherstuff": "what", "detail": %s}]}`,
		string(serialization))))
	errorResp := http.Response{
		StatusCode: http.StatusBadRequest,
		Body:       ioutil.NopCloser(errorBody),
	}

	finalError := translateStatusToError(&errorResp, "")
	require.Equal(t, origErr, finalError)
}
Beispiel #13
0
// InvalidateMetadataSignatures signs with the right key(s) but wrong hash
func (m *MetadataSwizzler) InvalidateMetadataSignatures(role string) error {
	signedThing, err := signedFromStore(m.MetadataCache, role)
	if err != nil {
		return err
	}
	sigs := make([]data.Signature, len(signedThing.Signatures))
	for i, origSig := range signedThing.Signatures {
		sigs[i] = data.Signature{
			KeyID:     origSig.KeyID,
			Signature: []byte("invalid signature"),
			Method:    origSig.Method,
		}
	}
	signedThing.Signatures = sigs

	metaBytes, err := json.Marshal(signedThing)
	if err != nil {
		return err
	}
	return m.MetadataCache.Set(role, metaBytes)
}
Beispiel #14
0
// NewTimestamp initializes a timestamp with an existing snapshot
func NewTimestamp(snapshot *Signed) (*SignedTimestamp, error) {
	snapshotJSON, err := json.Marshal(snapshot)
	if err != nil {
		return nil, err
	}
	snapshotMeta, err := NewFileMeta(bytes.NewReader(snapshotJSON), "sha256")
	if err != nil {
		return nil, err
	}
	return &SignedTimestamp{
		Signatures: make([]Signature, 0),
		Signed: Timestamp{
			Type:    TUFTypes["timestamp"],
			Version: 0,
			Expires: DefaultExpires("timestamp"),
			Meta: Files{
				CanonicalSnapshotRole: snapshotMeta,
			},
		},
	}, nil
}
Beispiel #15
0
// GetOrCreateTimestamp returns the current timestamp for the gun. This may mean
// a new timestamp is generated either because none exists, or because the current
// one has expired. Once generated, the timestamp is saved in the store.
func GetOrCreateTimestamp(gun string, store storage.MetaStore, cryptoService signed.CryptoService) ([]byte, error) {
	snapshot, err := store.GetCurrent(gun, "snapshot")
	if err != nil {
		return nil, err
	}
	d, err := store.GetCurrent(gun, "timestamp")
	if err != nil {
		if _, ok := err.(storage.ErrNotFound); !ok {
			logrus.Error("error retrieving timestamp: ", err.Error())
			return nil, err
		}
		logrus.Debug("No timestamp found, will proceed to create first timestamp")
	}
	ts := &data.SignedTimestamp{}
	if d != nil {
		err := json.Unmarshal(d, ts)
		if err != nil {
			logrus.Error("Failed to unmarshal existing timestamp")
			return nil, err
		}
		if !timestampExpired(ts) && !snapshotExpired(ts, snapshot) {
			return d, nil
		}
	}
	sgnd, version, err := CreateTimestamp(gun, ts, snapshot, store, cryptoService)
	if err != nil {
		logrus.Error("Failed to create a new timestamp")
		return nil, err
	}
	out, err := json.Marshal(sgnd)
	if err != nil {
		logrus.Error("Failed to marshal new timestamp")
		return nil, err
	}
	err = store.UpdateCurrent(gun, storage.MetaUpdate{Role: "timestamp", Version: version, Data: out})
	if err != nil {
		return nil, err
	}
	return out, nil
}
Beispiel #16
0
// If there WAS a pre-existing snapshot, and it is not expired, then just return it (it doesn't
// load any other metadata that it doesn't need)
func TestGetSnapshotReturnsPreviousSnapshotIfUnexpired(t *testing.T) {
	store := storage.NewMemStorage()
	repo, crypto, err := testutils.EmptyRepo("gun")
	require.NoError(t, err)

	// create an expired snapshot
	sgnd, err := repo.SignSnapshot(data.DefaultExpires(data.CanonicalSnapshotRole))
	require.NoError(t, err)
	snapshotJSON, err := json.Marshal(sgnd)
	require.NoError(t, err)

	require.NoError(t, store.UpdateCurrent("gun",
		storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 0, Data: snapshotJSON}))

	hashBytes := sha256.Sum256(snapshotJSON)
	hashHex := hex.EncodeToString(hashBytes[:])

	// test when db is missing the role data (no root)
	_, gottenSnapshot, err := GetOrCreateSnapshot("gun", hashHex, store, crypto)
	require.NoError(t, err, "GetSnapshot should not have failed")
	require.True(t, bytes.Equal(snapshotJSON, gottenSnapshot))
}
Beispiel #17
0
func TestGetSnapshotKeyExistingMetadata(t *testing.T) {
	repo, crypto, 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)
	store := storage.NewMemStorage()
	require.NoError(t,
		store.UpdateCurrent("gun", storage.MetaUpdate{Role: data.CanonicalRootRole, Version: 0, Data: rootJSON}))

	snapshotRole, err := repo.Root.BuildBaseRole(data.CanonicalSnapshotRole)
	require.NoError(t, err)
	key, ok := snapshotRole.Keys[repo.Root.Signed.Roles[data.CanonicalSnapshotRole].KeyIDs[0]]
	require.True(t, ok)

	k, err := GetOrCreateSnapshotKey("gun", store, crypto, data.ED25519Key)
	require.Nil(t, err, "Expected nil error")
	require.NotNil(t, k, "Key should not be nil")
	require.Equal(t, key, k, "Did not receive same key when attempting to recreate.")
	require.NotNil(t, k, "Key should not be nil")

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

	require.Nil(t, err, "Expected nil error")

	require.Equal(t, k, k2, "Did not receive same key when attempting to recreate.")
	require.NotNil(t, k2, "Key should not be nil")

	// try wiping out the cryptoservice data, and ensure we create a new key because the signer doesn't hold the key specified by TUF
	crypto = signed.NewEd25519()
	k3, err := GetOrCreateSnapshotKey("gun", store, crypto, data.ED25519Key)
	require.Nil(t, err, "Expected nil error")
	require.NotEqual(t, k, k3, "Received same key when attempting to recreate.")
	require.NotEqual(t, k2, k3, "Received same key when attempting to recreate.")
	require.NotNil(t, k3, "Key should not be nil")
}
Beispiel #18
0
// NewTimestamp initializes a timestamp with an existing snapshot
func NewTimestamp(snapshot *Signed) (*SignedTimestamp, error) {
	snapshotJSON, err := json.Marshal(snapshot)
	if err != nil {
		return nil, err
	}
	snapshotMeta, err := NewFileMeta(bytes.NewReader(snapshotJSON), NotaryDefaultHashes...)
	if err != nil {
		return nil, err
	}
	return &SignedTimestamp{
		Signatures: make([]Signature, 0),
		Signed: Timestamp{
			SignedCommon: SignedCommon{
				Type:    TUFTypes[CanonicalTimestampRole],
				Version: 0,
				Expires: DefaultExpires(CanonicalTimestampRole),
			},
			Meta: Files{
				CanonicalSnapshotRole: snapshotMeta,
			},
		},
	}, nil
}
Beispiel #19
0
// signs the new metadata, replacing whatever signature was there
func serializeMetadata(cs signed.CryptoService, s *data.Signed, role string,
	pubKeys ...data.PublicKey) ([]byte, error) {

	// delete the existing signatures
	s.Signatures = []data.Signature{}

	if len(pubKeys) < 1 {
		return nil, ErrNoKeyForRole{role}
	}

	if err := signed.Sign(cs, s, pubKeys, 1, nil); err != nil {
		if _, ok := err.(signed.ErrInsufficientSignatures); ok {
			return nil, ErrNoKeyForRole{Role: role}
		}
		return nil, err
	}

	metaBytes, err := json.Marshal(s)
	if err != nil {
		return nil, err
	}

	return metaBytes, nil
}
Beispiel #20
0
// TestTUFSQLGetCurrent asserts that GetCurrent walks from the current timestamp metadata
// to the snapshot specified in the checksum, to potentially other role metadata by checksum
func TestTUFSQLGetCurrent(t *testing.T) {
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	gormDB, tufDBStore := SetupTUFSQLite(t, tempBaseDir)
	defer os.RemoveAll(tempBaseDir)
	defer gormDB.Close()

	initialRootTUFFile := SampleTUF(1)

	ConsistentEmptyGetCurrentTest(t, tufDBStore, initialRootTUFFile)

	// put an initial piece of root metadata data in the database,
	// there isn't enough state to retrieve it since we require a timestamp and snapshot in our walk

	query := gormDB.Create(&initialRootTUFFile)
	require.NoError(t, query.Error, "Creating a row in an empty DB failed.")

	ConsistentMissingTSAndSnapGetCurrentTest(t, tufDBStore, initialRootTUFFile)

	// Note that get by checksum succeeds, since it does not try to walk timestamp/snapshot
	_, _, err = tufDBStore.GetChecksum("testGUN", "root", initialRootTUFFile.Sha256)
	require.NoError(t, err)

	// Now setup a valid TUF repo and use it to ensure we walk correctly
	validTUFRepo, _, err := testutils.EmptyRepo("testGUN")
	require.NoError(t, err)

	// Add the timestamp, snapshot, targets, and root to the database
	tufData, err := json.Marshal(validTUFRepo.Timestamp)
	require.NoError(t, err)
	tsTUF := SampleCustomTUF(data.CanonicalTimestampRole, "testGUN", tufData, validTUFRepo.Timestamp.Signed.Version)
	query = gormDB.Create(&tsTUF)
	require.NoError(t, query.Error, "Creating a row for timestamp in DB failed.")

	tufData, err = json.Marshal(validTUFRepo.Snapshot)
	require.NoError(t, err)
	snapTUF := SampleCustomTUF(data.CanonicalSnapshotRole, "testGUN", tufData, validTUFRepo.Snapshot.Signed.Version)
	query = gormDB.Create(&snapTUF)
	require.NoError(t, query.Error, "Creating a row for snapshot in DB failed.")

	tufData, err = json.Marshal(validTUFRepo.Targets[data.CanonicalTargetsRole])
	require.NoError(t, err)
	targetsTUF := SampleCustomTUF(data.CanonicalTargetsRole, "testGUN", tufData, validTUFRepo.Targets[data.CanonicalTargetsRole].Signed.Version)
	query = gormDB.Create(&targetsTUF)
	require.NoError(t, query.Error, "Creating a row for targets in DB failed.")

	tufData, err = json.Marshal(validTUFRepo.Root)
	require.NoError(t, err)
	rootTUF := SampleCustomTUF(data.CanonicalRootRole, "testGUN", tufData, validTUFRepo.Root.Signed.Version)
	query = gormDB.Create(&rootTUF)
	require.NoError(t, query.Error, "Creating a row for root in DB failed.")

	// GetCurrent on all of these roles should succeed
	ConsistentGetCurrentFoundTest(t, tufDBStore, tsTUF)
	ConsistentGetCurrentFoundTest(t, tufDBStore, snapTUF)
	ConsistentGetCurrentFoundTest(t, tufDBStore, targetsTUF)
	ConsistentGetCurrentFoundTest(t, tufDBStore, rootTUF)

	// Delete snapshot
	query = gormDB.Delete(&snapTUF)
	require.NoError(t, query.Error, "Deleting a row for snapshot in DB failed.")

	// GetCurrent snapshot lookup should still succeed because of caching
	ConsistentGetCurrentFoundTest(t, tufDBStore, snapTUF)

	// targets and root lookup on GetCurrent should also still succeed because of caching
	ConsistentGetCurrentFoundTest(t, tufDBStore, targetsTUF)
	ConsistentGetCurrentFoundTest(t, tufDBStore, rootTUF)

	// add another orphaned root, but ensure that we still get the previous root
	// since the new root isn't in a timestamp/snapshot chain
	orphanedRootTUF := SampleCustomTUF(data.CanonicalRootRole, "testGUN", []byte("orphanedRoot"), 9000)
	query = gormDB.Create(&orphanedRootTUF)
	require.NoError(t, query.Error, "Creating a row for root in DB failed.")
	// a GetCurrent for this gun and root gets us the previous root, which is linked in timestamp and snapshot
	ConsistentGetCurrentFoundTest(t, tufDBStore, rootTUF)
	// the orphaned root fails on a GetCurrent even though it's in the underlying store
	ConsistentTSAndSnapGetDifferentCurrentTest(t, tufDBStore, orphanedRootTUF)
}
Beispiel #21
0
// Marshal returns the regular non-canonical JSON form of a thing
func (c canonicalJSON) Marshal(from interface{}) ([]byte, error) {
	return json.Marshal(from)
}
Beispiel #22
0
// GenerateSnapshot generates a new snapshot given a previous (optional) snapshot
// We can't just load the previous snapshot, because it may have been signed by a different
// snapshot key (maybe from a previous root version).  Note that we need the root role and
// targets role to be loaded, because we need to generate metadata for both (and we need
// the root to be loaded so we can get the snapshot role to sign with)
func (rb *repoBuilder) GenerateSnapshot(prev *data.SignedSnapshot) ([]byte, int, error) {
	switch {
	case rb.repo.cryptoService == nil:
		return nil, 0, ErrInvalidBuilderInput{msg: "cannot generate snapshot without a cryptoservice"}
	case rb.IsLoaded(data.CanonicalSnapshotRole):
		return nil, 0, ErrInvalidBuilderInput{msg: "snapshot has already been loaded"}
	case rb.IsLoaded(data.CanonicalTimestampRole):
		return nil, 0, ErrInvalidBuilderInput{msg: "cannot generate snapshot if timestamp has already been loaded"}
	}

	if err := rb.checkPrereqsLoaded([]string{data.CanonicalRootRole}); err != nil {
		return nil, 0, err
	}

	// If there is no previous snapshot, we need to generate one, and so the targets must
	// have already been loaded.  Otherwise, so long as the previous snapshot structure is
	// valid (it has a targets meta), we're good.
	switch prev {
	case nil:
		if err := rb.checkPrereqsLoaded([]string{data.CanonicalTargetsRole}); err != nil {
			return nil, 0, err
		}

		if err := rb.repo.InitSnapshot(); err != nil {
			rb.repo.Snapshot = nil
			return nil, 0, err
		}
	default:
		if err := data.IsValidSnapshotStructure(prev.Signed); err != nil {
			return nil, 0, err
		}
		rb.repo.Snapshot = prev
	}

	sgnd, err := rb.repo.SignSnapshot(data.DefaultExpires(data.CanonicalSnapshotRole))
	if err != nil {
		rb.repo.Snapshot = nil
		return nil, 0, err
	}

	sgndJSON, err := json.Marshal(sgnd)
	if err != nil {
		rb.repo.Snapshot = nil
		return nil, 0, err
	}

	// loadedNotChecksummed should currently contain the root awaiting checksumming,
	// since it has to have been loaded.  Since the snapshot was generated using
	// the root and targets data (there may not be any) that that have been loaded,
	// remove all of them from rb.loadedNotChecksummed
	for tgtName := range rb.repo.Targets {
		delete(rb.loadedNotChecksummed, tgtName)
	}
	delete(rb.loadedNotChecksummed, data.CanonicalRootRole)

	// The timestamp can't have been loaded yet, so we want to cache the snapshot
	// bytes so we can validate the checksum when a timestamp gets generated or
	// loaded later.
	rb.loadedNotChecksummed[data.CanonicalSnapshotRole] = sgndJSON

	return sgndJSON, rb.repo.Snapshot.Signed.Version, nil
}