pass checksum to GetOrCreateSnapshot. One timestamp test now obsolete as we always regenerate a timestamp when regenerating a snapshot, other test has one error change because we now look for an explicit checksum, hence writing incorrect data to DB for the snapshot results in a rather than a

Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
David Lawrence 2016-04-18 22:07:11 -07:00
parent 3e5d6d1f31
commit ae133606ad
4 changed files with 59 additions and 57 deletions

View File

@ -49,10 +49,10 @@ func GetOrCreateSnapshotKey(gun string, store storage.KeyStore, crypto signed.Cr
// the expiry time and version. Note that this function does not write generated
// snapshots to the underlying data store, and will either return the latest snapshot time
// or nil as the time modified
func GetOrCreateSnapshot(gun string, store storage.MetaStore, cryptoService signed.CryptoService) (
func GetOrCreateSnapshot(gun, checksum string, store storage.MetaStore, cryptoService signed.CryptoService) (
*time.Time, []byte, error) {
lastModified, currentJSON, err := store.GetCurrent(gun, data.CanonicalSnapshotRole)
lastModified, currentJSON, err := store.GetChecksum(gun, data.CanonicalSnapshotRole, checksum)
if err != nil {
return nil, nil, err
}

View File

@ -2,6 +2,8 @@ package snapshot
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"testing"
"time"
@ -141,7 +143,10 @@ func TestGetSnapshotNoPreviousSnapshot(t *testing.T) {
require.NoError(t, err)
require.NoError(t, store.SetKey("gun", data.CanonicalSnapshotRole, key.Algorithm(), key.Public()))
_, _, err = GetOrCreateSnapshot("gun", store, crypto)
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)
@ -164,8 +169,11 @@ func TestGetSnapshotReturnsPreviousSnapshotIfUnexpired(t *testing.T) {
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", store, crypto)
_, gottenSnapshot, err := GetOrCreateSnapshot("gun", hashHex, store, crypto)
require.NoError(t, err, "GetSnapshot should not have failed")
require.True(t, bytes.Equal(snapshotJSON, gottenSnapshot))
}
@ -191,7 +199,10 @@ func TestGetSnapshotOldSnapshotExpired(t *testing.T) {
require.NoError(t, store.UpdateCurrent("gun",
storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 0, Data: snapshotJSON}))
_, gottenSnapshot, err := GetOrCreateSnapshot("gun", store, crypto)
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),
@ -225,7 +236,10 @@ func TestCannotMakeNewSnapshotIfNoRoot(t *testing.T) {
require.NoError(t, store.UpdateCurrent("gun",
storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 1, Data: snapshotJSON}))
_, _, err := GetOrCreateSnapshot("gun", store, crypto)
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
@ -257,8 +271,11 @@ func TestCreateSnapshotNoKeyInCrypto(t *testing.T) {
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", store, signed.NewEd25519())
_, _, err = GetOrCreateSnapshot("gun", hashHex, store, signed.NewEd25519())
require.Error(t, err)
require.IsType(t, signed.ErrInsufficientSignatures{}, err)
}

View File

@ -1,9 +1,11 @@
package timestamp
import (
"encoding/hex"
"time"
"github.com/docker/go/canonical/json"
"github.com/docker/notary"
"github.com/docker/notary/tuf"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed"
@ -68,8 +70,16 @@ func GetOrCreateTimestamp(gun string, store storage.MetaStore, cryptoService sig
logrus.Error("Failed to unmarshal existing timestamp")
return nil, nil, err
}
snapshotTime, snapshot, err := snapshot.GetOrCreateSnapshot(gun, store, cryptoService)
snapChecksums, err := prev.GetSnapshot()
if err != nil || snapChecksums == nil {
return nil, nil, err
}
snapshotSha256Bytes, ok := snapChecksums.Hashes[notary.SHA256]
if !ok {
return nil, nil, data.ErrMissingMeta{Role: data.CanonicalSnapshotRole}
}
snapshotSha256Hex := hex.EncodeToString(snapshotSha256Bytes[:])
snapshotTime, snapshot, err := snapshot.GetOrCreateSnapshot(gun, snapshotSha256Hex, store, cryptoService)
if err != nil {
logrus.Debug("Previous timestamp, but no valid snapshot for GUN ", gun)
return nil, nil, err

View File

@ -150,42 +150,6 @@ func TestGetTimestampOldTimestampExpired(t *testing.T) {
require.True(t, signedMeta.Signed.Expires.After(time.Now()))
}
// In practice this might happen if the snapshot is expired, for instance, and
// is re-signed.
func TestGetTimestampIfNewSnapshot(t *testing.T) {
store := storage.NewMemStorage()
repo, crypto, err := testutils.EmptyRepo("gun")
rootJSON, err := json.Marshal(repo.Root)
require.NoError(t, err)
timestampJSON, err := json.Marshal(repo.Timestamp)
require.NoError(t, err)
snapJSON, err := json.Marshal(repo.Snapshot)
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: snapJSON}))
require.NoError(t, store.UpdateCurrent("gun",
storage.MetaUpdate{Role: data.CanonicalTimestampRole, Version: 0, Data: timestampJSON}))
c1, ts1, err := GetOrCreateTimestamp("gun", store, crypto)
require.Nil(t, err, "GetTimestamp errored")
// update the snapshot to a new version
repo.Snapshot.Signed.Version++
snapJSON, err = json.Marshal(repo.Snapshot)
require.NoError(t, err)
store.UpdateCurrent("gun", storage.MetaUpdate{Role: "snapshot", Version: 1, Data: snapJSON})
c2, ts2, err := GetOrCreateTimestamp("gun", store, crypto)
require.NoError(t, err, "GetTimestamp errored")
require.NotEqual(t, ts1, ts2, "Timestamp was not regenerated when snapshot changed")
require.True(t, c1.Before(*c2), "Timestamp modification time incorrect")
}
// 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")
@ -203,14 +167,30 @@ func TestCannotMakeNewTimestampIfNoRootOrSnapshot(t *testing.T) {
timestampJSON, err := json.Marshal(repo.Timestamp)
require.NoError(t, err)
invalids := []map[string][]byte{
{data.CanonicalRootRole: rootJSON, data.CanonicalSnapshotRole: []byte("invalid JSON")},
{data.CanonicalRootRole: []byte("invalid JSON"), data.CanonicalSnapshotRole: snapJSON},
{data.CanonicalRootRole: rootJSON},
{data.CanonicalSnapshotRole: snapJSON},
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 _, dataToSet := range invalids {
for _, test := range invalids {
dataToSet := test.test
store := storage.NewMemStorage()
for roleName, jsonBytes := range dataToSet {
require.NoError(t, store.UpdateCurrent("gun",
@ -221,12 +201,7 @@ func TestCannotMakeNewTimestampIfNoRootOrSnapshot(t *testing.T) {
_, _, err := GetOrCreateTimestamp("gun", store, crypto)
require.Error(t, err, "GetTimestamp errored")
if len(dataToSet) == 1 { // missing metadata
require.IsType(t, storage.ErrNotFound{}, err)
} else {
require.IsType(t, &json.SyntaxError{}, err)
}
require.IsType(t, test.err, err)
}
}