Change minimum required version of metadata to be 1, not 0

Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
Ying Li 2016-04-22 10:35:15 -07:00
parent 5d1b4bc6ec
commit ab7064ea12
16 changed files with 128 additions and 86 deletions

View File

@ -660,7 +660,7 @@ func (r *NotaryRepository) bootstrapRepo() error {
} }
return err return err
} }
if err := b.Load(role, jsonBytes, 0, true); err != nil { if err := b.Load(role, jsonBytes, 1, true); err != nil {
return err return err
} }
} }
@ -769,7 +769,7 @@ func (r *NotaryRepository) Update(forWrite bool) error {
// Returns a tufclient.Client for the remote server, which may not be actually // Returns a tufclient.Client for the remote server, which may not be actually
// operational (if the URL is invalid but a root.json is cached). // operational (if the URL is invalid but a root.json is cached).
func (r *NotaryRepository) bootstrapClient(checkInitialized bool) (*tufclient.Client, error) { func (r *NotaryRepository) bootstrapClient(checkInitialized bool) (*tufclient.Client, error) {
minVersion := 0 minVersion := 1
oldBuilder := tuf.NewRepoBuilder(r.gun, r.CryptoService, r.trustPinning) oldBuilder := tuf.NewRepoBuilder(r.gun, r.CryptoService, r.trustPinning)
var newBuilder tuf.RepoBuilder var newBuilder tuf.RepoBuilder

View File

@ -44,7 +44,7 @@ func validateUpdate(cs signed.CryptoService, gun string, updates []storage.MetaU
if rootUpdate, ok := roles[data.CanonicalRootRole]; ok { if rootUpdate, ok := roles[data.CanonicalRootRole]; ok {
builder = builder.BootstrapNewBuilder() builder = builder.BootstrapNewBuilder()
if err := builder.Load(data.CanonicalRootRole, rootUpdate.Data, 0, false); err != nil { if err := builder.Load(data.CanonicalRootRole, rootUpdate.Data, 1, false); err != nil {
return nil, validation.ErrBadRoot{Msg: err.Error()} return nil, validation.ErrBadRoot{Msg: err.Error()}
} }
@ -67,7 +67,7 @@ func validateUpdate(cs signed.CryptoService, gun string, updates []storage.MetaU
// At this point, root and targets must have been loaded into the repo // At this point, root and targets must have been loaded into the repo
if snapshotUpdate, ok := roles[data.CanonicalSnapshotRole]; ok { if snapshotUpdate, ok := roles[data.CanonicalSnapshotRole]; ok {
if err := builder.Load(data.CanonicalSnapshotRole, snapshotUpdate.Data, 0, false); err != nil { if err := builder.Load(data.CanonicalSnapshotRole, snapshotUpdate.Data, 1, false); err != nil {
return nil, validation.ErrBadSnapshot{Msg: err.Error()} return nil, validation.ErrBadSnapshot{Msg: err.Error()}
} }
logrus.Debug("Successfully validated snapshot") logrus.Debug("Successfully validated snapshot")
@ -131,7 +131,7 @@ func loadAndValidateTargets(gun string, builder tuf.RepoBuilder, roles map[strin
} }
} }
if err := builder.Load(roleName, roles[roleName].Data, 0, false); err != nil { if err := builder.Load(roleName, roles[roleName].Data, 1, false); err != nil {
logrus.Error("ErrBadTargets: ", err.Error()) logrus.Error("ErrBadTargets: ", err.Error())
return nil, validation.ErrBadTargets{Msg: err.Error()} return nil, validation.ErrBadTargets{Msg: err.Error()}
} }
@ -223,7 +223,7 @@ func loadFromStore(gun, roleName string, builder tuf.RepoBuilder, store storage.
if err != nil { if err != nil {
return err return err
} }
if err := builder.Load(roleName, metaJSON, 0, true); err != nil { if err := builder.Load(roleName, metaJSON, 1, true); err != nil {
return err return err
} }
return nil return nil

View File

@ -76,7 +76,7 @@ func GetOrCreateSnapshot(gun, checksum string, store storage.MetaStore, cryptoSe
logrus.Debug("Previous snapshot, but no root for GUN ", gun) logrus.Debug("Previous snapshot, but no root for GUN ", gun)
return nil, nil, err return nil, nil, err
} }
if err := builder.Load(data.CanonicalRootRole, rootJSON, 0, false); err != nil { if err := builder.Load(data.CanonicalRootRole, rootJSON, 1, false); err != nil {
logrus.Debug("Could not load valid previous root for GUN ", gun) logrus.Debug("Could not load valid previous root for GUN ", gun)
return nil, nil, err return nil, nil, err
} }

View File

@ -144,13 +144,13 @@ func createTimestamp(gun string, prev *data.SignedTimestamp, snapshot []byte, st
logrus.Debug("Previous timestamp, but no root for GUN ", gun) logrus.Debug("Previous timestamp, but no root for GUN ", gun)
return nil, err return nil, err
} }
if err := builder.Load(data.CanonicalRootRole, root, 0, false); err != nil { if err := builder.Load(data.CanonicalRootRole, root, 1, false); err != nil {
logrus.Debug("Could not load valid previous root for GUN ", gun) logrus.Debug("Could not load valid previous root for GUN ", gun)
return nil, err return nil, err
} }
// load snapshot so we can include it in timestamp // load snapshot so we can include it in timestamp
if err := builder.Load(data.CanonicalSnapshotRole, snapshot, 0, false); err != nil { if err := builder.Load(data.CanonicalSnapshotRole, snapshot, 1, false); err != nil {
logrus.Debug("Could not load valid previous snapshot for GUN ", gun) logrus.Debug("Could not load valid previous snapshot for GUN ", gun)
return nil, err return nil, err
} }

View File

@ -467,6 +467,7 @@ func TestValidateRootWithPinnedCA(t *testing.T) {
data.CanonicalSnapshotRole: &rootRole.RootRole}, data.CanonicalSnapshotRole: &rootRole.RootRole},
false, false,
) )
testRoot.Signed.Version = 1
require.NoError(t, err, "Failed to create new root") require.NoError(t, err, "Failed to create new root")
keyReader, err := os.Open("../fixtures/notary-signer.key") keyReader, err := os.Open("../fixtures/notary-signer.key")
@ -581,6 +582,7 @@ func testValidateSuccessfulRootRotation(t *testing.T, keyAlg, rootKeyType string
}, },
false, false,
) )
origTestRoot.Signed.Version = 1
require.NoError(t, err, "Failed to create new root") require.NoError(t, err, "Failed to create new root")
signedOrigTestRoot, err := origTestRoot.ToSigned() signedOrigTestRoot, err := origTestRoot.ToSigned()
@ -607,6 +609,7 @@ func testValidateSuccessfulRootRotation(t *testing.T, keyAlg, rootKeyType string
data.CanonicalSnapshotRole: &rootRole.RootRole}, data.CanonicalSnapshotRole: &rootRole.RootRole},
false, false,
) )
testRoot.Signed.Version = 1
require.NoError(t, err, "Failed to create new root") require.NoError(t, err, "Failed to create new root")
signedTestRoot, err := testRoot.ToSigned() signedTestRoot, err := testRoot.ToSigned()
@ -659,6 +662,7 @@ func testValidateRootRotationMissingOrigSig(t *testing.T, keyAlg, rootKeyType st
}, },
false, false,
) )
origTestRoot.Signed.Version = 1
require.NoError(t, err, "Failed to create new root") require.NoError(t, err, "Failed to create new root")
signedOrigTestRoot, err := origTestRoot.ToSigned() signedOrigTestRoot, err := origTestRoot.ToSigned()
@ -734,6 +738,7 @@ func testValidateRootRotationMissingNewSig(t *testing.T, keyAlg, rootKeyType str
}, },
false, false,
) )
origTestRoot.Signed.Version = 1
require.NoError(t, err, "Failed to create new root") require.NoError(t, err, "Failed to create new root")
signedOrigTestRoot, err := origTestRoot.ToSigned() signedOrigTestRoot, err := origTestRoot.ToSigned()

View File

@ -166,7 +166,8 @@ func (rb *repoBuilder) IsLoaded(roleName string) bool {
} }
} }
// GetLoadedVersion returns the metadata version, if it is loaded, or 0 otherwise // GetLoadedVersion returns the metadata version, if it is loaded, or 1 (the
// minimum valid version number) otherwise
func (rb *repoBuilder) GetLoadedVersion(roleName string) int { func (rb *repoBuilder) GetLoadedVersion(roleName string) int {
switch { switch {
case roleName == data.CanonicalRootRole && rb.repo.Root != nil: case roleName == data.CanonicalRootRole && rb.repo.Root != nil:
@ -181,7 +182,7 @@ func (rb *repoBuilder) GetLoadedVersion(roleName string) int {
} }
} }
return 0 return 1
} }
// GetConsistentInfo returns the consistent name and size of a role, if it is known, // GetConsistentInfo returns the consistent name and size of a role, if it is known,

View File

@ -40,7 +40,7 @@ func getSampleMeta(t *testing.T) (map[string][]byte, string) {
func TestBuilderLoadsValidRolesOnly(t *testing.T) { func TestBuilderLoadsValidRolesOnly(t *testing.T) {
meta, gun := getSampleMeta(t) meta, gun := getSampleMeta(t)
builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
err := builder.Load("NotRoot", meta[data.CanonicalRootRole], 0, false) err := builder.Load("NotRoot", meta[data.CanonicalRootRole], 1, false)
require.Error(t, err) require.Error(t, err)
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
require.Contains(t, err.Error(), "is an invalid role") require.Contains(t, err.Error(), "is an invalid role")
@ -52,17 +52,17 @@ func TestBuilderOnlyAcceptsRootFirstWhenLoading(t *testing.T) {
for roleName, content := range meta { for roleName, content := range meta {
if roleName != data.CanonicalRootRole { if roleName != data.CanonicalRootRole {
err := builder.Load(roleName, content, 0, true) err := builder.Load(roleName, content, 1, true)
require.Error(t, err) require.Error(t, err)
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
require.Contains(t, err.Error(), "root must be loaded first") require.Contains(t, err.Error(), "root must be loaded first")
require.False(t, builder.IsLoaded(roleName)) require.False(t, builder.IsLoaded(roleName))
require.Equal(t, 0, builder.GetLoadedVersion(roleName)) require.Equal(t, 1, builder.GetLoadedVersion(roleName))
} }
} }
// we can load the root // we can load the root
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
require.True(t, builder.IsLoaded(data.CanonicalRootRole)) require.True(t, builder.IsLoaded(data.CanonicalRootRole))
} }
@ -71,31 +71,31 @@ func TestBuilderOnlyAcceptsDelegationsAfterParent(t *testing.T) {
builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
// load the root // load the root
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
// delegations can't be loaded without target // delegations can't be loaded without target
for _, delgName := range []string{"targets/a", "targets/a/b"} { for _, delgName := range []string{"targets/a", "targets/a/b"} {
err := builder.Load(delgName, meta[delgName], 0, false) err := builder.Load(delgName, meta[delgName], 1, false)
require.Error(t, err) require.Error(t, err)
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
require.Contains(t, err.Error(), "targets must be loaded first") require.Contains(t, err.Error(), "targets must be loaded first")
require.False(t, builder.IsLoaded(delgName)) require.False(t, builder.IsLoaded(delgName))
require.Equal(t, 0, builder.GetLoadedVersion(delgName)) require.Equal(t, 1, builder.GetLoadedVersion(delgName))
} }
// load the targets // load the targets
require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 1, false))
// targets/a/b can't be loaded because targets/a isn't loaded // targets/a/b can't be loaded because targets/a isn't loaded
err := builder.Load("targets/a/b", meta["targets/a/b"], 0, false) err := builder.Load("targets/a/b", meta["targets/a/b"], 1, false)
require.Error(t, err) require.Error(t, err)
require.IsType(t, data.ErrInvalidRole{}, err) require.IsType(t, data.ErrInvalidRole{}, err)
// targets/a can be loaded now though because targets is loaded // targets/a can be loaded now though because targets is loaded
require.NoError(t, builder.Load("targets/a", meta["targets/a"], 0, false)) require.NoError(t, builder.Load("targets/a", meta["targets/a"], 1, false))
// and now targets/a/b can be loaded because targets/a is loaded // and now targets/a/b can be loaded because targets/a is loaded
require.NoError(t, builder.Load("targets/a/b", meta["targets/a/b"], 0, false)) require.NoError(t, builder.Load("targets/a/b", meta["targets/a/b"], 1, false))
} }
func TestBuilderAcceptRoleOnce(t *testing.T) { func TestBuilderAcceptRoleOnce(t *testing.T) {
@ -104,12 +104,12 @@ func TestBuilderAcceptRoleOnce(t *testing.T) {
for _, roleName := range append(data.BaseRoles, "targets/a", "targets/a/b") { for _, roleName := range append(data.BaseRoles, "targets/a", "targets/a/b") {
// first time loading is ok // first time loading is ok
require.NoError(t, builder.Load(roleName, meta[roleName], 0, false)) require.NoError(t, builder.Load(roleName, meta[roleName], 1, false))
require.True(t, builder.IsLoaded(roleName)) require.True(t, builder.IsLoaded(roleName))
require.Equal(t, 1, builder.GetLoadedVersion(roleName)) require.Equal(t, 1, builder.GetLoadedVersion(roleName))
// second time loading is not // second time loading is not
err := builder.Load(roleName, meta[roleName], 0, false) err := builder.Load(roleName, meta[roleName], 1, false)
require.Error(t, err) require.Error(t, err)
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
require.Contains(t, err.Error(), "has already been loaded") require.Contains(t, err.Error(), "has already been loaded")
@ -124,14 +124,14 @@ func TestBuilderStopsAcceptingOrProducingDataOnceDone(t *testing.T) {
builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
for _, roleName := range data.BaseRoles { for _, roleName := range data.BaseRoles {
require.NoError(t, builder.Load(roleName, meta[roleName], 0, false)) require.NoError(t, builder.Load(roleName, meta[roleName], 1, false))
require.True(t, builder.IsLoaded(roleName)) require.True(t, builder.IsLoaded(roleName))
} }
_, err := builder.Finish() _, err := builder.Finish()
require.NoError(t, err) require.NoError(t, err)
err = builder.Load("targets/a", meta["targets/a"], 0, false) err = builder.Load("targets/a", meta["targets/a"], 1, false)
require.Error(t, err) require.Error(t, err)
require.Equal(t, tuf.ErrBuildDone, err) require.Equal(t, tuf.ErrBuildDone, err)
@ -200,7 +200,7 @@ func TestGenerateSnapshotInvalidOperations(t *testing.T) {
// --- we can't generate a snapshot if the targets isn't loaded and we have no previous snapshot, // --- we can't generate a snapshot if the targets isn't loaded and we have no previous snapshot,
// --- but if we have a previous snapshot with a valid targets, we're good even if no snapshot // --- but if we have a previous snapshot with a valid targets, we're good even if no snapshot
// --- is loaded // --- is loaded
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
_, _, err = builder.GenerateSnapshot(prevSnapshot) _, _, err = builder.GenerateSnapshot(prevSnapshot)
if prevSnapshot == nil { if prevSnapshot == nil {
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
@ -212,11 +212,11 @@ func TestGenerateSnapshotInvalidOperations(t *testing.T) {
// --- we can't generate a snapshot if we've loaded the timestamp already // --- we can't generate a snapshot if we've loaded the timestamp already
builder = tuf.NewRepoBuilder(gun, newCS, trustpinning.TrustPinConfig{}) builder = tuf.NewRepoBuilder(gun, newCS, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
if prevSnapshot == nil { if prevSnapshot == nil {
require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 1, false))
} }
require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 1, false))
_, _, err = builder.GenerateSnapshot(prevSnapshot) _, _, err = builder.GenerateSnapshot(prevSnapshot)
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
@ -225,11 +225,11 @@ func TestGenerateSnapshotInvalidOperations(t *testing.T) {
// --- we cannot generate a snapshot if we've already loaded a snapshot // --- we cannot generate a snapshot if we've already loaded a snapshot
builder = tuf.NewRepoBuilder(gun, newCS, trustpinning.TrustPinConfig{}) builder = tuf.NewRepoBuilder(gun, newCS, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
if prevSnapshot == nil { if prevSnapshot == nil {
require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 1, false))
} }
require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 1, false))
_, _, err = builder.GenerateSnapshot(prevSnapshot) _, _, err = builder.GenerateSnapshot(prevSnapshot)
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
@ -239,9 +239,9 @@ func TestGenerateSnapshotInvalidOperations(t *testing.T) {
for i := 0; i < len(snapKeys); i++ { for i := 0; i < len(snapKeys); i++ {
require.NoError(t, newCS.RemoveKey(snapKeys[i].ID())) require.NoError(t, newCS.RemoveKey(snapKeys[i].ID()))
builder = tuf.NewRepoBuilder(gun, newCS, trustpinning.TrustPinConfig{}) builder = tuf.NewRepoBuilder(gun, newCS, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
if prevSnapshot == nil { if prevSnapshot == nil {
require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 1, false))
} }
_, _, err = builder.GenerateSnapshot(prevSnapshot) _, _, err = builder.GenerateSnapshot(prevSnapshot)
@ -251,9 +251,9 @@ func TestGenerateSnapshotInvalidOperations(t *testing.T) {
// --- we cannot generate a snapshot if we don't have a cryptoservice // --- we cannot generate a snapshot if we don't have a cryptoservice
builder = tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{}) builder = tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
if prevSnapshot == nil { if prevSnapshot == nil {
require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 1, false))
} }
_, _, err = builder.GenerateSnapshot(prevSnapshot) _, _, err = builder.GenerateSnapshot(prevSnapshot)
@ -265,8 +265,8 @@ func TestGenerateSnapshotInvalidOperations(t *testing.T) {
// --- we can't generate a snapshot if we're given an invalid previous snapshot (for instance, an empty one), // --- we can't generate a snapshot if we're given an invalid previous snapshot (for instance, an empty one),
// --- even if we have a targets loaded // --- even if we have a targets loaded
builder := tuf.NewRepoBuilder(gun, cs, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, cs, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTargetsRole, meta[data.CanonicalTargetsRole], 1, false))
_, _, err = builder.GenerateSnapshot(&data.SignedSnapshot{}) _, _, err = builder.GenerateSnapshot(&data.SignedSnapshot{})
require.IsType(t, data.ErrInvalidMetadata{}, err) require.IsType(t, data.ErrInvalidMetadata{}, err)
@ -302,7 +302,7 @@ func TestGenerateTimestampInvalidOperations(t *testing.T) {
// --- we can't generate a timestamp if the snapshot isn't loaded, no matter if we have a previous // --- we can't generate a timestamp if the snapshot isn't loaded, no matter if we have a previous
// --- timestamp or not // --- timestamp or not
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
_, _, err = builder.GenerateTimestamp(prevTimestamp) _, _, err = builder.GenerateTimestamp(prevTimestamp)
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
require.Contains(t, err.Error(), "snapshot must be loaded first") require.Contains(t, err.Error(), "snapshot must be loaded first")
@ -310,9 +310,9 @@ func TestGenerateTimestampInvalidOperations(t *testing.T) {
// --- we can't generate a timestamp if we've loaded the timestamp already // --- we can't generate a timestamp if we've loaded the timestamp already
builder = tuf.NewRepoBuilder(gun, cs, trustpinning.TrustPinConfig{}) builder = tuf.NewRepoBuilder(gun, cs, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 1, false))
require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 1, false))
_, _, err = builder.GenerateTimestamp(prevTimestamp) _, _, err = builder.GenerateTimestamp(prevTimestamp)
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
@ -322,8 +322,8 @@ func TestGenerateTimestampInvalidOperations(t *testing.T) {
for i := 0; i < len(tsKeys); i++ { for i := 0; i < len(tsKeys); i++ {
require.NoError(t, cs.RemoveKey(tsKeys[i].ID())) require.NoError(t, cs.RemoveKey(tsKeys[i].ID()))
builder = tuf.NewRepoBuilder(gun, cs, trustpinning.TrustPinConfig{}) builder = tuf.NewRepoBuilder(gun, cs, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 1, false))
_, _, err = builder.GenerateTimestamp(prevTimestamp) _, _, err = builder.GenerateTimestamp(prevTimestamp)
require.IsType(t, signed.ErrInsufficientSignatures{}, err) require.IsType(t, signed.ErrInsufficientSignatures{}, err)
@ -332,8 +332,8 @@ func TestGenerateTimestampInvalidOperations(t *testing.T) {
// --- we cannot generate a timestamp if we don't have a cryptoservice // --- we cannot generate a timestamp if we don't have a cryptoservice
builder = tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{}) builder = tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 1, false))
_, _, err = builder.GenerateTimestamp(prevTimestamp) _, _, err = builder.GenerateTimestamp(prevTimestamp)
require.IsType(t, tuf.ErrInvalidBuilderInput{}, err) require.IsType(t, tuf.ErrInvalidBuilderInput{}, err)
@ -344,8 +344,8 @@ func TestGenerateTimestampInvalidOperations(t *testing.T) {
// --- we can't generate a timsetamp if we're given an invalid previous timestamp (for instance, an empty one), // --- we can't generate a timsetamp if we're given an invalid previous timestamp (for instance, an empty one),
// --- even if we have a snapshot loaded // --- even if we have a snapshot loaded
builder := tuf.NewRepoBuilder(gun, cs, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, cs, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 1, false))
_, _, err = builder.GenerateTimestamp(&data.SignedTimestamp{}) _, _, err = builder.GenerateTimestamp(&data.SignedTimestamp{})
require.IsType(t, data.ErrInvalidMetadata{}, err) require.IsType(t, data.ErrInvalidMetadata{}, err)
@ -369,11 +369,11 @@ func TestGetConsistentInfo(t *testing.T) {
meta, err := testutils.SignAndSerialize(repo) meta, err := testutils.SignAndSerialize(repo)
require.NoError(t, err) require.NoError(t, err)
builder := tuf.NewRepoBuilder(nil, gun, nil, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
// if neither snapshot nor timestamp are loaded, no matter how much other data is loaded, consistent info // if neither snapshot nor timestamp are loaded, no matter how much other data is loaded, consistent info
// is empty except for timestamp: timestamps have no checksums, and the length is always -1 // is empty except for timestamp: timestamps have no checksums, and the length is always -1
for _, roleToLoad := range []string{data.CanonicalRootRole, data.CanonicalTargetsRole} { for _, roleToLoad := range []string{data.CanonicalRootRole, data.CanonicalTargetsRole} {
require.NoError(t, builder.Load(roleToLoad, meta[roleToLoad], 0, false)) require.NoError(t, builder.Load(roleToLoad, meta[roleToLoad], 1, false))
for _, checkName := range append(data.BaseRoles, extraMeta...) { for _, checkName := range append(data.BaseRoles, extraMeta...) {
ci := builder.GetConsistentInfo(checkName) ci := builder.GetConsistentInfo(checkName)
require.Equal(t, checkName, ci.ConsistentName()) require.Equal(t, checkName, ci.ConsistentName())
@ -391,7 +391,7 @@ func TestGetConsistentInfo(t *testing.T) {
} }
// once timestamp is loaded, we can get the consistent info for snapshot but nothing else // once timestamp is loaded, we can get the consistent info for snapshot but nothing else
require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 1, false))
for _, checkName := range append(data.BaseRoles, extraMeta...) { for _, checkName := range append(data.BaseRoles, extraMeta...) {
ci := builder.GetConsistentInfo(checkName) ci := builder.GetConsistentInfo(checkName)
@ -416,7 +416,7 @@ func TestGetConsistentInfo(t *testing.T) {
} }
// once the snapshot is loaded, we can get real consistent info for all loaded roles // once the snapshot is loaded, we can get real consistent info for all loaded roles
require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 1, false))
for _, checkName := range data.BaseRoles { for _, checkName := range data.BaseRoles {
ci := builder.GetConsistentInfo(checkName) ci := builder.GetConsistentInfo(checkName)
require.True(t, ci.ChecksumKnown(), "%s's checksum is not known", checkName) require.True(t, ci.ChecksumKnown(), "%s's checksum is not known", checkName)
@ -508,35 +508,35 @@ func TestTimestampPreAndPostChecksumming(t *testing.T) {
snapJSON := append(meta[data.CanonicalSnapshotRole], ' ') snapJSON := append(meta[data.CanonicalSnapshotRole], ' ')
// --- load timestamp first // --- load timestamp first
builder := tuf.NewRepoBuilder(nil, gun, nil, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) 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 // 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], 0, false)) require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 1, false))
// loading the snapshot in fails, because of the checksum the timestamp has // loading the snapshot in fails, because of the checksum the timestamp has
err = builder.Load(data.CanonicalSnapshotRole, snapJSON, 0, false) err = builder.Load(data.CanonicalSnapshotRole, snapJSON, 1, false)
require.Error(t, err) require.Error(t, err)
require.IsType(t, data.ErrMismatchedChecksum{}, err) require.IsType(t, data.ErrMismatchedChecksum{}, err)
require.True(t, builder.IsLoaded(data.CanonicalTimestampRole)) require.True(t, builder.IsLoaded(data.CanonicalTimestampRole))
require.False(t, builder.IsLoaded(data.CanonicalSnapshotRole)) require.False(t, builder.IsLoaded(data.CanonicalSnapshotRole))
// all the other metadata can be loaded in, even though the checksums are wrong according to timestamp // 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"} { for _, roleName := range []string{data.CanonicalTargetsRole, "targets/other"} {
require.NoError(t, builder.Load(roleName, meta[roleName], 0, false)) require.NoError(t, builder.Load(roleName, meta[roleName], 1, false))
} }
// --- load snapshot first // --- load snapshot first
builder = tuf.NewRepoBuilder(nil, gun, nil, trustpinning.TrustPinConfig{}) builder = tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
for _, roleName := range append(data.BaseRoles, "targets/other") { for _, roleName := range append(data.BaseRoles, "targets/other") {
switch roleName { switch roleName {
case data.CanonicalTimestampRole: case data.CanonicalTimestampRole:
continue continue
case data.CanonicalSnapshotRole: case data.CanonicalSnapshotRole:
require.NoError(t, builder.Load(roleName, snapJSON, 0, false)) require.NoError(t, builder.Load(roleName, snapJSON, 1, false))
default: default:
require.NoError(t, builder.Load(roleName, meta[roleName], 0, false)) require.NoError(t, builder.Load(roleName, meta[roleName], 1, false))
} }
} }
// timestamp fails because the snapshot checksum is wrong // timestamp fails because the snapshot checksum is wrong
err = builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 0, false) err = builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 1, false)
require.Error(t, err) require.Error(t, err)
checksumErr, ok := err.(data.ErrMismatchedChecksum) checksumErr, ok := err.(data.ErrMismatchedChecksum)
require.True(t, ok) require.True(t, ok)
@ -587,13 +587,13 @@ func TestSnapshotLoadedFirstChecksumsOthers(t *testing.T) {
gun := "docker.com/notary" gun := "docker.com/notary"
meta := setupSnapshotChecksumming(t, gun) meta := setupSnapshotChecksumming(t, gun)
// --- load root then snapshot // --- load root then snapshot
builder := tuf.NewRepoBuilder(nil, gun, nil, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalRootRole, meta[data.CanonicalRootRole], 1, false))
require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 1, false))
// loading timestamp is fine, even though the timestamp metadata has the wrong checksum because // loading timestamp is fine, even though the timestamp metadata has the wrong checksum because
// we don't check timestamp checksums // we don't check timestamp checksums
require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 0, false)) require.NoError(t, builder.Load(data.CanonicalTimestampRole, meta[data.CanonicalTimestampRole], 1, false))
// loading the other roles' metadata with a space will fail because of a checksum failure (builder // loading the other roles' metadata with a space will fail because of a checksum failure (builder
// checks right away if the snapshot is loaded) - in the case of targets/other/other, which should // checks right away if the snapshot is loaded) - in the case of targets/other/other, which should
@ -608,10 +608,10 @@ func TestSnapshotLoadedFirstChecksumsOthers(t *testing.T) {
require.False(t, builder.IsLoaded(roleNameToLoad)) require.False(t, builder.IsLoaded(roleNameToLoad))
// now load it for real (since we need targets loaded before trying to load "targets/other") // now load it for real (since we need targets loaded before trying to load "targets/other")
require.NoError(t, builder.Load(roleNameToLoad, meta[roleNameToLoad], 0, false)) require.NoError(t, builder.Load(roleNameToLoad, meta[roleNameToLoad], 1, false))
} }
// loading the non-existent role wil fail // loading the non-existent role wil fail
err := builder.Load("targets/other/other", meta["targets/other/other"], 0, false) err := builder.Load("targets/other/other", meta["targets/other/other"], 1, false)
require.Error(t, err) require.Error(t, err)
require.IsType(t, data.ErrMissingMeta{}, err) require.IsType(t, data.ErrMissingMeta{}, err)
require.False(t, builder.IsLoaded("targets/other/other")) require.False(t, builder.IsLoaded("targets/other/other"))
@ -627,7 +627,7 @@ func TestSnapshotLoadedAfterChecksumsOthersRetroactively(t *testing.T) {
// --- load all the other metadata first, but with an extra space at the end which should // --- load all the other metadata first, but with an extra space at the end which should
// --- validate fine, except for the checksum. // --- validate fine, except for the checksum.
for _, roleNameToPermute := range append(data.BaseRoles, "targets/other") { for _, roleNameToPermute := range append(data.BaseRoles, "targets/other") {
builder := tuf.NewRepoBuilder(nil, gun, nil, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
if roleNameToPermute == data.CanonicalSnapshotRole { if roleNameToPermute == data.CanonicalSnapshotRole {
continue continue
} }
@ -641,12 +641,12 @@ func TestSnapshotLoadedAfterChecksumsOthersRetroactively(t *testing.T) {
// having a space added at the end should not affect any validity check except checksum // having a space added at the end should not affect any validity check except checksum
require.NoError(t, builder.Load(roleNameToLoad, append(meta[roleNameToLoad], ' '), 0, false)) require.NoError(t, builder.Load(roleNameToLoad, append(meta[roleNameToLoad], ' '), 0, false))
default: default:
require.NoError(t, builder.Load(roleNameToLoad, meta[roleNameToLoad], 0, false)) require.NoError(t, builder.Load(roleNameToLoad, meta[roleNameToLoad], 1, false))
} }
require.True(t, builder.IsLoaded(roleNameToLoad)) require.True(t, builder.IsLoaded(roleNameToLoad))
} }
// now load the snapshot - it should fail with the checksum failure for the permuted role // now load the snapshot - it should fail with the checksum failure for the permuted role
err := builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 0, false) err := builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 1, false)
switch roleNameToPermute { switch roleNameToPermute {
case data.CanonicalTimestampRole: case data.CanonicalTimestampRole:
require.NoError(t, err) // we don't check the timestamp's checksum require.NoError(t, err) // we don't check the timestamp's checksum
@ -662,14 +662,14 @@ func TestSnapshotLoadedAfterChecksumsOthersRetroactively(t *testing.T) {
// load all the metadata as is without alteration (so they should validate all checksums) // load all the metadata as is without alteration (so they should validate all checksums)
// but also load the metadata that is not contained in the snapshot. Then when the snapshot // but also load the metadata that is not contained in the snapshot. Then when the snapshot
// is loaded it will fail validation, because it doesn't have target/other/other's checksum // is loaded it will fail validation, because it doesn't have target/other/other's checksum
builder := tuf.NewRepoBuilder(nil, gun, nil, trustpinning.TrustPinConfig{}) builder := tuf.NewRepoBuilder(gun, nil, trustpinning.TrustPinConfig{})
for _, roleNameToLoad := range append(data.BaseRoles, "targets/other", "targets/other/other") { for _, roleNameToLoad := range append(data.BaseRoles, "targets/other", "targets/other/other") {
if roleNameToLoad == data.CanonicalSnapshotRole { if roleNameToLoad == data.CanonicalSnapshotRole {
continue continue
} }
require.NoError(t, builder.Load(roleNameToLoad, meta[roleNameToLoad], 0, false)) require.NoError(t, builder.Load(roleNameToLoad, meta[roleNameToLoad], 1, false))
} }
err := builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 0, false) err := builder.Load(data.CanonicalSnapshotRole, meta[data.CanonicalSnapshotRole], 1, false)
require.Error(t, err) require.Error(t, err)
require.IsType(t, data.ErrMissingMeta{}, err) require.IsType(t, data.ErrMissingMeta{}, err)
} }

View File

@ -118,7 +118,7 @@ func (c *Client) downloadTimestamp() error {
logrus.Debug(remoteErr.Error()) logrus.Debug(remoteErr.Error())
logrus.Warn("Error while downloading remote metadata, using cached timestamp - this might not be the latest version available remotely") logrus.Warn("Error while downloading remote metadata, using cached timestamp - this might not be the latest version available remotely")
err := c.newBuilder.Load(role, cachedTS, 0, false) err := c.newBuilder.Load(role, cachedTS, 1, false)
if err == nil { if err == nil {
logrus.Debug("successfully verified cached timestamp") logrus.Debug("successfully verified cached timestamp")
} }
@ -194,7 +194,7 @@ func (c *Client) tryLoadCacheThenRemote(consistentInfo tuf.ConsistentInfo) ([]by
return c.tryLoadRemote(consistentInfo, nil) return c.tryLoadRemote(consistentInfo, nil)
} }
if err = c.newBuilder.Load(consistentInfo.RoleName, cachedTS, 0, false); err == nil { if err = c.newBuilder.Load(consistentInfo.RoleName, cachedTS, 1, false); err == nil {
logrus.Debugf("successfully verified cached %s", consistentInfo.RoleName) logrus.Debugf("successfully verified cached %s", consistentInfo.RoleName)
return cachedTS, nil return cachedTS, nil
} }
@ -213,8 +213,8 @@ func (c *Client) tryLoadRemote(consistentInfo tuf.ConsistentInfo, old []byte) ([
// try to load the old data into the old builder - only use it to validate // try to load the old data into the old builder - only use it to validate
// versions if it loads successfully. If it errors, then the loaded version // versions if it loads successfully. If it errors, then the loaded version
// will be 0 // will be 1
c.oldBuilder.Load(consistentInfo.RoleName, old, 0, true) c.oldBuilder.Load(consistentInfo.RoleName, old, 1, true)
minVersion := c.oldBuilder.GetLoadedVersion(consistentInfo.RoleName) minVersion := c.oldBuilder.GetLoadedVersion(consistentInfo.RoleName)
if err := c.newBuilder.Load(consistentInfo.RoleName, raw, minVersion, false); err != nil { if err := c.newBuilder.Load(consistentInfo.RoleName, raw, minVersion, false); err != nil {

View File

@ -31,9 +31,9 @@ func isValidRootStructure(r Root) error {
role: CanonicalRootRole, msg: fmt.Sprintf("expected type %s, not %s", expectedType, r.Type)} role: CanonicalRootRole, msg: fmt.Sprintf("expected type %s, not %s", expectedType, r.Type)}
} }
if r.Version < 0 { if r.Version < 1 {
return ErrInvalidMetadata{ return ErrInvalidMetadata{
role: CanonicalRootRole, msg: "version cannot be negative"} role: CanonicalRootRole, msg: "version cannot be less than 1"}
} }
// all the base roles MUST appear in the root.json - other roles are allowed, // all the base roles MUST appear in the root.json - other roles are allowed,

View File

@ -225,4 +225,12 @@ func TestRootFromSignedValidatesVersion(t *testing.T) {
root.Signed.Version = -1 root.Signed.Version = -1
_, err := rootToSignedAndBack(t, root) _, err := rootToSignedAndBack(t, root)
require.IsType(t, ErrInvalidMetadata{}, err) require.IsType(t, ErrInvalidMetadata{}, err)
root.Signed.Version = 0
_, err = rootToSignedAndBack(t, root)
require.IsType(t, ErrInvalidMetadata{}, err)
root.Signed.Version = 1
_, err = rootToSignedAndBack(t, root)
require.NoError(t, err)
} }

View File

@ -32,9 +32,9 @@ func IsValidSnapshotStructure(s Snapshot) error {
role: CanonicalSnapshotRole, msg: fmt.Sprintf("expected type %s, not %s", expectedType, s.Type)} role: CanonicalSnapshotRole, msg: fmt.Sprintf("expected type %s, not %s", expectedType, s.Type)}
} }
if s.Version < 0 { if s.Version < 1 {
return ErrInvalidMetadata{ return ErrInvalidMetadata{
role: CanonicalSnapshotRole, msg: "version cannot be negative"} role: CanonicalSnapshotRole, msg: "version cannot be less than one"}
} }
for _, role := range []string{CanonicalRootRole, CanonicalTargetsRole} { for _, role := range []string{CanonicalRootRole, CanonicalTargetsRole} {

View File

@ -200,6 +200,14 @@ func TestSnapshotFromSignedValidatesVersion(t *testing.T) {
sn.Signed.Version = -1 sn.Signed.Version = -1
_, err := snapshotToSignedAndBack(t, sn) _, err := snapshotToSignedAndBack(t, sn)
require.IsType(t, ErrInvalidMetadata{}, err) require.IsType(t, ErrInvalidMetadata{}, err)
sn.Signed.Version = 0
_, err = snapshotToSignedAndBack(t, sn)
require.IsType(t, ErrInvalidMetadata{}, err)
sn.Signed.Version = 1
_, err = snapshotToSignedAndBack(t, sn)
require.NoError(t, err)
} }
// GetMeta returns the checksum, or an error if it is missing. // GetMeta returns the checksum, or an error if it is missing.

View File

@ -38,8 +38,8 @@ func isValidTargetsStructure(t Targets, roleName string) error {
role: roleName, msg: fmt.Sprintf("expected type %s, not %s", expectedType, t.Type)} role: roleName, msg: fmt.Sprintf("expected type %s, not %s", expectedType, t.Type)}
} }
if t.Version < 0 { if t.Version < 1 {
return ErrInvalidMetadata{role: roleName, msg: "version cannot be negative"} return ErrInvalidMetadata{role: roleName, msg: "version cannot be less than one"}
} }
for _, roleObj := range t.Delegations.Roles { for _, roleObj := range t.Delegations.Roles {

View File

@ -236,4 +236,16 @@ func TestTargetsFromSignedValidatesVersion(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
_, err = TargetsFromSigned(s, "targets/a") _, err = TargetsFromSigned(s, "targets/a")
require.IsType(t, ErrInvalidMetadata{}, err) require.IsType(t, ErrInvalidMetadata{}, err)
tg.Signed.Version = 0
s, err = tg.ToSigned()
require.NoError(t, err)
_, err = TargetsFromSigned(s, "targets/a")
require.IsType(t, ErrInvalidMetadata{}, err)
tg.Signed.Version = 1
s, err = tg.ToSigned()
require.NoError(t, err)
_, err = TargetsFromSigned(s, "targets/a")
require.NoError(t, err)
} }

View File

@ -31,9 +31,9 @@ func IsValidTimestampStructure(t Timestamp) error {
role: CanonicalTimestampRole, msg: fmt.Sprintf("expected type %s, not %s", expectedType, t.Type)} role: CanonicalTimestampRole, msg: fmt.Sprintf("expected type %s, not %s", expectedType, t.Type)}
} }
if t.Version < 0 { if t.Version < 1 {
return ErrInvalidMetadata{ return ErrInvalidMetadata{
role: CanonicalTimestampRole, msg: "version cannot be negative"} role: CanonicalTimestampRole, msg: "version cannot be less than one"}
} }
// Meta is a map of FileMeta, so if the role isn't in the map it returns // Meta is a map of FileMeta, so if the role isn't in the map it returns

View File

@ -200,6 +200,14 @@ func TestTimestampFromSignedValidatesVersion(t *testing.T) {
ts.Signed.Version = -1 ts.Signed.Version = -1
_, err := timestampToSignedAndBack(t, ts) _, err := timestampToSignedAndBack(t, ts)
require.IsType(t, ErrInvalidMetadata{}, err) require.IsType(t, ErrInvalidMetadata{}, err)
ts.Signed.Version = 0
_, err = timestampToSignedAndBack(t, ts)
require.IsType(t, ErrInvalidMetadata{}, err)
ts.Signed.Version = 1
_, err = timestampToSignedAndBack(t, ts)
require.NoError(t, err)
} }
// GetSnapshot returns the snapshot checksum, or an error if it is missing. // GetSnapshot returns the snapshot checksum, or an error if it is missing.