diff --git a/repo.go b/repo.go index 0834cfd1..e273ad9b 100644 --- a/repo.go +++ b/repo.go @@ -452,7 +452,7 @@ func (r *Repo) RootKeys() ([]*data.PublicKey, error) { return rootKeys(root) } -func rootKeys(root *data.Root) ([]*data.Key, error) { +func rootKeys(root *data.Root) ([]*data.PublicKey, error) { role, ok := root.Roles["root"] if !ok { return nil, nil diff --git a/repo_extended.go b/repo_extended.go new file mode 100644 index 00000000..795bf2fa --- /dev/null +++ b/repo_extended.go @@ -0,0 +1,99 @@ +package tuf + +import ( + "time" + + "github.com/theupdateframework/go-tuf/data" +) + +func (r *Repo) IncrementRootVersion() error { + return r.IncrementRootVersionWithExpires(data.DefaultExpires("root")) +} + +func (r *Repo) IncrementRootVersionWithExpires(expires time.Time) error { + role, err := r.root() + if err != nil { + return err + } + + if !validExpires(expires) { + return ErrInvalidExpires{expires} + } + + role.Expires = expires.Round(time.Second) + if !r.local.FileIsStaged("root.json") { + role.Version++ + } + + return r.setMeta("root.json", role) +} + +func (r *Repo) RootExpires() (time.Time, error) { + role, err := r.root() + if err != nil { + return time.Time{}, err + } + return role.Expires, nil +} + +func (r *Repo) IncrementSnapshotVersion() error { + return r.Snapshot() +} + +func (r *Repo) IncrementSnapshotVersionWithExpires(expires time.Time) error { + return r.SnapshotWithExpires(expires) +} + +func (r *Repo) SnapshotExpires() (time.Time, error) { + role, err := r.snapshot() + if err != nil { + return time.Time{}, err + } + return role.Expires, nil +} + +func (r *Repo) IncrementTargetsVersion() error { + return r.IncrementTargetsVersionWithExpires(data.DefaultExpires("targets")) +} + +func (r *Repo) IncrementTargetsVersionWithExpires(expires time.Time) error { + role, err := r.topLevelTargets() + if err != nil { + return err + } + + if !validExpires(expires) { + return ErrInvalidExpires{expires} + } + + role.Expires = expires.Round(time.Second) + if !r.local.FileIsStaged("targets.json") { + role.Version++ + } + + return r.setMeta("targets.json", role) +} + +func (r *Repo) TargetsExpires() (time.Time, error) { + role, err := r.topLevelTargets() + if err != nil { + return time.Time{}, err + } + return role.Expires, nil +} + +func (r *Repo) IncrementTimestampVersion() error { + return r.Timestamp() +} + +func (r *Repo) IncrementTimestampVersionWithExpires(expires time.Time) error { + return r.TimestampWithExpires(expires) +} + +func (r *Repo) TimestampExpires() (time.Time, error) { + role, err := r.timestamp() + if err != nil { + return time.Time{}, err + } + return role.Expires, nil +} diff --git a/repo_extended_test.go b/repo_extended_test.go new file mode 100644 index 00000000..d32e4a1d --- /dev/null +++ b/repo_extended_test.go @@ -0,0 +1,249 @@ +package tuf + +import ( + . "gopkg.in/check.v1" +) + +func genKeyErr(_ []string, err error) error { + return err +} + +func initRepo(c *C, r *Repo, paths []string) { + c.Assert(r.Init(false), IsNil) + c.Assert(genKeyErr(r.GenKey("root")), IsNil) + c.Assert(genKeyErr(r.GenKey("targets")), IsNil) + c.Assert(genKeyErr(r.GenKey("snapshot")), IsNil) + c.Assert(genKeyErr(r.GenKey("timestamp")), IsNil) + c.Assert(r.AddTargets(paths, nil), IsNil) + c.Assert(r.Snapshot(CompressionTypeNone), IsNil) + c.Assert(r.Timestamp(), IsNil) + c.Assert(r.Commit(), IsNil) +} + +func (RepoSuite) TestRolesExpirationsRotation(c *C) { + local := MemoryStore(nil, map[string][]byte{ + "myfile": []byte("DATA\n"), + }) + + r, err := NewRepo(local) + c.Assert(err, IsNil) + + initRepo(c, r, []string{"myfile"}) + + prevRootVersion, err := r.RootVersion() + c.Assert(err, IsNil) + prevRootExpires, err := r.RootExpires() + c.Assert(err, IsNil) + + prevTargetsVersion, err := r.TargetsVersion() + c.Assert(err, IsNil) + prevTargetsExpires, err := r.TargetsExpires() + c.Assert(err, IsNil) + + prevSnapshotVersion, err := r.SnapshotVersion() + c.Assert(err, IsNil) + prevSnapshotExpires, err := r.SnapshotExpires() + c.Assert(err, IsNil) + + prevTimestampVersion, err := r.TimestampVersion() + c.Assert(err, IsNil) + prevTimestampExpires, err := r.TimestampExpires() + c.Assert(err, IsNil) + + // Update timestamp + for i := 0; i < 10; i++ { + r, err := NewRepo(local) + c.Assert(err, IsNil) + + newTimestampExpires := prevTimestampExpires.AddDate(0, 0, 1) + + c.Assert(r.IncrementTimestampVersionWithExpires(newTimestampExpires), IsNil) + c.Assert(r.Commit(), IsNil) + + root, err := r.root() + c.Assert(err, IsNil) + c.Assert(root.Version, Equals, prevRootVersion) + c.Assert(root.Expires, Equals, prevRootExpires) + + targets, err := r.targets() + c.Assert(err, IsNil) + c.Assert(targets.Version, Equals, prevTargetsVersion) + c.Assert(targets.Expires, Equals, prevTargetsExpires) + + snapshot, err := r.snapshot() + c.Assert(err, IsNil) + c.Assert(snapshot.Version, Equals, prevSnapshotVersion) + c.Assert(snapshot.Expires, Equals, prevSnapshotExpires) + + timestamp, err := r.timestamp() + c.Assert(err, IsNil) + c.Assert(timestamp.Version, Equals, prevTimestampVersion+1) + c.Assert(timestamp.Expires, Equals, newTimestampExpires) + prevTimestampVersion = timestamp.Version + prevTimestampExpires = timestamp.Expires + } + + // Update snapshot, depends on timestamp + for i := 0; i < 10; i++ { + r, err := NewRepo(local) + c.Assert(err, IsNil) + + newSnapshotExpires := prevSnapshotExpires.AddDate(0, 0, 7) + newTimestampExpires := prevTimestampExpires.AddDate(0, 0, 1) + + c.Assert(r.IncrementSnapshotVersionWithExpires(newSnapshotExpires), IsNil) + c.Assert(r.IncrementTimestampVersionWithExpires(newTimestampExpires), IsNil) + c.Assert(r.Commit(), IsNil) + + root, err := r.root() + c.Assert(err, IsNil) + c.Assert(root.Version, Equals, prevRootVersion) + c.Assert(root.Expires, Equals, prevRootExpires) + + targets, err := r.targets() + c.Assert(err, IsNil) + c.Assert(targets.Version, Equals, prevTargetsVersion) + c.Assert(targets.Expires, Equals, prevTargetsExpires) + + snapshot, err := r.snapshot() + c.Assert(err, IsNil) + c.Assert(snapshot.Version, Equals, prevSnapshotVersion+1) + c.Assert(snapshot.Expires, Equals, newSnapshotExpires) + prevSnapshotVersion = snapshot.Version + prevSnapshotExpires = snapshot.Expires + + timestamp, err := r.timestamp() + c.Assert(err, IsNil) + c.Assert(timestamp.Version, Equals, prevTimestampVersion+1) + c.Assert(timestamp.Expires, Equals, newTimestampExpires) + prevTimestampVersion = timestamp.Version + prevTimestampExpires = timestamp.Expires + } + + // Update targets, depends on snapshot and timestamp + for i := 0; i < 10; i++ { + r, err := NewRepo(local) + c.Assert(err, IsNil) + + newTargetsExpires := prevTargetsExpires.AddDate(0, 3, 0) + newSnapshotExpires := prevSnapshotExpires.AddDate(0, 0, 7) + newTimestampExpires := prevTimestampExpires.AddDate(0, 0, 1) + + c.Assert(r.IncrementTargetsVersionWithExpires(newTargetsExpires), IsNil) + c.Assert(r.IncrementSnapshotVersionWithExpires(newSnapshotExpires), IsNil) + c.Assert(r.IncrementTimestampVersionWithExpires(newTimestampExpires), IsNil) + c.Assert(r.Commit(), IsNil) + + root, err := r.root() + c.Assert(err, IsNil) + c.Assert(root.Version, Equals, prevRootVersion) + c.Assert(root.Expires, Equals, prevRootExpires) + + targets, err := r.targets() + c.Assert(err, IsNil) + c.Assert(targets.Version, Equals, prevTargetsVersion+1) + c.Assert(targets.Expires, Equals, newTargetsExpires) + prevTargetsVersion = targets.Version + prevTargetsExpires = targets.Expires + + snapshot, err := r.snapshot() + c.Assert(err, IsNil) + c.Assert(snapshot.Version, Equals, prevSnapshotVersion+1) + c.Assert(snapshot.Expires, Equals, newSnapshotExpires) + prevSnapshotVersion = snapshot.Version + prevSnapshotExpires = snapshot.Expires + + timestamp, err := r.timestamp() + c.Assert(err, IsNil) + c.Assert(timestamp.Version, Equals, prevTimestampVersion+1) + c.Assert(timestamp.Expires, Equals, newTimestampExpires) + prevTimestampVersion = timestamp.Version + prevTimestampExpires = timestamp.Expires + } + + // Update root, depends on snapshot and timestamp + for i := 0; i < 10; i++ { + r, err := NewRepo(local) + c.Assert(err, IsNil) + + newRootExpires := prevRootExpires.AddDate(1, 0, 0) + newSnapshotExpires := prevSnapshotExpires.AddDate(0, 0, 7) + newTimestampExpires := prevTimestampExpires.AddDate(0, 0, 1) + + c.Assert(r.IncrementRootVersionWithExpires(newRootExpires), IsNil) + c.Assert(r.IncrementSnapshotVersionWithExpires(newSnapshotExpires), IsNil) + c.Assert(r.IncrementTimestampVersionWithExpires(newTimestampExpires), IsNil) + c.Assert(r.Commit(), IsNil) + + root, err := r.root() + c.Assert(err, IsNil) + c.Assert(root.Version, Equals, prevRootVersion+1) + c.Assert(root.Expires, Equals, newRootExpires) + prevRootVersion = root.Version + prevRootExpires = root.Expires + + targets, err := r.targets() + c.Assert(err, IsNil) + c.Assert(targets.Version, Equals, prevTargetsVersion) + c.Assert(targets.Expires, Equals, prevTargetsExpires) + + snapshot, err := r.snapshot() + c.Assert(err, IsNil) + c.Assert(snapshot.Version, Equals, prevSnapshotVersion+1) + c.Assert(snapshot.Expires, Equals, newSnapshotExpires) + prevSnapshotVersion = snapshot.Version + prevSnapshotExpires = snapshot.Expires + + timestamp, err := r.timestamp() + c.Assert(err, IsNil) + c.Assert(timestamp.Version, Equals, prevTimestampVersion+1) + c.Assert(timestamp.Expires, Equals, newTimestampExpires) + prevTimestampVersion = timestamp.Version + prevTimestampExpires = timestamp.Expires + } + + // Update root, targets, snapshot and timestamp at the same time + for i := 0; i < 10; i++ { + r, err := NewRepo(local) + c.Assert(err, IsNil) + + newRootExpires := prevRootExpires.AddDate(1, 0, 0) + newTargetsExpires := prevTargetsExpires.AddDate(0, 3, 0) + newSnapshotExpires := prevSnapshotExpires.AddDate(0, 0, 7) + newTimestampExpires := prevTimestampExpires.AddDate(0, 0, 1) + + c.Assert(r.IncrementRootVersionWithExpires(newRootExpires), IsNil) + c.Assert(r.IncrementTargetsVersionWithExpires(newTargetsExpires), IsNil) + c.Assert(r.IncrementSnapshotVersionWithExpires(newSnapshotExpires), IsNil) + c.Assert(r.IncrementTimestampVersionWithExpires(newTimestampExpires), IsNil) + c.Assert(r.Commit(), IsNil) + + root, err := r.root() + c.Assert(err, IsNil) + c.Assert(root.Version, Equals, prevRootVersion+1) + c.Assert(root.Expires, Equals, newRootExpires) + prevRootVersion = root.Version + prevRootExpires = root.Expires + + targets, err := r.targets() + c.Assert(err, IsNil) + c.Assert(targets.Version, Equals, prevTargetsVersion+1) + c.Assert(targets.Expires, Equals, newTargetsExpires) + prevTargetsVersion = targets.Version + prevTargetsExpires = targets.Expires + + snapshot, err := r.snapshot() + c.Assert(err, IsNil) + c.Assert(snapshot.Version, Equals, prevSnapshotVersion+1) + c.Assert(snapshot.Expires, Equals, newSnapshotExpires) + prevSnapshotVersion = snapshot.Version + prevSnapshotExpires = snapshot.Expires + + timestamp, err := r.timestamp() + c.Assert(err, IsNil) + c.Assert(timestamp.Version, Equals, prevTimestampVersion+1) + c.Assert(timestamp.Expires, Equals, newTimestampExpires) + prevTimestampVersion = timestamp.Version + prevTimestampExpires = timestamp.Expires + } +}