From 13eff30efd6c61f165e1bf06e8c0e72f5a0e5703 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 13:10:43 -0400 Subject: [PATCH 01/46] chore(deps): bump securesystemslib from 0.22.0 to 0.24.0 (#383) Bumps [securesystemslib](https://github.com/secure-systems-lab/securesystemslib) from 0.22.0 to 0.24.0. - [Release notes](https://github.com/secure-systems-lab/securesystemslib/releases) - [Changelog](https://github.com/secure-systems-lab/securesystemslib/blob/master/CHANGELOG.md) - [Commits](https://github.com/secure-systems-lab/securesystemslib/compare/v0.22.0...v0.24.0) --- updated-dependencies: - dependency-name: securesystemslib dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-test.txt b/requirements-test.txt index a364c2d7..9d0b3f7f 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,5 +1,5 @@ iso8601==1.0.2 requests==2.28.1 -securesystemslib==0.22.0 +securesystemslib==0.24.0 six==1.16.0 tuf==1.0.0 \ No newline at end of file From 6f59db8c7ce845b73bc4e2c672e496d5785533ec Mon Sep 17 00:00:00 2001 From: Timofey Kirillov Date: Thu, 21 Jul 2022 16:58:56 +0300 Subject: [PATCH 02/46] chore(trdl): export Repo methods to increment roles versions and expire dates Also added unit test case performing roles expiration rotation procedure. Signed-off-by: Timofey Kirillov --- repo_extended.go | 99 +++++++++++++++++ repo_extended_test.go | 249 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 348 insertions(+) create mode 100644 repo_extended.go create mode 100644 repo_extended_test.go 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..f62ee34c --- /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(), 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.topLevelTargets() + 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.topLevelTargets() + 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.topLevelTargets() + 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.topLevelTargets() + 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.topLevelTargets() + 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 + } +} From 040092c44a0845c3c92e48debd16c82910e94110 Mon Sep 17 00:00:00 2001 From: Zack Newman Date: Tue, 20 Sep 2022 12:08:48 -0400 Subject: [PATCH 03/46] fix: abandon updates if timestamp.json isn't new (#387) Adds a new test for this case: if a client sees a new `timestamp.json` file with the same version as its current `timestamp.json` file, it should do nothing (no update, but also no error). A few other tests were implicitly relying on the fact that the client did a full update each time, so they've been updated to commit a new timestamp. This updates go-tuf for TUF specification v1.0.30 (fixes #321). The only substantive change was [theupdateframework/specification#209][tuf-spec-209], which clarifies the intended behavior for updating metadata files. Updates for other roles were already in compliance: - Root metadata: https://github.com/theupdateframework/go-tuf/blob/13eff30efd6c61f165e1bf06e8c0e72f5a0e5703/client/client.go#L258 - Timestamp, checking snapshot version: https://github.com/theupdateframework/go-tuf/blob/13eff30efd6c61f165e1bf06e8c0e72f5a0e5703/client/client.go#L751 - Snapshot, must match version from timestamp: https://github.com/theupdateframework/go-tuf/blob/13eff30efd6c61f165e1bf06e8c0e72f5a0e5703/client/client.go#L667 - Snapshot, no rollback of targets: https://github.com/theupdateframework/go-tuf/blob/13eff30efd6c61f165e1bf06e8c0e72f5a0e5703/client/client.go#L685 - Targets: https://github.com/theupdateframework/go-tuf/blob/13eff30efd6c61f165e1bf06e8c0e72f5a0e5703/client/client.go#L643 [tuf-spec-209]: (https://github.com/theupdateframework/specification/pull/209). Signed-off-by: Zachary Newman Signed-off-by: Zachary Newman --- client/client.go | 29 ++++++++++++++++++++++------- client/client_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/client/client.go b/client/client.go index 17ddc980..5308b97b 100644 --- a/client/client.go +++ b/client/client.go @@ -143,7 +143,13 @@ func (c *Client) Update() (data.TargetFiles, error) { } // 5.4.(2,3 and 4) - Verify timestamp against various attacks // Returns the extracted snapshot metadata - snapshotMeta, err := c.decodeTimestamp(timestampJSON) + snapshotMeta, sameTimestampVersion, err := c.decodeTimestamp(timestampJSON) + if sameTimestampVersion { + // The new timestamp.json file had the same version; we don't need to + // update, so bail early. + return c.targets, nil + } + if err != nil { return nil, err } @@ -740,22 +746,31 @@ func (c *Client) decodeTargets(b json.RawMessage) (data.TargetFiles, error) { } // decodeTimestamp decodes and verifies timestamp metadata, and returns the -// new snapshot file meta. -func (c *Client) decodeTimestamp(b json.RawMessage) (data.TimestampFileMeta, error) { +// new snapshot file meta and signals whether the update should be aborted early +// (the new timestamp has the same version as the old one, so there's no need to +// complete the update). +func (c *Client) decodeTimestamp(b json.RawMessage) (data.TimestampFileMeta, bool, error) { timestamp := &data.Timestamp{} + if err := c.db.Unmarshal(b, timestamp, "timestamp", c.timestampVer); err != nil { - return data.TimestampFileMeta{}, ErrDecodeFailed{"timestamp.json", err} + return data.TimestampFileMeta{}, false, ErrDecodeFailed{"timestamp.json", err} + } + // 5.4.3.1 - Check for timestamp rollback attack + // We already checked for timestamp.Version < c.timestampVer in the Unmarshal call above. + // Here, we're checking for version equality, which indicates that we can abandon this update. + if timestamp.Version == c.timestampVer { + return data.TimestampFileMeta{}, true, nil } // 5.4.3.2 - Check for snapshot rollback attack // Verify that the current snapshot meta version is less than or equal to the new one if timestamp.Meta["snapshot.json"].Version < c.snapshotVer { - return data.TimestampFileMeta{}, verify.ErrLowVersion{Actual: timestamp.Meta["snapshot.json"].Version, Current: c.snapshotVer} + return data.TimestampFileMeta{}, false, verify.ErrLowVersion{Actual: timestamp.Meta["snapshot.json"].Version, Current: c.snapshotVer} } - // At this point we can trust the new timestamp and the snaphost version it refers to + // At this point we can trust the new timestamp and the snapshot version it refers to // so we can update the client's trusted versions and proceed with persisting the new timestamp c.timestampVer = timestamp.Version c.snapshotVer = timestamp.Meta["snapshot.json"].Version - return timestamp.Meta["snapshot.json"], nil + return timestamp.Meta["snapshot.json"], false, nil } // hasMetaFromSnapshot checks whether local metadata has the given meta diff --git a/client/client_test.go b/client/client_test.go index db8c3272..c583e2f1 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -896,6 +896,7 @@ func (s *ClientSuite) TestUpdateMixAndMatchAttack(c *C) { c.Assert(s.repo.AddTargetWithExpires("foo.txt", nil, expires), IsNil) c.Assert(s.repo.Snapshot(), IsNil) c.Assert(s.repo.Timestamp(), IsNil) + c.Assert(s.repo.Commit(), IsNil) s.syncRemote(c) client := s.updatedClient(c) @@ -909,6 +910,7 @@ func (s *ClientSuite) TestUpdateMixAndMatchAttack(c *C) { c.Assert(s.repo.AddTargetWithExpires("bar.txt", nil, expires), IsNil) c.Assert(s.repo.Snapshot(), IsNil) c.Assert(s.repo.Timestamp(), IsNil) + c.Assert(s.repo.Commit(), IsNil) s.syncRemote(c) newTargets, ok := s.remote.meta["targets.json"] if !ok { @@ -964,6 +966,41 @@ func (s *ClientSuite) TestUpdateReplayAttack(c *C) { }) } +func (s *ClientSuite) TestUpdateForkTimestamp(c *C) { + client := s.updatedClient(c) + + // grab the remote timestamp.json + oldTimestamp, ok := s.remote.meta["timestamp.json"] + if !ok { + c.Fatal("missing remote timestamp.json") + } + + // generate a new timestamp and sync with the client + version := client.timestampVer + c.Assert(version > 0, Equals, true) + c.Assert(s.repo.Timestamp(), IsNil) + s.syncRemote(c) + _, err := client.Update() + c.Assert(err, IsNil) + newVersion := client.timestampVer + c.Assert(newVersion > version, Equals, true) + + // generate a new, different timestamp with the *same version* + s.remote.meta["timestamp.json"] = oldTimestamp + c.Assert(s.repo.Timestamp(), IsNil) + c.Assert(client.timestampVer, Equals, newVersion) // double-check: same version? + s.syncRemote(c) + + oldMeta, err := client.local.GetMeta() + c.Assert(err, IsNil) + _, err = client.Update() + c.Assert(err, IsNil) // no error: the targets.json version didn't change, so there was no update! + // Client shouldn't update! + newMeta, err := client.local.GetMeta() + c.Assert(err, IsNil) + c.Assert(oldMeta, DeepEquals, newMeta) +} + func (s *ClientSuite) TestUpdateTamperedTargets(c *C) { client := s.newClient(c) @@ -998,6 +1035,7 @@ func (s *ClientSuite) TestUpdateTamperedTargets(c *C) { c.Assert(err, IsNil) s.store.SetMeta("targets.json", tamperedJSON) s.store.Commit(false, nil, nil) + c.Assert(s.repo.Timestamp(), IsNil) // unless timestamp changes, the client doesn't even look at "targets.json" s.syncRemote(c) _, err = client.Update() c.Assert(err, DeepEquals, ErrWrongSize{"targets.json", int64(len(tamperedJSON)), int64(len(targetsJSON))}) From f237d7ca5b42a20b380f0827687aa7c8804cbb54 Mon Sep 17 00:00:00 2001 From: asraa Date: Tue, 20 Sep 2022 13:03:06 -0400 Subject: [PATCH 04/46] feat: pass logger into repo and client (#385) * feat: pass logger into repo and client Signed-off-by: Asra Ali --- .golangci.yml | 1 + cmd/tuf-client/main.go | 3 +- cmd/tuf/gen_key.go | 5 +-- cmd/tuf/get_threshold.go | 3 +- cmd/tuf/main.go | 8 +++-- cmd/tuf/payload.go | 3 +- cmd/tuf/set_threshold.go | 3 +- cmd/tuf/sign_payload.go | 2 +- internal/fsutil/perm_test.go | 2 -- local_store.go | 31 ++++++++++++++-- pkg/keys/deprecated_ecdsa.go | 2 -- repo.go | 69 ++++++++++++++++++++++++++++-------- repo_test.go | 9 ++++- 13 files changed, 111 insertions(+), 30 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 6e8bf3c8..570c05d6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,3 +13,4 @@ linters: - gosimple - unused - typecheck + - forbidigo diff --git a/cmd/tuf-client/main.go b/cmd/tuf-client/main.go index 15d03fad..25a32005 100644 --- a/cmd/tuf-client/main.go +++ b/cmd/tuf-client/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "log" + "os" docopt "github.com/flynn/go-docopt" tuf "github.com/theupdateframework/go-tuf/client" @@ -32,7 +33,7 @@ See "tuf-client help " for more information on a specific command. if cmd == "help" { if len(cmdArgs) == 0 { // `tuf-client help` - fmt.Println(usage) + fmt.Fprint(os.Stderr, usage) return } else { // `tuf-client help ` cmd = cmdArgs[0] diff --git a/cmd/tuf/gen_key.go b/cmd/tuf/gen_key.go index bd4334ae..2ad77a58 100644 --- a/cmd/tuf/gen_key.go +++ b/cmd/tuf/gen_key.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "os" "time" "github.com/flynn/go-docopt" @@ -39,7 +40,7 @@ func cmdGenKey(args *docopt.Args, repo *tuf.Repo) error { string(data.KeySchemeRSASSA_PSS_SHA256): keyScheme = data.KeyScheme(t) default: - fmt.Println("Using default key scheme", keyScheme) + fmt.Fprint(os.Stderr, "Using default key scheme", keyScheme) } var err error @@ -57,7 +58,7 @@ func cmdGenKey(args *docopt.Args, repo *tuf.Repo) error { return err } for _, id := range keyids { - fmt.Println("Generated", role, keyScheme, "key with ID", id) + fmt.Fprintf(os.Stdout, "Generated %s %s key with ID %s", role, keyScheme, id) } return nil } diff --git a/cmd/tuf/get_threshold.go b/cmd/tuf/get_threshold.go index e40ec26e..a0d78fdd 100644 --- a/cmd/tuf/get_threshold.go +++ b/cmd/tuf/get_threshold.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "os" "github.com/flynn/go-docopt" "github.com/theupdateframework/go-tuf" @@ -23,6 +24,6 @@ func cmdGetThreshold(args *docopt.Args, repo *tuf.Repo) error { return err } - fmt.Println("The threshold for", role, "role is", threshold) + fmt.Fprintf(os.Stdout, "The threshold for %s role is %d", role, threshold) return nil } diff --git a/cmd/tuf/main.go b/cmd/tuf/main.go index f2b73972..6ee220b2 100644 --- a/cmd/tuf/main.go +++ b/cmd/tuf/main.go @@ -58,7 +58,7 @@ See "tuf help " for more information on a specific command if cmd == "help" { if len(cmdArgs) == 0 { // `tuf help` - fmt.Println(usage) + fmt.Fprint(os.Stderr, usage) return } else { // `tuf help ` cmd = cmdArgs[0] @@ -115,7 +115,11 @@ func runCommand(name string, args []string, dir string, insecure bool) error { if !insecure { p = getPassphrase } - repo, err := tuf.NewRepo(tuf.FileSystemStore(dir, p)) + logger := log.New(os.Stdout, "", 0) + storeOpts := tuf.StoreOpts{Logger: logger, PassFunc: p} + + repo, err := tuf.NewRepoWithOpts(tuf.FileSystemStoreWithOpts(dir, storeOpts), + tuf.WithLogger(logger)) if err != nil { return err } diff --git a/cmd/tuf/payload.go b/cmd/tuf/payload.go index 8cc0c2ff..3ae2c891 100644 --- a/cmd/tuf/payload.go +++ b/cmd/tuf/payload.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "os" "github.com/flynn/go-docopt" "github.com/theupdateframework/go-tuf" @@ -20,6 +21,6 @@ func cmdPayload(args *docopt.Args, repo *tuf.Repo) error { if err != nil { return err } - fmt.Print(string(p)) + fmt.Fprint(os.Stdout, string(p)) return nil } diff --git a/cmd/tuf/set_threshold.go b/cmd/tuf/set_threshold.go index 57754d24..29149ff9 100644 --- a/cmd/tuf/set_threshold.go +++ b/cmd/tuf/set_threshold.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "os" "strconv" "github.com/flynn/go-docopt" @@ -28,6 +29,6 @@ func cmdSetThreshold(args *docopt.Args, repo *tuf.Repo) error { return err } - fmt.Println("The threshold for", role, "role is now", threshold) + fmt.Fprintf(os.Stdout, "The threshold for %s role is now %d", role, threshold) return nil } diff --git a/cmd/tuf/sign_payload.go b/cmd/tuf/sign_payload.go index 8da5642b..6772972c 100644 --- a/cmd/tuf/sign_payload.go +++ b/cmd/tuf/sign_payload.go @@ -36,7 +36,7 @@ func cmdSignPayload(args *docopt.Args, repo *tuf.Repo) error { if err != nil { return err } - fmt.Print(string(bytes)) + fmt.Fprint(os.Stdout, string(bytes)) fmt.Fprintln(os.Stderr, "tuf: signed with", numKeys, "key(s)") return nil diff --git a/internal/fsutil/perm_test.go b/internal/fsutil/perm_test.go index 6061d291..f80ef94a 100644 --- a/internal/fsutil/perm_test.go +++ b/internal/fsutil/perm_test.go @@ -4,7 +4,6 @@ package fsutil import ( - "fmt" "os" "path/filepath" "testing" @@ -59,7 +58,6 @@ func TestEnsureMaxPermissions(t *testing.T) { assert.NoError(t, err) err = EnsureMaxPermissions(fi, os.FileMode(0222)) assert.Error(t, err) - fmt.Println(err) // Check matching due to more restrictive perms on file err = os.Chmod(p, 0444) diff --git a/local_store.go b/local_store.go index 1b4a7f60..fee03f31 100644 --- a/local_store.go +++ b/local_store.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "io/fs" + "log" "os" "path/filepath" "strings" @@ -197,18 +198,44 @@ type persistedKeys struct { Data json.RawMessage `json:"data"` } +type StoreOpts struct { + Logger *log.Logger + PassFunc util.PassphraseFunc +} + func FileSystemStore(dir string, p util.PassphraseFunc) LocalStore { return &fileSystemStore{ dir: dir, passphraseFunc: p, + logger: log.New(io.Discard, "", 0), signerForKeyID: make(map[string]keys.Signer), keyIDsForRole: make(map[string][]string), } } +func FileSystemStoreWithOpts(dir string, opts ...StoreOpts) LocalStore { + store := &fileSystemStore{ + dir: dir, + passphraseFunc: nil, + logger: log.New(io.Discard, "", 0), + signerForKeyID: make(map[string]keys.Signer), + keyIDsForRole: make(map[string][]string), + } + for _, opt := range opts { + if opt.Logger != nil { + store.logger = opt.Logger + } + if opt.PassFunc != nil { + store.passphraseFunc = opt.PassFunc + } + } + return store +} + type fileSystemStore struct { dir string passphraseFunc util.PassphraseFunc + logger *log.Logger signerForKeyID map[string]keys.Signer keyIDsForRole map[string][]string @@ -526,7 +553,7 @@ func (f *fileSystemStore) ChangePassphrase(role string) error { keys, _, err := f.loadPrivateKeys(role) if err != nil { if os.IsNotExist(err) { - fmt.Printf("Failed to change passphrase. Missing keys file for %s role. \n", role) + f.logger.Printf("Failed to change passphrase. Missing keys file for %s role. \n", role) } return err } @@ -548,7 +575,7 @@ func (f *fileSystemStore) ChangePassphrase(role string) error { if err := util.AtomicallyWriteFile(f.keysPath(role), append(data, '\n'), 0600); err != nil { return err } - fmt.Printf("Successfully changed passphrase for %s keys file\n", role) + f.logger.Printf("Successfully changed passphrase for %s keys file\n", role) return nil } diff --git a/pkg/keys/deprecated_ecdsa.go b/pkg/keys/deprecated_ecdsa.go index 4a8f151e..6d48c9d6 100644 --- a/pkg/keys/deprecated_ecdsa.go +++ b/pkg/keys/deprecated_ecdsa.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "io" - "os" "github.com/theupdateframework/go-tuf/data" ) @@ -98,6 +97,5 @@ func (p *deprecatedP256Verifier) UnmarshalPublicKey(key *data.PublicKey) error { } p.key = key - fmt.Fprintln(os.Stderr, "tuf: warning using deprecated ecdsa hex-encoded keys") return nil } diff --git a/repo.go b/repo.go index 603785f1..cce0020f 100644 --- a/repo.go +++ b/repo.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "log" "path" "sort" "strings" @@ -48,18 +49,47 @@ type Repo struct { meta map[string]json.RawMessage prefix string indent string + logger *log.Logger +} + +type RepoOpts func(r *Repo) + +func WithLogger(logger *log.Logger) RepoOpts { + return func(r *Repo) { + r.logger = logger + } +} + +func WithHashAlgorithms(hashAlgorithms ...string) RepoOpts { + return func(r *Repo) { + r.hashAlgorithms = hashAlgorithms + } +} + +func WithPrefix(prefix string) RepoOpts { + return func(r *Repo) { + r.prefix = prefix + } +} + +func WithIndex(indent string) RepoOpts { + return func(r *Repo) { + r.indent = indent + } } func NewRepo(local LocalStore, hashAlgorithms ...string) (*Repo, error) { return NewRepoIndent(local, "", "", hashAlgorithms...) } -func NewRepoIndent(local LocalStore, prefix string, indent string, hashAlgorithms ...string) (*Repo, error) { +func NewRepoIndent(local LocalStore, prefix string, indent string, + hashAlgorithms ...string) (*Repo, error) { r := &Repo{ local: local, hashAlgorithms: hashAlgorithms, prefix: prefix, indent: indent, + logger: log.New(io.Discard, "", 0), } var err error @@ -70,6 +100,17 @@ func NewRepoIndent(local LocalStore, prefix string, indent string, hashAlgorithm return r, nil } +func NewRepoWithOpts(local LocalStore, opts ...RepoOpts) (*Repo, error) { + r, err := NewRepo(local) + if err != nil { + return nil, err + } + for _, opt := range opts { + opt(r) + } + return r, nil +} + func (r *Repo) Init(consistentSnapshot bool) error { t, err := r.topLevelTargets() if err != nil { @@ -91,7 +132,7 @@ func (r *Repo) Init(consistentSnapshot bool) error { return err } - fmt.Println("Repository initialized") + r.logger.Println("Repository initialized") return nil } @@ -533,7 +574,7 @@ func (r *Repo) RevokeKeyWithExpires(keyRole, id string, expires time.Time) error err = r.setMeta("root.json", root) if err == nil { - fmt.Println("Revoked", keyRole, "key with ID", id, "in root metadata") + r.logger.Println("Revoked", keyRole, "key with ID", id, "in root metadata") } return err } @@ -783,7 +824,7 @@ func (r *Repo) Sign(roleFilename string) error { r.meta[roleFilename] = b err = r.local.SetMeta(roleFilename, b) if err == nil { - fmt.Println("Signed", roleFilename, "with", numKeys, "key(s)") + r.logger.Println("Signed", roleFilename, "with", numKeys, "key(s)") } return err } @@ -1223,7 +1264,7 @@ func (r *Repo) removeTargetsWithExpiresFromMeta(metaName string, paths []string, for _, path := range paths { path = util.NormalizeTarget(path) if _, ok := t.Targets[path]; !ok { - fmt.Printf("[%v] The following target is not present: %v\n", metaName, path) + r.logger.Printf("[%v] The following target is not present: %v\n", metaName, path) continue } removed = true @@ -1243,17 +1284,17 @@ func (r *Repo) removeTargetsWithExpiresFromMeta(metaName string, paths []string, err = r.setMeta(metaName, t) if err == nil { - fmt.Printf("[%v] Removed targets:\n", metaName) + r.logger.Printf("[%v] Removed targets:\n", metaName) for _, v := range removed_targets { - fmt.Println("*", v) + r.logger.Println("*", v) } if len(t.Targets) != 0 { - fmt.Printf("[%v] Added/staged targets:\n", metaName) + r.logger.Printf("[%v] Added/staged targets:\n", metaName) for k := range t.Targets { - fmt.Println("*", k) + r.logger.Println("*", k) } } else { - fmt.Printf("[%v] There are no added/staged targets\n", metaName) + r.logger.Printf("[%v] There are no added/staged targets\n", metaName) } } return err @@ -1307,7 +1348,7 @@ func (r *Repo) SnapshotWithExpires(expires time.Time) error { } err = r.setMeta("snapshot.json", snapshot) if err == nil { - fmt.Println("Staged snapshot.json metadata with expiration date:", snapshot.Expires) + r.logger.Println("Staged snapshot.json metadata with expiration date:", snapshot.Expires) } return err } @@ -1339,7 +1380,7 @@ func (r *Repo) TimestampWithExpires(expires time.Time) error { err = r.setMeta("timestamp.json", timestamp) if err == nil { - fmt.Println("Staged timestamp.json metadata with expiration date:", timestamp.Expires) + r.logger.Println("Staged timestamp.json metadata with expiration date:", timestamp.Expires) } return err } @@ -1505,7 +1546,7 @@ func (r *Repo) Commit() error { err = r.local.Commit(root.ConsistentSnapshot, versions, hashes) if err == nil { - fmt.Println("Committed successfully") + r.logger.Println("Committed successfully") } return err } @@ -1513,7 +1554,7 @@ func (r *Repo) Commit() error { func (r *Repo) Clean() error { err := r.local.Clean() if err == nil { - fmt.Println("Removed all staged metadata and target files") + r.logger.Println("Removed all staged metadata and target files") } return err } diff --git a/repo_test.go b/repo_test.go index 2f3aebb4..d841bb59 100644 --- a/repo_test.go +++ b/repo_test.go @@ -9,6 +9,7 @@ import ( "encoding/json" "errors" "fmt" + "log" "os" "path" "path/filepath" @@ -1422,7 +1423,12 @@ func (rs *RepoSuite) TestKeyPersistence(c *C) { // Test changing the passphrase // 1. Create a secure store with a passphrase (create new object and temp folder so we discard any previous state) tmp = newTmpDir(c) - store = FileSystemStore(tmp.path, testPassphraseFunc) + var logBytes bytes.Buffer + storeOpts := StoreOpts{ + Logger: log.New(&logBytes, "", 0), + PassFunc: testPassphraseFunc, + } + store = FileSystemStoreWithOpts(tmp.path, storeOpts) // 1.5. Changing passphrase works for top-level and delegated roles. r, err := NewRepo(store) @@ -1433,6 +1439,7 @@ func (rs *RepoSuite) TestKeyPersistence(c *C) { // 2. Test changing the passphrase when the keys file does not exist - should FAIL c.Assert(store.(PassphraseChanger).ChangePassphrase("root"), NotNil) + c.Assert(strings.Contains(logBytes.String(), "Missing keys file"), Equals, true) // 3. Generate a new key signer, err = keys.GenerateEd25519Key() From 0e33cdfd19658fc15d91f498e35b3a2633e28a2f Mon Sep 17 00:00:00 2001 From: Marina Moore Date: Wed, 21 Sep 2022 11:54:19 -0400 Subject: [PATCH 05/46] docs: Add docs for adding and rotating root keys (#389) * docs: Add docs for adding and rotating root keys Signed-off-by: Marina Moore * typo fix from review Signed-off-by: Marina Moore Signed-off-by: Marina Moore --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index b1a4b6ea..125978c1 100644 --- a/README.md +++ b/README.md @@ -603,6 +603,39 @@ $ tree . └── staged ``` +#### Adding a new root key + +Copy `staged/root.json` to the root box and generate a new root key on the root box: + +```bash +$ tuf gen-key root +$ tuf sign root.json +``` + +Copy `staged/root.json` from the root box and commit: + +```bash +$ tuf commit +``` + +#### Rotating root key(s) + +Copy `staged/root.json` to the root box to do the rotation, where `abcd` is the keyid of the key that is being replaced: + +```bash +$ tuf gen-key root +$ tuf revoke-key root abcd +$ tuf sign root.json +``` + +Note that `revoke-key` removes the old key from `root.json`, but the key remains in the `keys/` directory on the root box as it is needed to sign the next `root.json`. After this signing is done, the old key may be removed from `keys/`. Any number of keys may be added or revoked during this step, but ensure that at least a threshold of valid keys remain. + +Copy `staged/root.json` from the root box to commit: + +```bash +$ tuf commit +``` + ## Client For the client package, see https://godoc.org/github.com/theupdateframework/go-tuf/client. From 7f9beab143b1e5bfe25447c5504ea2f1e04803bb Mon Sep 17 00:00:00 2001 From: Zack Newman Date: Wed, 21 Sep 2022 12:03:22 -0400 Subject: [PATCH 06/46] chore: update TUF spec version (#392) We fixed #321 but forgot to update this, so now the GH actions bot is confused (#391). Signed-off-by: Zachary Newman --- .github/workflows/specification-version-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/specification-version-check.yml b/.github/workflows/specification-version-check.yml index 1c4834f8..44218e1a 100644 --- a/.github/workflows/specification-version-check.yml +++ b/.github/workflows/specification-version-check.yml @@ -11,4 +11,4 @@ jobs: issues: write uses: theupdateframework/specification/.github/workflows/check-latest-spec-version.yml@master with: - tuf-version: "v1.0.29" # Should be updated to the according version either manually or extracted automatically as how it's done in python-tuf + tuf-version: "v1.0.30" # Should be updated to the according version either manually or extracted automatically as how it's done in python-tuf From 8a4aabfd6040b1337938bacae09845bb6be42ed4 Mon Sep 17 00:00:00 2001 From: Zack Newman Date: Wed, 21 Sep 2022 19:20:46 -0400 Subject: [PATCH 07/46] test: update lint CI parameters (#394) tests: update lint CI parameters Context: linting in CI (`golangci-lint`) occasionally times out on Windows (flaky). Most of the time, it's fast enough (~1min). But occasionally it hits the 3 minute timeout. It's somewhat expected that `golangci-lint` is slow: https://github.com/golangci/golangci-lint-action/issues/297 This PR does 3 things: 1. Bump the timeout from 3 to 5 minutes (why solve the problem when you can band-aid it?) 2. Add the `--verbose` flag, so if we start to see this again we'll have much better information with which to figure out what specifically is taking so long. 3. Remove the patch number from the `golangci-lint` version; it's disallowed, according to the `golangci-lint` action README. Fixes #390 (for now). Signed-off-by: Zachary Newman Signed-off-by: Zachary Newman --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a805655a..9bcde9c5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -65,5 +65,5 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@537aa1903e5d359d0b27dbc19ddd22c5087f3fbc with: - version: v1.49.0 - args: --timeout 3m + version: v1.49 + args: --timeout 5m --verbose From 6ea14f5b38354cef05bbaf1c2c1b4971b0165dcd Mon Sep 17 00:00:00 2001 From: Zack Newman Date: Wed, 21 Sep 2022 19:21:48 -0400 Subject: [PATCH 08/46] chore: update TUF spec version to 1.0.31 (#393) Fixes #391; see that issue for justification. Signed-off-by: Zachary Newman Signed-off-by: Zachary Newman --- .github/workflows/specification-version-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/specification-version-check.yml b/.github/workflows/specification-version-check.yml index 44218e1a..f128207d 100644 --- a/.github/workflows/specification-version-check.yml +++ b/.github/workflows/specification-version-check.yml @@ -11,4 +11,4 @@ jobs: issues: write uses: theupdateframework/specification/.github/workflows/check-latest-spec-version.yml@master with: - tuf-version: "v1.0.30" # Should be updated to the according version either manually or extracted automatically as how it's done in python-tuf + tuf-version: "v1.0.31" # Should be updated to the according version either manually or extracted automatically as how it's done in python-tuf From e56ccf66a7f2fe1ae04c0994da2736d8c2d36681 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 10:12:45 -0400 Subject: [PATCH 09/46] chore(deps): bump amannn/action-semantic-pull-request from 4.5.0 to 4.6.0 (#398) chore(deps): bump amannn/action-semantic-pull-request Bumps [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) from 4.5.0 to 4.6.0. - [Release notes](https://github.com/amannn/action-semantic-pull-request/releases) - [Changelog](https://github.com/amannn/action-semantic-pull-request/blob/main/CHANGELOG.md) - [Commits](https://github.com/amannn/action-semantic-pull-request/compare/91682d013dea3ff257520b9b68c9cb93ced4fe9b...505e44b4f33b4c801f063838b3f053990ee46ea7) --- updated-dependencies: - dependency-name: amannn/action-semantic-pull-request dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index c283a6be..f3f9e439 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -13,6 +13,6 @@ jobs: runs-on: "ubuntu-latest" steps: - name: - uses: amannn/action-semantic-pull-request@91682d013dea3ff257520b9b68c9cb93ced4fe9b + uses: amannn/action-semantic-pull-request@505e44b4f33b4c801f063838b3f053990ee46ea7 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From f75cbcc8550dfb9311c6723999fe7b1d3d2bc116 Mon Sep 17 00:00:00 2001 From: asraa Date: Tue, 27 Sep 2022 12:40:49 -0500 Subject: [PATCH 10/46] fix(cmd): fix logging of help message (#395) fix: fix logging of help message Signed-off-by: Asra Ali Signed-off-by: Asra Ali --- cmd/tuf-client/main.go | 2 +- cmd/tuf/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/tuf-client/main.go b/cmd/tuf-client/main.go index 25a32005..df3632b2 100644 --- a/cmd/tuf-client/main.go +++ b/cmd/tuf-client/main.go @@ -33,7 +33,7 @@ See "tuf-client help " for more information on a specific command. if cmd == "help" { if len(cmdArgs) == 0 { // `tuf-client help` - fmt.Fprint(os.Stderr, usage) + fmt.Fprint(os.Stdout, usage) return } else { // `tuf-client help ` cmd = cmdArgs[0] diff --git a/cmd/tuf/main.go b/cmd/tuf/main.go index 6ee220b2..dc6a256c 100644 --- a/cmd/tuf/main.go +++ b/cmd/tuf/main.go @@ -58,7 +58,7 @@ See "tuf help " for more information on a specific command if cmd == "help" { if len(cmdArgs) == 0 { // `tuf help` - fmt.Fprint(os.Stderr, usage) + fmt.Fprint(os.Stdout, usage) return } else { // `tuf help ` cmd = cmdArgs[0] From b611a26358a47179232a9ba3d909eb47798e3399 Mon Sep 17 00:00:00 2001 From: Zack Newman Date: Wed, 28 Sep 2022 12:36:06 -0400 Subject: [PATCH 11/46] docs: fix broken link (#401) [docs] Fix broken link Signed-off-by: Zachary Newman Signed-off-by: Zachary Newman --- docs/TESTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/TESTING.md b/docs/TESTING.md index 3a00a95b..fd755365 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -15,4 +15,4 @@ go test ./... To update the data for these tests requires Docker and make (see -test data [README.md](client/python_interop/testdata/README.md) for details). \ No newline at end of file +test data [README.md](../client/python_interop/testdata/README.md) for details). From 4f55897602eacf9fc202b8a7f25236d21bfc800a Mon Sep 17 00:00:00 2001 From: Ville Aikas <11279988+vaikas@users.noreply.github.com> Date: Wed, 28 Sep 2022 14:08:59 -0700 Subject: [PATCH 12/46] test: Do not fail-fast when CI runs. (#403) do not fail fast. Signed-off-by: Ville Aikas Signed-off-by: Ville Aikas --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9bcde9c5..cf53fcc3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,6 +14,7 @@ jobs: run: strategy: + fail-fast: false # Keep running if one leg fails. matrix: os: [ubuntu-latest, macos-latest, windows-latest] go-version: ${{ fromJSON(needs.get-go-versions.outputs.matrix) }} From 22f95c0a789bde1f89f6319be8aa2bb8f6ccc025 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:04:02 -0400 Subject: [PATCH 13/46] chore(deps): bump iso8601 from 1.0.2 to 1.1.0 (#404) Bumps [iso8601](https://github.com/micktwomey/pyiso8601) from 1.0.2 to 1.1.0. - [Release notes](https://github.com/micktwomey/pyiso8601/releases) - [Commits](https://github.com/micktwomey/pyiso8601/compare/1.0.2...1.1.0) --- updated-dependencies: - dependency-name: iso8601 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-test.txt b/requirements-test.txt index 9d0b3f7f..05fae07d 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,4 +1,4 @@ -iso8601==1.0.2 +iso8601==1.1.0 requests==2.28.1 securesystemslib==0.24.0 six==1.16.0 From 2541d68b83e92c9f78a1daa79e73e83d288a0b9f Mon Sep 17 00:00:00 2001 From: Abhisman Date: Fri, 30 Sep 2022 16:34:16 +0530 Subject: [PATCH 14/46] docs: fix broken link (#405) Signed-off-by: Abhisman --- docs/TESTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/TESTING.md b/docs/TESTING.md index fd755365..5549853c 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -1,6 +1,6 @@ # Testing -The [Python interoperability tests](client/python_interop/) require Python 3 +The [Python interoperability tests](../client/python_interop/) require Python 3 (available as `python` on the `$PATH`) and the [`python-tuf` package](https://github.com/theupdateframework/python-tuf) installed. To use the correct versions of the packages, it is recommended to use a [virtual environment](https://docs.python.org/3/library/venv.html#module-venv) and install the dependencies via: From 3890c1e7ace43d67622428187a85ba486c2528e5 Mon Sep 17 00:00:00 2001 From: Ville Aikas <11279988+vaikas@users.noreply.github.com> Date: Fri, 30 Sep 2022 04:28:10 -0700 Subject: [PATCH 15/46] feat: Add Filesystem based remote store to support airgap. (#397) * Add Filesystem based remote store to support airgap. Signed-off-by: Ville Aikas * Try with T.Cleanup too. Wonder if this goes to 11 at some point? Signed-off-by: Ville Aikas * close the file. Signed-off-by: Ville Aikas * t.Cleanup vs. defer. Signed-off-by: Ville Aikas * omit one initializing test for windows. Signed-off-by: Ville Aikas Signed-off-by: Ville Aikas Co-authored-by: Joshua Lock --- client/client.go | 2 + client/client_test.go | 163 ++++++++++++++++++++++--------- client/file_store.go | 90 +++++++++++++++++ client/file_store_test.go | 197 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 407 insertions(+), 45 deletions(-) create mode 100644 client/file_store.go create mode 100644 client/file_store_test.go diff --git a/client/client.go b/client/client.go index 5308b97b..f103d802 100644 --- a/client/client.go +++ b/client/client.go @@ -807,6 +807,8 @@ type Destination interface { // - The target does not exist in any targets // - Metadata cannot be generated for the downloaded data // - Generated metadata does not match local metadata for the given file +// - Size of the download does not match if the reported size is known and +// incorrect func (c *Client) Download(name string, dest Destination) (err error) { // delete dest if there is an error defer func() { diff --git a/client/client_test.go b/client/client_test.go index c583e2f1..327b1371 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -31,15 +31,19 @@ import ( func Test(t *testing.T) { TestingT(t) } type ClientSuite struct { - store tuf.LocalStore - repo *tuf.Repo - local LocalStore - remote *fakeRemoteStore - expiredTime time.Time - keyIDs map[string][]string + store tuf.LocalStore + repo *tuf.Repo + local LocalStore + remote RemoteStore + expiredTime time.Time + keyIDs map[string][]string + useFileStore bool + // Only used with FileStore + tmpDir string } -var _ = Suite(&ClientSuite{}) +var _ = Suite(&ClientSuite{useFileStore: false}) +var _ = Suite(&ClientSuite{useFileStore: true}) func newFakeRemoteStore() *fakeRemoteStore { return &fakeRemoteStore{ @@ -69,6 +73,66 @@ func (f *fakeRemoteStore) get(name string, store map[string]*fakeFile) (io.ReadC return file, file.size, nil } +// These are helper methods for manipulating the internals of the Stores +// because the set/delete methods are not part of the Interface, we need to +// switch on the underlying implementation. +// Also readMeta method is convenience for ease of testing. +func (s *ClientSuite) setRemoteMeta(path string, data []byte) error { + switch impl := s.remote.(type) { + case *fakeRemoteStore: + impl.meta[path] = newFakeFile(data) + return nil + case *FileRemoteStore: + return impl.addMeta(path, data) + default: + return fmt.Errorf("non-supoprted RemoteStore, got %+v", impl) + } +} + +func (s *ClientSuite) setRemoteTarget(path string, data []byte) error { + switch impl := s.remote.(type) { + case *fakeRemoteStore: + impl.targets[path] = newFakeFile(data) + return nil + case *FileRemoteStore: + return impl.addTarget(path, data) + default: + return fmt.Errorf("non-supoprted RemoteStore, got %+v", impl) + } +} + +func (s *ClientSuite) deleteMeta(path string) error { + switch impl := s.remote.(type) { + case *fakeRemoteStore: + delete(impl.meta, path) + return nil + case *FileRemoteStore: + return impl.deleteMeta(path) + default: + return fmt.Errorf("non-supported RemoteStore, got %+v", impl) + } +} + +func (s *ClientSuite) deleteTarget(path string) error { + switch impl := s.remote.(type) { + case *fakeRemoteStore: + delete(impl.targets, path) + return nil + case *FileRemoteStore: + return impl.deleteTarget(path) + default: + return fmt.Errorf("non-supported RemoteStore, got %+v", impl) + } +} + +func (s *ClientSuite) readMeta(name string) ([]byte, error) { + stream, _, err := s.remote.GetMeta(name) + if err != nil { + return nil, err + } + return io.ReadAll(stream) +} + func newFakeFile(b []byte) *fakeFile { return &fakeFile{buf: bytes.NewReader(b), size: int64(len(b))} } @@ -118,15 +182,28 @@ func (s *ClientSuite) SetUpTest(c *C) { c.Assert(s.repo.Commit(), IsNil) // create a remote store containing valid repo files - s.remote = newFakeRemoteStore() + if s.useFileStore { + s.remote, s.tmpDir, err = newTestFileStoreFS() + if err != nil { + c.Fatalf("failed to create new FileStore: %v", err) + } + } else { + s.remote = newFakeRemoteStore() + } s.syncRemote(c) for path, data := range targetFiles { - s.remote.targets[path] = newFakeFile(data) + s.setRemoteTarget(path, data) } s.expiredTime = time.Now().Add(time.Hour) } +func (s *ClientSuite) TearDownTest(c *C) { + if s.tmpDir != "" { + rmrf(s.tmpDir, c.Logf) + } +} + func (s *ClientSuite) genKey(c *C, role string) []string { ids, err := s.repo.GenKey(role) c.Assert(err, IsNil) @@ -163,7 +240,9 @@ func (s *ClientSuite) syncRemote(c *C) { meta, err := s.store.GetMeta() c.Assert(err, IsNil) for name, data := range meta { - s.remote.meta[name] = newFakeFile(data) + if err := s.setRemoteMeta(name, data); err != nil { + panic(fmt.Sprintf("setMetadata failed: %v", err)) + } } } @@ -252,7 +331,7 @@ func (s *ClientSuite) TestInitAllowsExpired(c *C) { c.Assert(s.repo.Commit(), IsNil) s.syncRemote(c) client := NewClient(MemoryLocalStore(), s.remote) - bytes, err := io.ReadAll(s.remote.meta["root.json"]) + bytes, err := s.readMeta("root.json") c.Assert(err, IsNil) s.withMetaExpired(func() { c.Assert(client.Init(bytes), IsNil) @@ -261,7 +340,7 @@ func (s *ClientSuite) TestInitAllowsExpired(c *C) { func (s *ClientSuite) TestInit(c *C) { client := NewClient(MemoryLocalStore(), s.remote) - bytes, err := io.ReadAll(s.remote.meta["root.json"]) + bytes, err := s.readMeta("root.json") c.Assert(err, IsNil) dataSigned := &data.Signed{} c.Assert(json.Unmarshal(bytes, dataSigned), IsNil) @@ -299,11 +378,11 @@ func (s *ClientSuite) TestFirstUpdate(c *C) { func (s *ClientSuite) TestMissingRemoteMetadata(c *C) { client := s.newClient(c) - delete(s.remote.meta, "targets.json") + s.deleteMeta("targets.json") _, err := client.Update() c.Assert(err, Equals, ErrMissingRemoteMetadata{"targets.json"}) - delete(s.remote.meta, "timestamp.json") + s.deleteMeta("timestamp.json") _, err = client.Update() c.Assert(err, Equals, ErrMissingRemoteMetadata{"timestamp.json"}) } @@ -774,7 +853,7 @@ func (s *ClientSuite) TestLocalExpired(c *C) { } func (s *ClientSuite) TestTimestampTooLarge(c *C) { - s.remote.meta["timestamp.json"] = newFakeFile(make([]byte, defaultTimestampDownloadLimit+1)) + s.setRemoteMeta("timestamp.json", make([]byte, defaultTimestampDownloadLimit+1)) _, err := s.newClient(c).Update() c.Assert(err, Equals, ErrMetaTooLarge{"timestamp.json", defaultTimestampDownloadLimit + 1, defaultTimestampDownloadLimit}) } @@ -901,8 +980,8 @@ func (s *ClientSuite) TestUpdateMixAndMatchAttack(c *C) { client := s.updatedClient(c) // grab the remote targets.json - oldTargets, ok := s.remote.meta["targets.json"] - if !ok { + oldTargets, err := s.readMeta("targets.json") + if err != nil { c.Fatal("missing remote targets.json") } @@ -912,22 +991,22 @@ func (s *ClientSuite) TestUpdateMixAndMatchAttack(c *C) { c.Assert(s.repo.Timestamp(), IsNil) c.Assert(s.repo.Commit(), IsNil) s.syncRemote(c) - newTargets, ok := s.remote.meta["targets.json"] - if !ok { + newTargets, err := s.readMeta("targets.json") + if err != nil { c.Fatal("missing remote targets.json") } - s.remote.meta["targets.json"] = oldTargets + s.setRemoteMeta("targets.json", oldTargets) // check update returns ErrWrongSize for targets.json - _, err := client.Update() - c.Assert(err, DeepEquals, ErrWrongSize{"targets.json", oldTargets.size, newTargets.size}) + _, err = client.Update() + c.Assert(err, DeepEquals, ErrWrongSize{"targets.json", int64(len(oldTargets)), int64(len(newTargets))}) // do the same but keep the size the same c.Assert(s.repo.RemoveTargetWithExpires("foo.txt", expires), IsNil) c.Assert(s.repo.Snapshot(), IsNil) c.Assert(s.repo.Timestamp(), IsNil) s.syncRemote(c) - s.remote.meta["targets.json"] = oldTargets + s.setRemoteMeta("targets.json", oldTargets) // check update returns ErrWrongHash _, err = client.Update() @@ -938,8 +1017,8 @@ func (s *ClientSuite) TestUpdateReplayAttack(c *C) { client := s.updatedClient(c) // grab the remote timestamp.json - oldTimestamp, ok := s.remote.meta["timestamp.json"] - if !ok { + oldTimestamp, err := s.readMeta("timestamp.json") + if err != nil { c.Fatal("missing remote timestamp.json") } @@ -948,12 +1027,12 @@ func (s *ClientSuite) TestUpdateReplayAttack(c *C) { c.Assert(version > 0, Equals, true) c.Assert(s.repo.Timestamp(), IsNil) s.syncRemote(c) - _, err := client.Update() + _, err = client.Update() c.Assert(err, IsNil) c.Assert(client.timestampVer > version, Equals, true) // replace remote timestamp.json with the old one - s.remote.meta["timestamp.json"] = oldTimestamp + s.setRemoteMeta("timestamp.json", oldTimestamp) // check update returns ErrLowVersion _, err = client.Update() @@ -970,8 +1049,8 @@ func (s *ClientSuite) TestUpdateForkTimestamp(c *C) { client := s.updatedClient(c) // grab the remote timestamp.json - oldTimestamp, ok := s.remote.meta["timestamp.json"] - if !ok { + oldTimestamp, err := s.readMeta("timestamp.json") + if err != nil { c.Fatal("missing remote timestamp.json") } @@ -980,13 +1059,13 @@ func (s *ClientSuite) TestUpdateForkTimestamp(c *C) { c.Assert(version > 0, Equals, true) c.Assert(s.repo.Timestamp(), IsNil) s.syncRemote(c) - _, err := client.Update() + _, err = client.Update() c.Assert(err, IsNil) newVersion := client.timestampVer c.Assert(newVersion > version, Equals, true) // generate a new, different timestamp with the *same version* - s.remote.meta["timestamp.json"] = oldTimestamp + s.setRemoteMeta("timestamp.json", oldTimestamp) c.Assert(s.repo.Timestamp(), IsNil) c.Assert(client.timestampVer, Equals, newVersion) // double-check: same version? s.syncRemote(c) @@ -1098,7 +1177,7 @@ func (s *ClientSuite) TestDownloadUnknownTarget(c *C) { func (s *ClientSuite) TestDownloadNoExist(c *C) { client := s.updatedClient(c) - delete(s.remote.targets, "foo.txt") + s.deleteTarget("foo.txt") var dest testDestination c.Assert(client.Download("foo.txt", &dest), Equals, ErrNotFound{"foo.txt"}) c.Assert(dest.deleted, Equals, true) @@ -1117,29 +1196,24 @@ func (s *ClientSuite) TestDownloadOK(c *C) { func (s *ClientSuite) TestDownloadWrongSize(c *C) { client := s.updatedClient(c) - remoteFile := &fakeFile{buf: bytes.NewReader([]byte("wrong-size")), size: 10} - s.remote.targets["foo.txt"] = remoteFile + // Update with a file that's incorrect size. + s.setRemoteTarget("foo.txt", []byte("wrong-size")) var dest testDestination c.Assert(client.Download("foo.txt", &dest), DeepEquals, ErrWrongSize{"foo.txt", 10, 3}) - c.Assert(remoteFile.bytesRead, Equals, 0) c.Assert(dest.deleted, Equals, true) } func (s *ClientSuite) TestDownloadTargetTooLong(c *C) { client := s.updatedClient(c) - remoteFile := s.remote.targets["foo.txt"] - remoteFile.buf = bytes.NewReader([]byte("foo-ooo")) + s.setRemoteTarget("foo.txt", []byte("foo-ooo")) var dest testDestination - c.Assert(client.Download("foo.txt", &dest), IsNil) - c.Assert(remoteFile.bytesRead, Equals, 3) - c.Assert(dest.deleted, Equals, false) - c.Assert(dest.String(), Equals, "foo") + c.Assert(client.Download("foo.txt", &dest), DeepEquals, ErrWrongSize{"foo.txt", 7, 3}) + c.Assert(dest.deleted, Equals, true) } func (s *ClientSuite) TestDownloadTargetTooShort(c *C) { client := s.updatedClient(c) - remoteFile := s.remote.targets["foo.txt"] - remoteFile.buf = bytes.NewReader([]byte("fo")) + s.setRemoteTarget("foo.txt", []byte("fo")) var dest testDestination c.Assert(client.Download("foo.txt", &dest), DeepEquals, ErrWrongSize{"foo.txt", 2, 3}) c.Assert(dest.deleted, Equals, true) @@ -1147,8 +1221,7 @@ func (s *ClientSuite) TestDownloadTargetTooShort(c *C) { func (s *ClientSuite) TestDownloadTargetCorruptData(c *C) { client := s.updatedClient(c) - remoteFile := s.remote.targets["foo.txt"] - remoteFile.buf = bytes.NewReader([]byte("corrupt")) + s.setRemoteTarget("foo.txt", []byte("ooo")) var dest testDestination assertWrongHash(c, client.Download("foo.txt", &dest)) c.Assert(dest.deleted, Equals, true) diff --git a/client/file_store.go b/client/file_store.go new file mode 100644 index 00000000..520bbe73 --- /dev/null +++ b/client/file_store.go @@ -0,0 +1,90 @@ +package client + +import ( + "bytes" + "errors" + "fmt" + "io" + "io/fs" +) + +// FileRemoteStore provides a RemoteStore interface compatible +// implementation that can be used where the RemoteStore is backed by a +// fs.FS. This is useful for example in air-gapped environments where there's no +// possibility to make outbound network connections. +// By having this be a fs.FS instead of directories allows the repository to +// be backed by something that's not persisted to disk. +func NewFileRemoteStore(fsys fs.FS, targetDir string) (*FileRemoteStore, error) { + if fsys == nil { + return nil, errors.New("nil fs.FS") + } + t := targetDir + if t == "" { + t = "targets" + } + // Make sure directory exists + d, err := fsys.Open(t) + if err != nil { + return nil, fmt.Errorf("failed to open targets directory %s: %w", t, err) + } + fi, err := d.Stat() + if err != nil { + return nil, fmt.Errorf("failed to stat targets directory %s: %w", t, err) + } + if !fi.IsDir() { + return nil, fmt.Errorf("targets directory not a directory %s", t) + } + + fsysT, err := fs.Sub(fsys, t) + if err != nil { + return nil, fmt.Errorf("failed to open targets directory %s: %w", t, err) + } + return &FileRemoteStore{fsys: fsys, targetDir: fsysT}, nil +} + +type FileRemoteStore struct { + // Meta directory fs + fsys fs.FS + // Target directory fs. + targetDir fs.FS + // In order to be able to make write operations (create, delete) we can't + // use fs.FS for it (it's read only), so we have to know the underlying + // directory that add/delete test methods can use. This is only necessary + // for testing purposes. + testDir string +} + +func (f *FileRemoteStore) GetMeta(name string) (io.ReadCloser, int64, error) { + rc, b, err := f.get(f.fsys, name) + return handleErrors(name, rc, b, err) +} + +func (f *FileRemoteStore) GetTarget(name string) (io.ReadCloser, int64, error) { + rc, b, err := f.get(f.targetDir, name) + return handleErrors(name, rc, b, err) +} + +func (f *FileRemoteStore) get(fsys fs.FS, s string) (io.ReadCloser, int64, error) { + if !fs.ValidPath(s) { + return nil, 0, fmt.Errorf("invalid path %s", s) + } + + b, err := fs.ReadFile(fsys, s) + if err != nil { + return nil, -1, err + } + return io.NopCloser(bytes.NewReader(b)), int64(len(b)), nil +} + +// handleErrors converts NotFound errors to something that TUF knows how to +// handle properly. For example, when looking for n+1 root files, this is a +// signal that it will stop looking. +func handleErrors(name string, rc io.ReadCloser, b int64, err error) (io.ReadCloser, int64, error) { + if err == nil { + return rc, b, err + } + if errors.Is(err, fs.ErrNotExist) { + return rc, b, ErrNotFound{name} + } + return rc, b, err +} diff --git a/client/file_store_test.go b/client/file_store_test.go new file mode 100644 index 00000000..95e02e38 --- /dev/null +++ b/client/file_store_test.go @@ -0,0 +1,197 @@ +package client + +import ( + "bytes" + "io" + "io/fs" + "os" + "path/filepath" + "runtime" + "strings" + "testing" +) + +const targetsDir = "targets" + +func TestCreates(t *testing.T) { + runningWindows := false + if runtime.GOOS == "windows" { + runningWindows = true + } + tmpDir := t.TempDir() + defer os.RemoveAll(tmpDir) + dir := filepath.Join(tmpDir, "repository") + os.Mkdir(dir, os.ModePerm) + os.Mkdir(filepath.Join(dir, "targets"), os.ModePerm) + if !runningWindows { + targetDirThatIsFile := filepath.Join(dir, "targets-that-isfile") + f, err := os.Create(targetDirThatIsFile) + if err != nil { + t.Fatalf("failed to create file: %s: %v", targetDirThatIsFile, err) + } + defer f.Close() + } + t.Cleanup(func() { rmrf(dir, t.Logf) }) + t.Cleanup(func() { rmrf(tmpDir, t.Logf) }) + + tests := []struct { + name string + fsys fs.FS + td string + wantErr string + doNotRunOnWindows bool + }{{ + name: "nil, error", + wantErr: "nil fs.FS", + }, { + name: "missing targets directory", + fsys: os.DirFS(dir), + td: "targets-not-there", + wantErr: "failed to open targets directory targets-not-there", + }, { + name: "targets directory is not a file", + fsys: os.DirFS(dir), + td: "targets-that-isfile", + wantErr: "targets directory not a directory targets-that-isfile", + doNotRunOnWindows: true, + }, { + name: "works, explicit targets", + fsys: os.DirFS(dir), + td: "targets", + }, { + name: "works, explicit targets", + fsys: os.DirFS(dir), + td: "targets", + }} + + for _, tc := range tests { + if tc.doNotRunOnWindows { + t.Skip("Can't figure out how to make this work on windows") + } + _, err := NewFileRemoteStore(tc.fsys, tc.td) + if tc.wantErr != "" && err == nil { + t.Errorf("%q wanted error %s, got none", tc.name, tc.wantErr) + } else if tc.wantErr == "" && err != nil { + t.Errorf("%q did not want error, got: %v", tc.name, err) + } else if err != nil && !strings.Contains(err.Error(), tc.wantErr) { + t.Errorf("%q wanted error %s but got: %s", tc.name, tc.wantErr, err) + } + } +} + +func TestBasicOps(t *testing.T) { + metas := map[string][]byte{ + "root.json": []byte("root"), + "snapshot.json": []byte("snapshot"), + "timestamp": []byte("timestamp"), + } + + fsys, dir, err := newTestFileStoreFS() + if err != nil { + t.Fatalf("Failed to create test FileStore") + } + t.Cleanup(func() { rmrf(dir, t.Logf) }) + defer os.RemoveAll(dir) + + // Add targets and metas and check them. + for k, v := range targetFiles { + if err := fsys.addTarget(k, v); err != nil { + t.Errorf("failed to add target %s: %v", k, err) + } + rc, size, err := fsys.GetTarget(k) + if err != nil { + t.Errorf("failed to GetTarget %s: %v", k, err) + } + if size != int64(len(v)) { + t.Errorf("unexpected size returned for GetTarget: %s want %d got %d", k, len(v), size) + } + got, err := io.ReadAll(rc) + if err != nil { + t.Errorf("failed to ReadAll returned ReacCloser %s: %v", k, err) + } + if !bytes.Equal(v, got) { + t.Errorf("Read unexpected bytes, want: %s got: %s", string(k), string(got)) + } + } + for k, v := range metas { + if err := fsys.addMeta(k, v); err != nil { + t.Errorf("failed to add meta %s %v", k, err) + } + rc, size, err := fsys.GetMeta(k) + if err != nil { + t.Errorf("failed to GetMeta %s: %v", k, err) + } + if size != int64(len(v)) { + t.Errorf("unexpected size returned for GetMeta: %s want %d got %d", k, len(v), size) + } + got, err := io.ReadAll(rc) + if err != nil { + t.Errorf("failed to ReadAll returned ReacCloser %s: %v", k, err) + } + if !bytes.Equal(v, got) { + t.Errorf("Read unexpected bytes, want: %s got: %s", string(k), string(got)) + } + } +} + +// Test helper methods +func (f *FileRemoteStore) addMeta(name string, data []byte) error { + return os.WriteFile(filepath.Join(f.testDir, name), data, os.ModePerm) +} + +func (f *FileRemoteStore) addTarget(name string, data []byte) error { + fname := filepath.Join(f.testDir, targetsDir, name) + err := os.WriteFile(fname, data, os.ModePerm) + return err +} + +func (f *FileRemoteStore) deleteMeta(name string) error { + return os.Remove(filepath.Join(f.testDir, name)) +} + +func (f *FileRemoteStore) deleteTarget(name string) error { + return os.Remove(filepath.Join(f.testDir, targetsDir, name)) +} + +func newTestFileStoreFS() (*FileRemoteStore, string, error) { + tmpDir := os.TempDir() + tufDir := filepath.Join(tmpDir, "tuf-file-store-test") + // Clean it in case there is cruft left around + os.RemoveAll(tufDir) + os.Mkdir(tufDir, os.ModePerm) + os.Mkdir(filepath.Join(tufDir, targetsDir), os.ModePerm) + fs, err := NewFileRemoteStore(os.DirFS(tufDir), targetsDir) + fs.testDir = tufDir + return fs, tufDir, err +} + +// goes through a dir and removes everything. This is to work around: +// https://github.com/golang/go/issues/51442 +func rmrf(dir string, logger func(string, ...interface{})) { + if dir == "" { + logger("cowardly refusing to remove a not fully specified fir") + return + } + logger("Removing %s", dir) + d, err := os.Open(dir) + if err != nil { + logger("Failed to open %s: %v", dir, err) + return + } + defer d.Close() + // -1 means give me everything, we don't have that many entries, so + // fine here. + names, err := d.Readdirnames(-1) + if err != nil { + logger("Failed to ReaddirNames %s: %v", dir, err) + return + } + for _, name := range names { + toRemove := filepath.Join(dir, name) + err = os.RemoveAll(toRemove) + if err != nil { + logger("Failed to RemoveAll %s: %v", toRemove, err) + // Do not want to fail here, just keep doing the best we can + } + } +} From b4b954d5250b438b244ebaeed5fab56fec8f06b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 15:04:50 -0400 Subject: [PATCH 16/46] chore(deps): bump arnested/go-version-action from 1.1.5 to 1.1.6 (#408) Bumps [arnested/go-version-action](https://github.com/arnested/go-version-action) from 1.1.5 to 1.1.6. - [Release notes](https://github.com/arnested/go-version-action/releases) - [Commits](https://github.com/arnested/go-version-action/compare/6d27c5921683f55415260f7a285d330ddb146fa2...b556f8d91b644164318c709d28b9083eaf0c064d) --- updated-dependencies: - dependency-name: arnested/go-version-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- .github/workflows/tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 00018f61..69d74bfa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: with: fetch-depth: 0 - name: Get Go version - uses: arnested/go-version-action@6d27c5921683f55415260f7a285d330ddb146fa2 + uses: arnested/go-version-action@b556f8d91b644164318c709d28b9083eaf0c064d id: go-version - name: Set up Go uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cf53fcc3..adf8ec4d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ jobs: matrix: ${{ steps.versions.outputs.matrix }} steps: - uses: actions/checkout@v3 - - uses: arnested/go-version-action@6d27c5921683f55415260f7a285d330ddb146fa2 + - uses: arnested/go-version-action@b556f8d91b644164318c709d28b9083eaf0c064d id: versions run: From adbdc7d5f6960d8c63e978f27860fb9f8953a9d2 Mon Sep 17 00:00:00 2001 From: Arthur Bellal Date: Wed, 5 Oct 2022 20:06:33 +0200 Subject: [PATCH 17/46] fix(data): add back SnapshotFileMeta.Custom (#373) add back SnapshotFileMeta.custom Signed-off-by: Arthur Bellal Signed-off-by: Arthur Bellal --- data/types.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/data/types.go b/data/types.go index d051b762..3e1806bd 100644 --- a/data/types.go +++ b/data/types.go @@ -172,11 +172,14 @@ func (f Hashes) HashAlgorithms() []string { } type metapathFileMeta struct { - Length int64 `json:"length,omitempty"` - Hashes Hashes `json:"hashes,omitempty"` - Version int64 `json:"version"` + Length int64 `json:"length,omitempty"` + Hashes Hashes `json:"hashes,omitempty"` + Version int64 `json:"version"` + Custom *json.RawMessage `json:"custom,omitempty"` } +// SnapshotFileMeta is the meta field of a snapshot +// Note: Contains a `custom` field type SnapshotFileMeta metapathFileMeta type SnapshotFiles map[string]SnapshotFileMeta From 14853e3bc59fe2ab3897f5b2c3ac5d224a7ee7b6 Mon Sep 17 00:00:00 2001 From: Zack Newman Date: Thu, 6 Oct 2022 02:39:34 -0600 Subject: [PATCH 18/46] chore: update release notes breaking change regex (#409) Signed-off-by: Zachary Newman Signed-off-by: Zachary Newman --- .goreleaser/tuf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser/tuf.yml b/.goreleaser/tuf.yml index eaa45c77..4662f273 100644 --- a/.goreleaser/tuf.yml +++ b/.goreleaser/tuf.yml @@ -23,7 +23,7 @@ changelog: use: github groups: - title: "Breaking changes" - regexp: "^.*BREAKING CHANGE[(\\w)]*:+.*$" + regexp: "^.*(?:BREAKING CHANGE)|![(\\w)]*:+.*$" order: 0 - title: Features regexp: "^.*feat[(\\w)]*:+.*$" From 47058744075a884dd3f0b55b0d64017e71db34d6 Mon Sep 17 00:00:00 2001 From: asraa Date: Thu, 6 Oct 2022 09:59:07 -0500 Subject: [PATCH 19/46] fix: fix delegation null json value interoperability (#410) fix: fix delegation null json value Signed-off-by: Asra Ali Signed-off-by: Asra Ali Co-authored-by: Radoslav Dimitrov --- client/python_interop/python_interop_test.go | 68 +++++++++++++++++++- repo.go | 3 +- repo_test.go | 8 +++ 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/client/python_interop/python_interop_test.go b/client/python_interop/python_interop_test.go index cd968f93..9017ed65 100644 --- a/client/python_interop/python_interop_test.go +++ b/client/python_interop/python_interop_test.go @@ -85,7 +85,8 @@ func (InteropSuite) TestGoClientPythonGenerated(c *C) { } } -func generateRepoFS(c *C, dir string, files map[string][]byte, consistentSnapshot bool) *tuf.Repo { +func generateRepoFS(c *C, dir string, files map[string][]byte, + consistentSnapshot bool) *tuf.Repo { repo, err := tuf.NewRepo(tuf.FileSystemStore(dir, nil)) c.Assert(err, IsNil) if !consistentSnapshot { @@ -107,6 +108,12 @@ func generateRepoFS(c *C, dir string, files map[string][]byte, consistentSnapsho return repo } +func refreshRepo(c *C, repo *tuf.Repo) { + c.Assert(repo.Snapshot(), IsNil) + c.Assert(repo.Timestamp(), IsNil) + c.Assert(repo.Commit(), IsNil) +} + func (InteropSuite) TestPythonClientGoGenerated(c *C) { // clone the Python client if necessary cwd, err := os.Getwd() @@ -161,6 +168,65 @@ func (InteropSuite) TestPythonClientGoGenerated(c *C) { } } +// This is a regression test for issue +// https://github.com/theupdateframework/go-tuf/issues/402 +func (InteropSuite) TestPythonClientGoGeneratedNullDelegations(c *C) { + // clone the Python client if necessary + cwd, err := os.Getwd() + c.Assert(err, IsNil) + + files := map[string][]byte{ + "foo.txt": []byte("foo"), + "bar/baz.txt": []byte("baz"), + } + + for _, consistentSnapshot := range []bool{false, true} { + // generate repository + tmp := c.MkDir() + // start file server + addr, cleanup := startFileServer(c, tmp) + defer cleanup() + name := fmt.Sprintf("consistent-snapshot-delegations-%t", consistentSnapshot) + dir := filepath.Join(tmp, name) + repo := generateRepoFS(c, dir, files, consistentSnapshot) + // "Reset" top-level targets delegations and re-sign + c.Assert(repo.ResetTargetsDelegations("targets"), IsNil) + refreshRepo(c, repo) + + // create initial files for Python client + clientDir := filepath.Join(dir, "client") + currDir := filepath.Join(clientDir, "tufrepo", "metadata", "current") + prevDir := filepath.Join(clientDir, "tufrepo", "metadata", "previous") + c.Assert(os.MkdirAll(currDir, 0755), IsNil) + c.Assert(os.MkdirAll(prevDir, 0755), IsNil) + rootJSON, err := os.ReadFile(filepath.Join(dir, "repository", "1.root.json")) + c.Assert(err, IsNil) + c.Assert(os.WriteFile(filepath.Join(currDir, "root.json"), rootJSON, 0644), IsNil) + + args := []string{ + filepath.Join(cwd, "testdata", "python-tuf-v1.0.0", "client.py"), + "--repo=http://" + addr + "/" + name, + } + for path := range files { + args = append(args, path) + } + + // run Python client update + cmd := exec.Command("python", args...) + cmd.Dir = clientDir + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + c.Assert(cmd.Run(), IsNil) + + // check the target files got downloaded + for path, expected := range files { + actual, err := os.ReadFile(filepath.Join(clientDir, "tuftargets", url.QueryEscape(path))) + c.Assert(err, IsNil) + c.Assert(actual, DeepEquals, expected) + } + } +} + func startFileServer(c *C, dir string) (string, func() error) { l, err := net.Listen("tcp", "127.0.0.1:0") c.Assert(err, IsNil) diff --git a/repo.go b/repo.go index cce0020f..8b38d508 100644 --- a/repo.go +++ b/repo.go @@ -698,8 +698,7 @@ func (r *Repo) ResetTargetsDelegationsWithExpires(delegator string, expires time return fmt.Errorf("error getting delegator (%q) metadata: %w", delegator, err) } - t.Delegations = &data.Delegations{} - t.Delegations.Keys = make(map[string]*data.PublicKey) + t.Delegations = nil t.Expires = expires.Round(time.Second) diff --git a/repo_test.go b/repo_test.go index d841bb59..20d57a10 100644 --- a/repo_test.go +++ b/repo_test.go @@ -2044,6 +2044,14 @@ func (rs *RepoSuite) TestDelegations(c *C) { t, err := r.targets(delegator) c.Assert(err, IsNil) + // Check if there are no delegations. + if t.Delegations == nil { + if delegatedRoles != nil { + c.Fatal("expected delegated roles on delegator") + } + return + } + // Check that delegated roles are copied verbatim. c.Assert(t.Delegations.Roles, DeepEquals, delegatedRoles) From 0f8d7fe3afaf22be46803f8da12b8b27953e2c65 Mon Sep 17 00:00:00 2001 From: Zack Newman Date: Fri, 7 Oct 2022 16:21:35 -0600 Subject: [PATCH 20/46] docs: mention breaking changes in PR template (#413) --- .github/PULL_REQUEST_TEMPLATE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f25ffa80..56186b3f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,13 +1,14 @@ Please fill in the fields below to submit a pull request. The more information that is provided, the better. Fixes # + Release Notes: **Types of changes**: - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected). **Please ensure that your PR title** is a [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/) breaking change (with a `!`, as in `feat!: change foo`). **Description of the changes being introduced by the pull request**: From 6f221460433f1b17829cfdb7d65814e46261edf7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Oct 2022 12:33:10 -0400 Subject: [PATCH 21/46] chore(deps): bump actions/setup-python from 4.2.0 to 4.3.0 (#414) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/b55428b1882923874294fa556849718a1d7f2ca5...13ae5bb136fac2878aff31522b9efb785519f984) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index adf8ec4d..085f2e32 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,7 +30,7 @@ jobs: go-version: ${{ matrix.go-version }} - name: Setup - Python - uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 + uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 with: python-version: "3.10" cache: "pip" From b4c6f5aa03d33c7981eec4ba25bd52163cb3de22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Oct 2022 10:28:40 -0400 Subject: [PATCH 22/46] chore(deps): bump amannn/action-semantic-pull-request from 4.6.0 to 5.0.0 (#415) chore(deps): bump amannn/action-semantic-pull-request Bumps [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) from 4.6.0 to 5.0.0. - [Release notes](https://github.com/amannn/action-semantic-pull-request/releases) - [Changelog](https://github.com/amannn/action-semantic-pull-request/blob/main/CHANGELOG.md) - [Commits](https://github.com/amannn/action-semantic-pull-request/compare/505e44b4f33b4c801f063838b3f053990ee46ea7...5369185dc9812f174fa58b03b13b79920b68f8e1) --- updated-dependencies: - dependency-name: amannn/action-semantic-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index f3f9e439..67fc694b 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -13,6 +13,6 @@ jobs: runs-on: "ubuntu-latest" steps: - name: - uses: amannn/action-semantic-pull-request@505e44b4f33b4c801f063838b3f053990ee46ea7 + uses: amannn/action-semantic-pull-request@5369185dc9812f174fa58b03b13b79920b68f8e1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 3f725e21c467b2f6f0f522069682c03782b436b0 Mon Sep 17 00:00:00 2001 From: asraa Date: Thu, 13 Oct 2022 10:38:26 -0500 Subject: [PATCH 23/46] docs: add security.md (#412) --- docs/SECURITY.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docs/SECURITY.md diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 00000000..8b5859c8 --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,20 @@ +# Security Policy + +The go-tuf community is committed to maintaining a reliable and consistent TUF client implementation. If you believe you have identified a security issue in go-tuf's client protocol, please follow these guidelines for responsible disclosure. + +## Supported Versions + +You may report issues for the most recent version of go-tuf. We will not retroactively make changes to older versions. + +## Reporting a Vulnerability + +If you discover a potential security issue in this project we ask that you notify the go-tuf maintainers via our [vulnerability reporting form](https://forms.gle/ShM4s3mLbUAx5QHo8). At the minimum, the report must contain the following: +* A description of the issue. +* A specific version or commit SHA of `go-tuf` where the issue reproduces. +* Instructions to reproduce the issue. + +Please do **not** create a public GitHub issue or pull request to submit vulnerability reports. These public trackers are intended for non-time-sensitive and non-security-related bug reports and feature requests. Major feature requests, such as design changes to the specification, should be proposed via a [TUF Augmentation Protocol](https://theupdateframework.github.io/specification/latest/#tuf-augmentation-proposal-tap-support) (TAP). + +## Disclosure + +This project follows a 90 day disclosure timeline. From 39613e37d47494ada9c50c3a75136af5cfe90258 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Oct 2022 09:20:14 -0500 Subject: [PATCH 24/46] chore(deps): bump amannn/action-semantic-pull-request from 5.0.0 to 5.0.1 (#416) chore(deps): bump amannn/action-semantic-pull-request Bumps [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) from 5.0.0 to 5.0.1. - [Release notes](https://github.com/amannn/action-semantic-pull-request/releases) - [Changelog](https://github.com/amannn/action-semantic-pull-request/blob/main/CHANGELOG.md) - [Commits](https://github.com/amannn/action-semantic-pull-request/compare/5369185dc9812f174fa58b03b13b79920b68f8e1...570204e54c9030a6cb7ef781c492e76c1798d1c0) --- updated-dependencies: - dependency-name: amannn/action-semantic-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 67fc694b..5ea94f53 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -13,6 +13,6 @@ jobs: runs-on: "ubuntu-latest" steps: - name: - uses: amannn/action-semantic-pull-request@5369185dc9812f174fa58b03b13b79920b68f8e1 + uses: amannn/action-semantic-pull-request@570204e54c9030a6cb7ef781c492e76c1798d1c0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 81884a3062498fae15b4e12f5dd84c73b1788bd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Oct 2022 07:42:37 -0400 Subject: [PATCH 25/46] chore(deps): bump amannn/action-semantic-pull-request from 5.0.1 to 5.0.2 (#419) chore(deps): bump amannn/action-semantic-pull-request Bumps [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) from 5.0.1 to 5.0.2. - [Release notes](https://github.com/amannn/action-semantic-pull-request/releases) - [Changelog](https://github.com/amannn/action-semantic-pull-request/blob/main/CHANGELOG.md) - [Commits](https://github.com/amannn/action-semantic-pull-request/compare/570204e54c9030a6cb7ef781c492e76c1798d1c0...01d5fd8a8ebb9aafe902c40c53f0f4744f7381eb) --- updated-dependencies: - dependency-name: amannn/action-semantic-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 5ea94f53..9c16b8e8 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -13,6 +13,6 @@ jobs: runs-on: "ubuntu-latest" steps: - name: - uses: amannn/action-semantic-pull-request@570204e54c9030a6cb7ef781c492e76c1798d1c0 + uses: amannn/action-semantic-pull-request@01d5fd8a8ebb9aafe902c40c53f0f4744f7381eb env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From fff5e69bbaf9c7360a0b50d2aac6534aa2ec4d64 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 13:11:43 -0400 Subject: [PATCH 26/46] chore(deps): bump actions/setup-go from 3.3.0 to 3.3.1 (#421) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/268d8c0ca0432bb2cf416faae41297df9d262d7f...c4a742cab115ed795e34d4513e2cf7d472deb55f) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 69d74bfa..88db3d99 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: uses: arnested/go-version-action@b556f8d91b644164318c709d28b9083eaf0c064d id: go-version - name: Set up Go - uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f + uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f with: go-version: ${{ steps.go-version.outputs.minimal }} - name: Run GoReleaser diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 085f2e32..d39cab04 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v3 - name: Setup - Go ${{ matrix.go-version }} - uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f + uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f with: go-version: ${{ matrix.go-version }} @@ -59,7 +59,7 @@ jobs: runs-on: ${{ matrix.os }} needs: get-go-versions steps: - - uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f + - uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f with: go-version: ${{ matrix.go-version }} - uses: actions/checkout@v3 From 680a077d4693bc851b41ee48621c4825cbca76e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Oct 2022 11:28:06 -0400 Subject: [PATCH 27/46] chore(deps): bump goreleaser/goreleaser-action from 3.1.0 to 3.2.0 (#420) Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/ff11ca24a9b39f2d36796d1fbd7a4e39c182630a...b508e2e3ef3b19d4e4146d4f8fb3ba9db644a757) --- updated-dependencies: - dependency-name: goreleaser/goreleaser-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 88db3d99..5ea02a2d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: with: go-version: ${{ steps.go-version.outputs.minimal }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@ff11ca24a9b39f2d36796d1fbd7a4e39c182630a + uses: goreleaser/goreleaser-action@b508e2e3ef3b19d4e4146d4f8fb3ba9db644a757 with: distribution: goreleaser version: "v1.7.0" From 7d83cf28176cfb9956ebdb4bb67563383f44d791 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Oct 2022 16:02:19 +0300 Subject: [PATCH 28/46] chore(deps): bump golangci/golangci-lint-action from 3.2.0 to 3.3.0 (#423) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/537aa1903e5d359d0b27dbc19ddd22c5087f3fbc...07db5389c99593f11ad7b44463c2d4233066a9b1) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d39cab04..46fe4221 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -64,7 +64,7 @@ jobs: go-version: ${{ matrix.go-version }} - uses: actions/checkout@v3 - name: golangci-lint - uses: golangci/golangci-lint-action@537aa1903e5d359d0b27dbc19ddd22c5087f3fbc + uses: golangci/golangci-lint-action@07db5389c99593f11ad7b44463c2d4233066a9b1 with: version: v1.49 args: --timeout 5m --verbose From 64bd8051f80416e24c24b80e4d0584709f0178b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 14:41:01 -0400 Subject: [PATCH 29/46] chore(deps): bump github.com/stretchr/testify from 1.8.0 to 1.8.1 (#424) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.0 to 1.8.1. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.0...v1.8.1) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 +--- go.sum | 24 ++++++++---------------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index a5151da0..717b9895 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e github.com/google/gofuzz v1.2.0 github.com/secure-systems-lab/go-securesystemslib v0.4.0 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.1 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 @@ -19,9 +19,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/kr/pretty v0.2.1 // indirect github.com/kr/text v0.1.0 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ff41cd25..05aeffa5 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e h1:Ss/B3/5wWRh8+emnK0++g5zQzwDTi30W10pKxKc4JXI= github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e/go.mod h1:HyVoz1Mz5Co8TFO8EupIdlcpwShBmY98dkT2xeHkvEI= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -43,15 +43,14 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -59,13 +58,13 @@ github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/ github.com/secure-systems-lab/go-securesystemslib v0.4.0/go.mod h1:FGBZgq2tXWICsxWQW1msNf49F0Pf2Op5Htayx335Qbs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -79,12 +78,10 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -97,14 +94,11 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= @@ -113,7 +107,6 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= @@ -124,7 +117,6 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -143,8 +135,8 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 047cdb3be5f66afc9d69a157d6b2c53dc83601b6 Mon Sep 17 00:00:00 2001 From: asraa Date: Mon, 31 Oct 2022 10:40:16 -0500 Subject: [PATCH 30/46] fix: fix verification to continue on invalid sigs (#418) * fix: fix verification to continue on invalid sigs Signed-off-by: Asra Ali --- client/client_test.go | 73 ++++++++++++++++++++++++++++++++++++++++--- go.mod | 2 +- go.sum | 3 +- repo.go | 36 ++++++++++++--------- repo_test.go | 3 +- verify/verify.go | 36 ++++++++++++++------- verify/verify_test.go | 19 ++++++++--- 7 files changed, 135 insertions(+), 37 deletions(-) diff --git a/client/client_test.go b/client/client_test.go index 327b1371..b9fcbd81 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -2,6 +2,7 @@ package client import ( "bytes" + "crypto/ed25519" "crypto/sha256" "encoding/hex" "encoding/json" @@ -351,7 +352,7 @@ func (s *ClientSuite) TestInit(c *C) { _, err = client.Update() c.Assert(err, Equals, ErrNoRootKeys) - // check Init() returns ErrInvalid when the root's signature is + // check Init() returns ErrRoleThreshold when the root's signature is // invalid // modify root and marshal without regenerating signatures root.Version = root.Version + 1 @@ -360,7 +361,8 @@ func (s *ClientSuite) TestInit(c *C) { dataSigned.Signed = rootBytes dataBytes, err := json.Marshal(dataSigned) c.Assert(err, IsNil) - c.Assert(client.Init(dataBytes), Equals, verify.ErrInvalid) + c.Assert(client.Init(dataBytes), Equals, verify.ErrRoleThreshold{ + Expected: 1, Actual: 0}) // check Update() does not return ErrNoRootKeys after initialization c.Assert(client.Init(bytes), IsNil) @@ -368,6 +370,29 @@ func (s *ClientSuite) TestInit(c *C) { c.Assert(err, IsNil) } +// This is a regression test for https://github.com/theupdateframework/go-tuf/issues/370 +// where a single invalid signature resulted in an early return. +// Instead, the client should have continued and counted the number +// of valid signatures, ignoring the incorrect one. +func (s *ClientSuite) TestExtraRootSignaturesOnInit(c *C) { + client := NewClient(MemoryLocalStore(), s.remote) + bytes, err := s.readMeta("root.json") + c.Assert(err, IsNil) + dataSigned := &data.Signed{} + c.Assert(json.Unmarshal(bytes, dataSigned), IsNil) + + // check Init() succeeds when an extra invalid signature was + // added to the root. + dataSigned.Signatures = append(dataSigned.Signatures, + data.Signature{ + KeyID: dataSigned.Signatures[0].KeyID, + Signature: make([]byte, ed25519.SignatureSize), + }) + dataBytes, err := json.Marshal(dataSigned) + c.Assert(err, IsNil) + c.Assert(client.Init(dataBytes), IsNil) +} + func (s *ClientSuite) TestFirstUpdate(c *C) { files, err := s.newClient(c).Update() c.Assert(err, IsNil) @@ -455,6 +480,44 @@ func (s *ClientSuite) TestNewRoot(c *C) { } } +// This is a regression test for https://github.com/theupdateframework/go-tuf/issues/370 +// where a single invalid signature resulted in an early return. +// Instead, the client should have continued and counted the number +// of valid signatures, ignoring the incorrect one. +func (s *ClientSuite) TestExtraSignaturesOnRootUpdate(c *C) { + client := s.newClient(c) + + // Add an extra root key to update the root to a new version. + s.genKey(c, "root") + // update metadata + c.Assert(s.repo.Sign("targets.json"), IsNil) + c.Assert(s.repo.Snapshot(), IsNil) + c.Assert(s.repo.Timestamp(), IsNil) + c.Assert(s.repo.Commit(), IsNil) + s.syncRemote(c) + + // Add an extra signature to the new remote root. + bytes, err := s.readMeta("root.json") + c.Assert(err, IsNil) + dataSigned := &data.Signed{} + c.Assert(json.Unmarshal(bytes, dataSigned), IsNil) + dataSigned.Signatures = append(dataSigned.Signatures, + data.Signature{ + KeyID: dataSigned.Signatures[0].KeyID, + Signature: make([]byte, ed25519.SignatureSize), + }) + dataBytes, err := json.Marshal(dataSigned) + c.Assert(err, IsNil) + s.setRemoteMeta("root.json", dataBytes) + s.setRemoteMeta("2.root.json", dataBytes) + + // check Update() succeeds when an extra invalid signature was + // added to the root. + _, err = client.Update() + c.Assert(err, IsNil) + c.Assert(client.rootVer, Equals, int64(2)) +} + // startTUFRepoServer starts a HTTP server to serve a TUF Repo. func startTUFRepoServer(baseDir string, relPath string) (net.Listener, error) { serverDir := filepath.Join(baseDir, relPath) @@ -517,9 +580,11 @@ func (s *ClientSuite) TestUpdateRoots(c *C) { // Fails updating root from version 1 to version 3 when versions 1 and 3 are expired but version 2 is not expired. {"testdata/Published3Times_keyrotated_latestrootexpired", ErrDecodeFailed{File: "root.json", Err: verify.ErrExpired{}}, map[string]int64{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}}, // Fails updating root from version 1 to version 2 when old root 1 did not sign off on it (nth root didn't sign off n+1). - {"testdata/Published2Times_keyrotated_invalidOldRootSignature", errors.New("tuf: signature verification failed"), map[string]int64{}}, + // TODO(asraa): This testcase should have revoked the old key! + // https://github.com/theupdateframework/go-tuf/issues/417 + {"testdata/Published2Times_keyrotated_invalidOldRootSignature", nil, map[string]int64{}}, // Fails updating root from version 1 to version 2 when the new root 2 did not sign itself (n+1th root didn't sign off n+1) - {"testdata/Published2Times_keyrotated_invalidNewRootSignature", errors.New("tuf: signature verification failed"), map[string]int64{}}, + {"testdata/Published2Times_keyrotated_invalidNewRootSignature", verify.ErrRoleThreshold{Expected: 1, Actual: 0}, map[string]int64{}}, // Fails updating root to 2.root.json when the value of the version field inside it is 1 (rollback attack prevention). {"testdata/Published1Time_backwardRootVersion", verify.ErrWrongVersion(verify.ErrWrongVersion{Given: 1, Expected: 2}), map[string]int64{}}, // Fails updating root to 2.root.json when the value of the version field inside it is 3 (rollforward attack prevention). diff --git a/go.mod b/go.mod index 717b9895..ab6d7ada 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,6 @@ require ( github.com/kr/pretty v0.2.1 // indirect github.com/kr/text v0.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 05aeffa5..4acdef41 100644 --- a/go.sum +++ b/go.sum @@ -101,8 +101,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/repo.go b/repo.go index 8b38d508..c6a23dee 100644 --- a/repo.go +++ b/repo.go @@ -843,7 +843,13 @@ func (r *Repo) AddOrUpdateSignature(roleFilename string, signature data.Signatur return ErrInvalidRole{role, "no trusted keys for role"} } + s, err := r.SignedMeta(roleFilename) + if err != nil { + return err + } + keyInDB := false + validSig := false for _, db := range dbs { roleData := db.GetRole(role) if roleData == nil { @@ -851,15 +857,27 @@ func (r *Repo) AddOrUpdateSignature(roleFilename string, signature data.Signatur } if roleData.ValidKey(signature.KeyID) { keyInDB = true + + verifier, err := db.GetVerifier(signature.KeyID) + if err != nil { + continue + } + + // Now check if this validly signed the metadata. + if err := verify.VerifySignature(s.Signed, signature.Signature, + verifier); err == nil { + validSig = true + break + } } } if !keyInDB { + // This key was not delegated for the role in any delegatee. return verify.ErrInvalidKey } - - s, err := r.SignedMeta(roleFilename) - if err != nil { - return err + if !validSig { + // The signature was invalid. + return verify.ErrInvalid } // Add or update signature. @@ -872,16 +890,6 @@ func (r *Repo) AddOrUpdateSignature(roleFilename string, signature data.Signatur signatures = append(signatures, signature) s.Signatures = signatures - // Check signature on signed meta. Ignore threshold errors as this may not be fully - // signed. - for _, db := range dbs { - if err := db.VerifySignatures(s, role); err != nil { - if _, ok := err.(verify.ErrRoleThreshold); !ok { - return err - } - } - } - b, err := r.jsonMarshal(s) if err != nil { return err diff --git a/repo_test.go b/repo_test.go index 20d57a10..ad69e664 100644 --- a/repo_test.go +++ b/repo_test.go @@ -2663,7 +2663,8 @@ func (rs *RepoSuite) TestSnapshotWithInvalidRoot(c *C) { local.SetMeta("root.json", b) // Snapshotting should fail. - c.Assert(r.Snapshot(), Equals, ErrInsufficientSignatures{"root.json", verify.ErrInvalid}) + c.Assert(r.Snapshot(), Equals, ErrInsufficientSignatures{ + "root.json", verify.ErrRoleThreshold{Expected: 1, Actual: 0}}) // Correctly sign root c.Assert(r.Sign("root.json"), IsNil) diff --git a/verify/verify.go b/verify/verify.go index f5675a25..e62042ee 100644 --- a/verify/verify.go +++ b/verify/verify.go @@ -8,6 +8,7 @@ import ( "github.com/secure-systems-lab/go-securesystemslib/cjson" "github.com/theupdateframework/go-tuf/data" "github.com/theupdateframework/go-tuf/internal/roles" + "github.com/theupdateframework/go-tuf/pkg/keys" ) type signedMeta struct { @@ -16,6 +17,22 @@ type signedMeta struct { Version int64 `json:"version"` } +// VerifySignature takes a signed JSON message, a signature, and a +// verifier and verifies the given signature on the JSON message +// using the verifier. It returns an error if verification fails. +func VerifySignature(signed json.RawMessage, sig data.HexBytes, + verifier keys.Verifier) error { + var decoded map[string]interface{} + if err := json.Unmarshal(signed, &decoded); err != nil { + return err + } + msg, err := cjson.EncodeCanonical(decoded) + if err != nil { + return err + } + return verifier.Verify(msg, sig) +} + func (db *DB) VerifyIgnoreExpiredCheck(s *data.Signed, role string, minVersion int64) error { if err := db.VerifySignatures(s, role); err != nil { return err @@ -80,15 +97,6 @@ func (db *DB) VerifySignatures(s *data.Signed, role string) error { return ErrUnknownRole{role} } - var decoded map[string]interface{} - if err := json.Unmarshal(s.Signed, &decoded); err != nil { - return err - } - msg, err := cjson.EncodeCanonical(decoded) - if err != nil { - return err - } - // Verify that a threshold of keys signed the data. Since keys can have // multiple key ids, we need to protect against multiple attached // signatures that just differ on the key id. @@ -103,9 +111,13 @@ func (db *DB) VerifySignatures(s *data.Signed, role string) error { continue } - if err := verifier.Verify(msg, sig.Signature); err != nil { - // FIXME: don't err out on the 1st bad signature. - return ErrInvalid + if err := VerifySignature(s.Signed, sig.Signature, verifier); err != nil { + // If a signature fails verification, don't count it towards the + // threshold but also return early and error out immediately. + // Note: Because of this, it is impossible to distinguish between + // an error of an invalid signature and a threshold not achieved. + // Invalid signatures lead to not achieving the threshold. + continue } // Only consider this key valid if we haven't seen any of it's diff --git a/verify/verify_test.go b/verify/verify_test.go index afbf79d8..191c1ed0 100644 --- a/verify/verify_test.go +++ b/verify/verify_test.go @@ -89,9 +89,12 @@ func (VerifySuite) Test(c *C) { err: ErrUnknownRole{"foo"}, }, { + // It is impossible to distinguish between an error of an invalid + // signature and a threshold not achieved. Invalid signatures lead + // to not achieving the threshold. name: "signature wrong length", mut: func(t *test) { t.s.Signatures[0].Signature = []byte{0} }, - err: ErrInvalid, + err: ErrRoleThreshold{1, 0}, }, { name: "key missing from role", @@ -101,7 +104,15 @@ func (VerifySuite) Test(c *C) { { name: "invalid signature", mut: func(t *test) { t.s.Signatures[0].Signature = make([]byte, ed25519.SignatureSize) }, - err: ErrInvalid, + err: ErrRoleThreshold{1, 0}, + }, + { + name: "enough signatures with extra invalid signature", + mut: func(t *test) { + t.s.Signatures = append(t.s.Signatures, data.Signature{ + KeyID: t.s.Signatures[0].KeyID, + Signature: make([]byte, ed25519.SignatureSize)}) + }, }, { name: "not enough signatures", @@ -189,7 +200,8 @@ func (VerifySuite) Test(c *C) { }, }, { - name: "invalid ecdsa signature", + // The threshold is still achieved. + name: "invalid second ecdsa signature", mut: func(t *test) { k, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) s := ecdsaSigner{k} @@ -198,7 +210,6 @@ func (VerifySuite) Test(c *C) { t.keys = append(t.keys, s.PublicData()) t.roles["root"].KeyIDs = append(t.roles["root"].KeyIDs, s.PublicData().IDs()...) }, - err: ErrInvalid, }, } for _, t := range tests { From cfd009dc71976e58d4d44a9cfd05c5d8ec2f38af Mon Sep 17 00:00:00 2001 From: Ethan Lowman <53835328+ethan-lowman-dd@users.noreply.github.com> Date: Thu, 3 Nov 2022 12:41:30 -0400 Subject: [PATCH 31/46] docs: Remove ethan-lowman-dd from maintainers (#428) Signed-off-by: Ethan Lowman Signed-off-by: Ethan Lowman --- docs/MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/MAINTAINERS b/docs/MAINTAINERS index d6b39ded..7a3768d6 100644 --- a/docs/MAINTAINERS +++ b/docs/MAINTAINERS @@ -1,7 +1,6 @@ Asra Ali (github: asraa) Trishank Karthik Kuppusamy (github: trishankatdatadog) Joshua Lock (github: joshuagl) -Ethan Lowman (github: ethan-lowman-dd) Marina Moore (github: mnm678) Zack Newman (github: znewman01) Hossein Siadati (github: hosseinsia) From 2ac63f72c7df4f90c9b2ebff73cfaa84b21d1f1b Mon Sep 17 00:00:00 2001 From: Trishank Karthik Kuppusamy Date: Fri, 4 Nov 2022 04:26:13 -0400 Subject: [PATCH 32/46] docs: Update MAINTAINERS (#430) Update MAINTAINERS Remove @hosseinsia from list of maintainers. Thanks for your service! Signed-off-by: Trishank Karthik Kuppusamy Signed-off-by: Trishank Karthik Kuppusamy --- docs/MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/MAINTAINERS b/docs/MAINTAINERS index 7a3768d6..70935e60 100644 --- a/docs/MAINTAINERS +++ b/docs/MAINTAINERS @@ -3,5 +3,4 @@ Trishank Karthik Kuppusamy (github: trishanka Joshua Lock (github: joshuagl) Marina Moore (github: mnm678) Zack Newman (github: znewman01) -Hossein Siadati (github: hosseinsia) Radoslav Dimitrov (github: rdimitrov) From 901213da55cde30e096c093d4cae2609bbebbdc1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 10:21:33 -0600 Subject: [PATCH 33/46] chore(deps): bump golangci/golangci-lint-action from 3.3.0 to 3.3.1 (#433) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/07db5389c99593f11ad7b44463c2d4233066a9b1...0ad9a0988b3973e851ab0a07adf248ec2e100376) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 46fe4221..a4b510f8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -64,7 +64,7 @@ jobs: go-version: ${{ matrix.go-version }} - uses: actions/checkout@v3 - name: golangci-lint - uses: golangci/golangci-lint-action@07db5389c99593f11ad7b44463c2d4233066a9b1 + uses: golangci/golangci-lint-action@0ad9a0988b3973e851ab0a07adf248ec2e100376 with: version: v1.49 args: --timeout 5m --verbose From 535756abf04956a76b2f1f3eb1989b7447b5c6a6 Mon Sep 17 00:00:00 2001 From: Joshua Lock Date: Tue, 15 Nov 2022 15:28:00 +0000 Subject: [PATCH 34/46] chore: Update interop tests for new python-tuf release 2.0.0 (#434) Update interop tests for new python-tuf release 2.0.0 Simply re-ran the generation scripts with the newest python-tuf release, renamed the directory to reflect the updated version and updated any references to the directory. Fixes #367 Signed-off-by: Joshua Lock --- client/python_interop/python_interop_test.go | 6 +- client/python_interop/testdata/Makefile | 2 +- .../repository/metadata/1.root.json | 71 ------------------- .../repository/metadata/1.snapshot.json | 19 ----- .../repository/metadata/timestamp.json | 23 ------ .../repository/metadata/1.root.json | 71 ------------------- .../repository/metadata/snapshot.json | 19 ----- .../repository/metadata/timestamp.json | 23 ------ .../Dockerfile | 2 +- .../client.py | 0 .../generate.py | 0 .../generate.sh | 0 .../repository/metadata/1.root.json | 71 +++++++++++++++++++ .../repository/metadata/1.snapshot.json | 19 +++++ .../repository/metadata/1.targets.json | 4 +- .../repository/metadata/timestamp.json | 19 +++++ ...ce9c420da5db6203afab700b27e10cf9.file1.txt | 0 ...7d7615dc3e9515c782c49d2075658701.file2.txt | 0 .../repository/metadata/1.root.json | 71 +++++++++++++++++++ .../repository/metadata/snapshot.json | 19 +++++ .../repository/metadata/targets.json | 4 +- .../repository/metadata/timestamp.json | 19 +++++ .../repository/targets/dir/file2.txt | 0 .../repository/targets/file1.txt | 0 requirements-test.txt | 4 +- 25 files changed, 229 insertions(+), 237 deletions(-) delete mode 100644 client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.root.json delete mode 100644 client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.snapshot.json delete mode 100644 client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/timestamp.json delete mode 100644 client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/1.root.json delete mode 100644 client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/snapshot.json delete mode 100644 client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/timestamp.json rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/Dockerfile (57%) rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/client.py (100%) rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/generate.py (100%) rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/generate.sh (100%) create mode 100755 client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.root.json create mode 100755 client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.snapshot.json rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/with-consistent-snapshot/repository/metadata/1.targets.json (67%) mode change 100644 => 100755 create mode 100755 client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/timestamp.json rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/with-consistent-snapshot/repository/targets/55ae75d991c770d8f3ef07cbfde124ffce9c420da5db6203afab700b27e10cf9.file1.txt (100%) rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/with-consistent-snapshot/repository/targets/dir/04e2f59431a9d219321baf7d21b8cc797d7615dc3e9515c782c49d2075658701.file2.txt (100%) create mode 100755 client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/1.root.json create mode 100755 client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/snapshot.json rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/without-consistent-snapshot/repository/metadata/targets.json (67%) mode change 100644 => 100755 create mode 100755 client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/timestamp.json rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/without-consistent-snapshot/repository/targets/dir/file2.txt (100%) rename client/python_interop/testdata/{python-tuf-v1.0.0 => python-tuf-v2.0.0}/without-consistent-snapshot/repository/targets/file1.txt (100%) diff --git a/client/python_interop/python_interop_test.go b/client/python_interop/python_interop_test.go index 9017ed65..b906e230 100644 --- a/client/python_interop/python_interop_test.go +++ b/client/python_interop/python_interop_test.go @@ -43,7 +43,7 @@ func (InteropSuite) TestGoClientPythonGenerated(c *C) { // start file server cwd, err := os.Getwd() c.Assert(err, IsNil) - testDataDir := filepath.Join(cwd, "testdata", "python-tuf-v1.0.0") + testDataDir := filepath.Join(cwd, "testdata", "python-tuf-v2.0.0") addr, cleanup := startFileServer(c, testDataDir) defer cleanup() @@ -145,7 +145,7 @@ func (InteropSuite) TestPythonClientGoGenerated(c *C) { c.Assert(os.WriteFile(filepath.Join(currDir, "root.json"), rootJSON, 0644), IsNil) args := []string{ - filepath.Join(cwd, "testdata", "python-tuf-v1.0.0", "client.py"), + filepath.Join(cwd, "testdata", "python-tuf-v2.0.0", "client.py"), "--repo=http://" + addr + "/" + name, } for path := range files { @@ -204,7 +204,7 @@ func (InteropSuite) TestPythonClientGoGeneratedNullDelegations(c *C) { c.Assert(os.WriteFile(filepath.Join(currDir, "root.json"), rootJSON, 0644), IsNil) args := []string{ - filepath.Join(cwd, "testdata", "python-tuf-v1.0.0", "client.py"), + filepath.Join(cwd, "testdata", "python-tuf-v2.0.0", "client.py"), "--repo=http://" + addr + "/" + name, } for path := range files { diff --git a/client/python_interop/testdata/Makefile b/client/python_interop/testdata/Makefile index f5ef1630..3b84759a 100644 --- a/client/python_interop/testdata/Makefile +++ b/client/python_interop/testdata/Makefile @@ -1,4 +1,4 @@ -PYTHON_TUF=python-tuf-v1.0.0 +PYTHON_TUF=python-tuf-v2.0.0 all: docker build -t tuf-gen ./$(PYTHON_TUF) diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.root.json b/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.root.json deleted file mode 100644 index 13ccb178..00000000 --- a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.root.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "signatures": [ - { - "keyid": "e26489b1801b03e9e770b18f34c337cc29c1b02c4a4385ac698dfe879753e6b3", - "sig": "6385f433122fbe8760030371c0e6768cecff0df2fb22fdf04618da9f09b230070e3ef23f4d13978993466f2f1f983e4d712443c23bde08a5be77df6e6832be0e" - } - ], - "signed": { - "_type": "root", - "consistent_snapshot": true, - "expires": "2030-01-01T00:00:00Z", - "keys": { - "7b1aa7dbc1b24fb44d0146b0fe726d92f9640e26dc197d50345f9b00e0c98c4a": { - "keytype": "ed25519", - "keyval": { - "public": "98b7918168c7adfe0cdc26bd332baf67335ac4e8be350ddc3d27e54b93ae8b41" - }, - "scheme": "ed25519" - }, - "7fe79f52b6ab730028c299b82e4c45c828b3a47fea06f9e4582597a62c4e2f9a": { - "keytype": "ed25519", - "keyval": { - "public": "baa12f5d0f6d053c27625240b021286c9d8939ae62ec6143ee9ef1ada31fc0d9" - }, - "scheme": "ed25519" - }, - "d72e12473433414326514f50289712cb2a4fd8b518b70fcea077018d50a702f2": { - "keytype": "ed25519", - "keyval": { - "public": "ab5ae139b430f0210e4b3ae024882e9bf8c7d31e6ae958061da8ab51ce162c3c" - }, - "scheme": "ed25519" - }, - "e26489b1801b03e9e770b18f34c337cc29c1b02c4a4385ac698dfe879753e6b3": { - "keytype": "ed25519", - "keyval": { - "public": "aef72f53b1aeed769cc5678dbdc8a104d562c87e8201278156f84bab2c0c0a30" - }, - "scheme": "ed25519" - } - }, - "roles": { - "root": { - "keyids": [ - "e26489b1801b03e9e770b18f34c337cc29c1b02c4a4385ac698dfe879753e6b3" - ], - "threshold": 1 - }, - "snapshot": { - "keyids": [ - "d72e12473433414326514f50289712cb2a4fd8b518b70fcea077018d50a702f2" - ], - "threshold": 1 - }, - "targets": { - "keyids": [ - "7b1aa7dbc1b24fb44d0146b0fe726d92f9640e26dc197d50345f9b00e0c98c4a" - ], - "threshold": 1 - }, - "timestamp": { - "keyids": [ - "7fe79f52b6ab730028c299b82e4c45c828b3a47fea06f9e4582597a62c4e2f9a" - ], - "threshold": 1 - } - }, - "spec_version": "1.0.19", - "version": 1 - } -} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.snapshot.json b/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.snapshot.json deleted file mode 100644 index 4a792fe1..00000000 --- a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.snapshot.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "signatures": [ - { - "keyid": "d72e12473433414326514f50289712cb2a4fd8b518b70fcea077018d50a702f2", - "sig": "da8a6d4ec27acf62c23d16b51430456d12a20b3373ae52ecf3461ae52f7643dafcc51ca76f5080e9441c055e6a888323fb41e40427df4fc16fea5f35b358db04" - } - ], - "signed": { - "_type": "snapshot", - "expires": "2030-01-01T00:00:00Z", - "meta": { - "targets.json": { - "version": 1 - } - }, - "spec_version": "1.0.19", - "version": 1 - } -} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/timestamp.json b/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/timestamp.json deleted file mode 100644 index c86ca151..00000000 --- a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/timestamp.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "signatures": [ - { - "keyid": "7fe79f52b6ab730028c299b82e4c45c828b3a47fea06f9e4582597a62c4e2f9a", - "sig": "a10f63e6ce554a259ed8e49afbfc6dc358fad05a377ed9f237ba0d81a058fb995be6ab2a4d67166532203fc68239bd8eaf1ebbbe9730c88773b27479d7395a0a" - } - ], - "signed": { - "_type": "timestamp", - "expires": "2030-01-01T00:00:00Z", - "meta": { - "snapshot.json": { - "hashes": { - "sha256": "e92738a47826131048e88e6850dab1667c2e4934514c294a478670e5ec230514" - }, - "length": 432, - "version": 1 - } - }, - "spec_version": "1.0.19", - "version": 1 - } -} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/1.root.json b/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/1.root.json deleted file mode 100644 index a278bf24..00000000 --- a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/1.root.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "signatures": [ - { - "keyid": "cbc434dd8f82c00935912ae123555c8f1d8e202ee74ed3511474a511fbd2bc3b", - "sig": "fb9652e344f028d864391f3bd897cc9e2e8c7a2bd7498cdf11816e517f7eedcf5b79a39757d4891e20d8c4917f6b1ef2d6fe729feb54bda771432f8664a48500" - } - ], - "signed": { - "_type": "root", - "consistent_snapshot": false, - "expires": "2030-01-01T00:00:00Z", - "keys": { - "6694e8c2a2d3cf98ebe41d2442235c46c7caaa4bd8908036d45ac5b046b08dde": { - "keytype": "ed25519", - "keyval": { - "public": "ce1de9af6e9f0599ade37d947e4fd19bc4d89da7ab3f335055196b42f6fa1704" - }, - "scheme": "ed25519" - }, - "ae6fcd48721c779d066643ed9d895feb48a86039732e93b58895d99bbbd0c0ae": { - "keytype": "ed25519", - "keyval": { - "public": "bb7e06355dee36ba33aa70780f82477724a78d69b9d7de3ebd647ff0d648516f" - }, - "scheme": "ed25519" - }, - "cbc434dd8f82c00935912ae123555c8f1d8e202ee74ed3511474a511fbd2bc3b": { - "keytype": "ed25519", - "keyval": { - "public": "e88e416ada03c8ef6b825aa43ff2c608683c51efa752234a454f9b1f9c5a2a39" - }, - "scheme": "ed25519" - }, - "e03d20021373f9de91fccedeb6572438b6803f2d3ab37adf51b72dc4aa527655": { - "keytype": "ed25519", - "keyval": { - "public": "95c4cabf0783bf904943179f5db97b8210d745b0dd4bfa4659f0c172b80d6e08" - }, - "scheme": "ed25519" - } - }, - "roles": { - "root": { - "keyids": [ - "cbc434dd8f82c00935912ae123555c8f1d8e202ee74ed3511474a511fbd2bc3b" - ], - "threshold": 1 - }, - "snapshot": { - "keyids": [ - "6694e8c2a2d3cf98ebe41d2442235c46c7caaa4bd8908036d45ac5b046b08dde" - ], - "threshold": 1 - }, - "targets": { - "keyids": [ - "ae6fcd48721c779d066643ed9d895feb48a86039732e93b58895d99bbbd0c0ae" - ], - "threshold": 1 - }, - "timestamp": { - "keyids": [ - "e03d20021373f9de91fccedeb6572438b6803f2d3ab37adf51b72dc4aa527655" - ], - "threshold": 1 - } - }, - "spec_version": "1.0.19", - "version": 1 - } -} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/snapshot.json b/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/snapshot.json deleted file mode 100644 index 30668fb5..00000000 --- a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/snapshot.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "signatures": [ - { - "keyid": "6694e8c2a2d3cf98ebe41d2442235c46c7caaa4bd8908036d45ac5b046b08dde", - "sig": "6c06bd2dc1f9b9991ff68fa3edb9b3b6becee25f638b4187e161ac65cadcbb59d320196bb0fb72cf08734b75531f3ceddefdc56424ec8a8c8fee068b2584450d" - } - ], - "signed": { - "_type": "snapshot", - "expires": "2030-01-01T00:00:00Z", - "meta": { - "targets.json": { - "version": 1 - } - }, - "spec_version": "1.0.19", - "version": 1 - } -} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/timestamp.json b/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/timestamp.json deleted file mode 100644 index 5a9d3c31..00000000 --- a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/timestamp.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "signatures": [ - { - "keyid": "e03d20021373f9de91fccedeb6572438b6803f2d3ab37adf51b72dc4aa527655", - "sig": "50315d16c729d2068586776285f6282c87cd722e052acf293166ca1cf7313bdc1a673d02309f9be2d710d82c239ce349f3bffbcb76fbebb655bea2199db92503" - } - ], - "signed": { - "_type": "timestamp", - "expires": "2030-01-01T00:00:00Z", - "meta": { - "snapshot.json": { - "hashes": { - "sha256": "4471c47119f7b16307f9955e7fa0fdcaf53c82f7a857ea2b2f46fd6fe9bc53e9" - }, - "length": 432, - "version": 1 - } - }, - "spec_version": "1.0.19", - "version": 1 - } -} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/Dockerfile b/client/python_interop/testdata/python-tuf-v2.0.0/Dockerfile similarity index 57% rename from client/python_interop/testdata/python-tuf-v1.0.0/Dockerfile rename to client/python_interop/testdata/python-tuf-v2.0.0/Dockerfile index 3987fe06..10b4f445 100644 --- a/client/python_interop/testdata/python-tuf-v1.0.0/Dockerfile +++ b/client/python_interop/testdata/python-tuf-v2.0.0/Dockerfile @@ -1,7 +1,7 @@ FROM python:3.10 RUN apt-get update && apt-get install -y libsodium-dev tree -RUN pip install 'securesystemslib[crypto,pynacl]==0.22.0' 'tuf==v1.0.0' +RUN pip install -U pip && pip install 'securesystemslib[crypto,pynacl]==0.25.0' 'tuf==v2.0.0' ADD generate.py generate.sh / CMD /generate.sh diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/client.py b/client/python_interop/testdata/python-tuf-v2.0.0/client.py similarity index 100% rename from client/python_interop/testdata/python-tuf-v1.0.0/client.py rename to client/python_interop/testdata/python-tuf-v2.0.0/client.py diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/generate.py b/client/python_interop/testdata/python-tuf-v2.0.0/generate.py similarity index 100% rename from client/python_interop/testdata/python-tuf-v1.0.0/generate.py rename to client/python_interop/testdata/python-tuf-v2.0.0/generate.py diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/generate.sh b/client/python_interop/testdata/python-tuf-v2.0.0/generate.sh similarity index 100% rename from client/python_interop/testdata/python-tuf-v1.0.0/generate.sh rename to client/python_interop/testdata/python-tuf-v2.0.0/generate.sh diff --git a/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.root.json b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.root.json new file mode 100755 index 00000000..1d7d8394 --- /dev/null +++ b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.root.json @@ -0,0 +1,71 @@ +{ + "signatures": [ + { + "keyid": "7e576308aa26b10a124e13fd6bc4d63977d1904db6823c2862636d2b330fd669", + "sig": "c50fb9e20819b06d8dbebc748a269f1b9e089a2d8a81f64f7e889c054e619ec22c98e4ae24cb868b7c7757f62853cb0cd5dd658dad5ba94286a34255f5f7a100" + } + ], + "signed": { + "_type": "root", + "consistent_snapshot": true, + "expires": "2030-01-01T00:00:00Z", + "keys": { + "7e576308aa26b10a124e13fd6bc4d63977d1904db6823c2862636d2b330fd669": { + "keytype": "ed25519", + "keyval": { + "public": "018908d2190610e54be1f6af0c77a7f59efc5b42971575a06e66018ae36bf15c" + }, + "scheme": "ed25519" + }, + "e76b314161b74584dbda0b3e46eaf1b9feea6f85abc0d9c8432e7fe3752d4f0f": { + "keytype": "ed25519", + "keyval": { + "public": "ecfe22e7fb9c2d867bad321ce90f297d5747efce8d96af171b5d5801b13a1c72" + }, + "scheme": "ed25519" + }, + "fa5b604a0ee5980e5f8a2398729e03c539fa68123cd3eb2e99f70d3504a71704": { + "keytype": "ed25519", + "keyval": { + "public": "128d5aba7c967e6e87c4e06b852282c91dd90c9ac9dec3adc9e6a237d4530752" + }, + "scheme": "ed25519" + }, + "faf425a6c41e594be56b35ab08c0dfe486ab6e14a25308bbfa990e050cdf0aef": { + "keytype": "ed25519", + "keyval": { + "public": "2a70c65b98f325026225b568af3587e993a0a5ab96671469e4ecfbb386412063" + }, + "scheme": "ed25519" + } + }, + "roles": { + "root": { + "keyids": [ + "7e576308aa26b10a124e13fd6bc4d63977d1904db6823c2862636d2b330fd669" + ], + "threshold": 1 + }, + "snapshot": { + "keyids": [ + "fa5b604a0ee5980e5f8a2398729e03c539fa68123cd3eb2e99f70d3504a71704" + ], + "threshold": 1 + }, + "targets": { + "keyids": [ + "faf425a6c41e594be56b35ab08c0dfe486ab6e14a25308bbfa990e050cdf0aef" + ], + "threshold": 1 + }, + "timestamp": { + "keyids": [ + "e76b314161b74584dbda0b3e46eaf1b9feea6f85abc0d9c8432e7fe3752d4f0f" + ], + "threshold": 1 + } + }, + "spec_version": "1.0.19", + "version": 1 + } +} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.snapshot.json b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.snapshot.json new file mode 100755 index 00000000..fbf2d1cb --- /dev/null +++ b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.snapshot.json @@ -0,0 +1,19 @@ +{ + "signatures": [ + { + "keyid": "fa5b604a0ee5980e5f8a2398729e03c539fa68123cd3eb2e99f70d3504a71704", + "sig": "1c09c1ca4c38e68f4ba9ac48c6ed6fcee13e5a071dcfeb51e7b5cf1a823bcc16b26528f67efaa59383a4a765cdd5fd81d67f74a5c09789673cab164a7251b20d" + } + ], + "signed": { + "_type": "snapshot", + "expires": "2030-01-01T00:00:00Z", + "meta": { + "targets.json": { + "version": 1 + } + }, + "spec_version": "1.0.19", + "version": 1 + } +} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.targets.json b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.targets.json old mode 100644 new mode 100755 similarity index 67% rename from client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.targets.json rename to client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.targets.json index 402978bb..5acb7c64 --- a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/metadata/1.targets.json +++ b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/1.targets.json @@ -1,8 +1,8 @@ { "signatures": [ { - "keyid": "7b1aa7dbc1b24fb44d0146b0fe726d92f9640e26dc197d50345f9b00e0c98c4a", - "sig": "012a5a56af043b44fb913d859b61f85800c72fd93b5b3a04ac20f988c29114c643e933f427ff4d38b29b5b2340fe76cfa05704e075d799431fbafe80f9733500" + "keyid": "faf425a6c41e594be56b35ab08c0dfe486ab6e14a25308bbfa990e050cdf0aef", + "sig": "42e49b11e043fa847b0f82786d5fb44988ab0281bda02553e54eb95d7fdbeea25b95c81b824c900cf6132d4714d3ad4d88786155d915603859d27c7934d5650f" } ], "signed": { diff --git a/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/timestamp.json b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/timestamp.json new file mode 100755 index 00000000..23ab4e54 --- /dev/null +++ b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/metadata/timestamp.json @@ -0,0 +1,19 @@ +{ + "signatures": [ + { + "keyid": "e76b314161b74584dbda0b3e46eaf1b9feea6f85abc0d9c8432e7fe3752d4f0f", + "sig": "9c734040db3786f9b8f44db282f53f054fca99654ea393601430adb0d1204c44ab534568b4412b52a8578f35306720903117758abb4534dc8c15ad5a9ebe7e09" + } + ], + "signed": { + "_type": "timestamp", + "expires": "2030-01-01T00:00:00Z", + "meta": { + "snapshot.json": { + "version": 1 + } + }, + "spec_version": "1.0.19", + "version": 1 + } +} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/targets/55ae75d991c770d8f3ef07cbfde124ffce9c420da5db6203afab700b27e10cf9.file1.txt b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/targets/55ae75d991c770d8f3ef07cbfde124ffce9c420da5db6203afab700b27e10cf9.file1.txt similarity index 100% rename from client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/targets/55ae75d991c770d8f3ef07cbfde124ffce9c420da5db6203afab700b27e10cf9.file1.txt rename to client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/targets/55ae75d991c770d8f3ef07cbfde124ffce9c420da5db6203afab700b27e10cf9.file1.txt diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/targets/dir/04e2f59431a9d219321baf7d21b8cc797d7615dc3e9515c782c49d2075658701.file2.txt b/client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/targets/dir/04e2f59431a9d219321baf7d21b8cc797d7615dc3e9515c782c49d2075658701.file2.txt similarity index 100% rename from client/python_interop/testdata/python-tuf-v1.0.0/with-consistent-snapshot/repository/targets/dir/04e2f59431a9d219321baf7d21b8cc797d7615dc3e9515c782c49d2075658701.file2.txt rename to client/python_interop/testdata/python-tuf-v2.0.0/with-consistent-snapshot/repository/targets/dir/04e2f59431a9d219321baf7d21b8cc797d7615dc3e9515c782c49d2075658701.file2.txt diff --git a/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/1.root.json b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/1.root.json new file mode 100755 index 00000000..cf2d4494 --- /dev/null +++ b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/1.root.json @@ -0,0 +1,71 @@ +{ + "signatures": [ + { + "keyid": "3838ee205d1906276ddb1df0803192f95753104e4dd828b70f17e3b3aa90de75", + "sig": "fb2b85aea59950fb7ca3012fd93d252ba7c1cec30c2afae0f1b4fb0146158e0800ad0e99221123b396e0a1a487b5cafdfe50d94a893e7dd5ede2891341a31f00" + } + ], + "signed": { + "_type": "root", + "consistent_snapshot": false, + "expires": "2030-01-01T00:00:00Z", + "keys": { + "3838ee205d1906276ddb1df0803192f95753104e4dd828b70f17e3b3aa90de75": { + "keytype": "ed25519", + "keyval": { + "public": "4203975790ecf4aba558cb7ab3f9430c51b4c3553117d09949f3123fb49d4961" + }, + "scheme": "ed25519" + }, + "4908b7ba44138d79f05f3d211cb5f4bf9e73a71a7bc4ecd1b263accff7632445": { + "keytype": "ed25519", + "keyval": { + "public": "9dc9bf2210f5b743e3b094eae198c1bb2633966d6c10ac2a6d54b782623b8b89" + }, + "scheme": "ed25519" + }, + "8c0291ae0d3c260405e6683cd2260ee6fbb5676deb57541acbe5b94ca4089a50": { + "keytype": "ed25519", + "keyval": { + "public": "ca9a2dfe087762bea03a556ddc01c9ed113f5651ca1546804dae39441099fca3" + }, + "scheme": "ed25519" + }, + "c0ef91ecbb8a59bffc5642ba01129d64059b076b946d120733ea949e2c7786a2": { + "keytype": "ed25519", + "keyval": { + "public": "fcd7c34b20c3b8093b6b21b6a505f715e3d0645c1d9e05ee14d29f045e0b41d8" + }, + "scheme": "ed25519" + } + }, + "roles": { + "root": { + "keyids": [ + "3838ee205d1906276ddb1df0803192f95753104e4dd828b70f17e3b3aa90de75" + ], + "threshold": 1 + }, + "snapshot": { + "keyids": [ + "c0ef91ecbb8a59bffc5642ba01129d64059b076b946d120733ea949e2c7786a2" + ], + "threshold": 1 + }, + "targets": { + "keyids": [ + "4908b7ba44138d79f05f3d211cb5f4bf9e73a71a7bc4ecd1b263accff7632445" + ], + "threshold": 1 + }, + "timestamp": { + "keyids": [ + "8c0291ae0d3c260405e6683cd2260ee6fbb5676deb57541acbe5b94ca4089a50" + ], + "threshold": 1 + } + }, + "spec_version": "1.0.19", + "version": 1 + } +} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/snapshot.json b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/snapshot.json new file mode 100755 index 00000000..333bc5dd --- /dev/null +++ b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/snapshot.json @@ -0,0 +1,19 @@ +{ + "signatures": [ + { + "keyid": "c0ef91ecbb8a59bffc5642ba01129d64059b076b946d120733ea949e2c7786a2", + "sig": "44b9651d75522ac5bdb13e23706f37ade578c59355525ac473d14de4f3cb5c5ace9c2d32b552754305f665e4e91c6773c6876e704939200bb71ab0e03a59ce03" + } + ], + "signed": { + "_type": "snapshot", + "expires": "2030-01-01T00:00:00Z", + "meta": { + "targets.json": { + "version": 1 + } + }, + "spec_version": "1.0.19", + "version": 1 + } +} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/targets.json b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/targets.json old mode 100644 new mode 100755 similarity index 67% rename from client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/targets.json rename to client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/targets.json index ed805ca8..e224e70b --- a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/metadata/targets.json +++ b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/targets.json @@ -1,8 +1,8 @@ { "signatures": [ { - "keyid": "ae6fcd48721c779d066643ed9d895feb48a86039732e93b58895d99bbbd0c0ae", - "sig": "50eec0672e2861e3b73a8a4a15cc60113dc5b478d1431a55d90f8ab65a1954acbbc860f586f3a331144e41a56c54e54c49d9d9eba6ace2c553ec542aafcf4c04" + "keyid": "4908b7ba44138d79f05f3d211cb5f4bf9e73a71a7bc4ecd1b263accff7632445", + "sig": "faf60abd2a725d5962c8a708d9d298d25accbe379b01dc9a5516161b702287b57d425d927942c1a5ddf462be1f8c12718575de5c29994bbff7d83c6218fbc00b" } ], "signed": { diff --git a/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/timestamp.json b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/timestamp.json new file mode 100755 index 00000000..915f07af --- /dev/null +++ b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/metadata/timestamp.json @@ -0,0 +1,19 @@ +{ + "signatures": [ + { + "keyid": "8c0291ae0d3c260405e6683cd2260ee6fbb5676deb57541acbe5b94ca4089a50", + "sig": "933aba2b1f567c8fc6c8b08850330449be6c83a30a75f4d978600b5470f69416bbd0f6cb6cf2c088a0bc2d948290123a2e6419908c58b1b32772aa8f2f94490e" + } + ], + "signed": { + "_type": "timestamp", + "expires": "2030-01-01T00:00:00Z", + "meta": { + "snapshot.json": { + "version": 1 + } + }, + "spec_version": "1.0.19", + "version": 1 + } +} \ No newline at end of file diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/targets/dir/file2.txt b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/targets/dir/file2.txt similarity index 100% rename from client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/targets/dir/file2.txt rename to client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/targets/dir/file2.txt diff --git a/client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/targets/file1.txt b/client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/targets/file1.txt similarity index 100% rename from client/python_interop/testdata/python-tuf-v1.0.0/without-consistent-snapshot/repository/targets/file1.txt rename to client/python_interop/testdata/python-tuf-v2.0.0/without-consistent-snapshot/repository/targets/file1.txt diff --git a/requirements-test.txt b/requirements-test.txt index 05fae07d..59333532 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,5 +1,5 @@ iso8601==1.1.0 requests==2.28.1 -securesystemslib==0.24.0 +securesystemslib==0.25.0 six==1.16.0 -tuf==1.0.0 \ No newline at end of file +tuf==2.0.0 From 00e8129a6d462d7d06f1374dbfabe76f6c163231 Mon Sep 17 00:00:00 2001 From: Marina Moore Date: Wed, 16 Nov 2022 09:37:15 -0500 Subject: [PATCH 35/46] docs: Use Github's vulnerability reporting (#432) * use Github's vulnerability reporting Signed-off-by: Marina Moore * Update docs/SECURITY.md Co-authored-by: Joshua Lock Signed-off-by: Marina Moore Signed-off-by: Marina Moore Signed-off-by: Marina Moore Co-authored-by: Joshua Lock --- docs/SECURITY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/SECURITY.md b/docs/SECURITY.md index 8b5859c8..eb26fed7 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -8,7 +8,8 @@ You may report issues for the most recent version of go-tuf. We will not retroac ## Reporting a Vulnerability -If you discover a potential security issue in this project we ask that you notify the go-tuf maintainers via our [vulnerability reporting form](https://forms.gle/ShM4s3mLbUAx5QHo8). At the minimum, the report must contain the following: +If you discover a potential security issue in this project we ask that you notify the go-tuf maintainers via [Github's private reporting feature](https://github.com/theupdateframework/go-tuf/security/advisories/new) (requires being signed in to GitHub). At the minimum, the report must contain the following: + * A description of the issue. * A specific version or commit SHA of `go-tuf` where the issue reproduces. * Instructions to reproduce the issue. From c803c816c7061506db0791cc128ccf64d24e6226 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Dec 2022 19:35:18 +0200 Subject: [PATCH 36/46] chore(deps): bump actions/setup-go from 3.3.1 to 3.4.0 (#435) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3.3.1 to 3.4.0. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/c4a742cab115ed795e34d4513e2cf7d472deb55f...d0a58c1c4d2b25278816e339b944508c875f3613) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5ea02a2d..10b21f94 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: uses: arnested/go-version-action@b556f8d91b644164318c709d28b9083eaf0c064d id: go-version - name: Set up Go - uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f + uses: actions/setup-go@d0a58c1c4d2b25278816e339b944508c875f3613 with: go-version: ${{ steps.go-version.outputs.minimal }} - name: Run GoReleaser diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a4b510f8..83753d6e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v3 - name: Setup - Go ${{ matrix.go-version }} - uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f + uses: actions/setup-go@d0a58c1c4d2b25278816e339b944508c875f3613 with: go-version: ${{ matrix.go-version }} @@ -59,7 +59,7 @@ jobs: runs-on: ${{ matrix.os }} needs: get-go-versions steps: - - uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f + - uses: actions/setup-go@d0a58c1c4d2b25278816e339b944508c875f3613 with: go-version: ${{ matrix.go-version }} - uses: actions/checkout@v3 From 9cb61d6e65f5e63d17f2a628c94963bff6268498 Mon Sep 17 00:00:00 2001 From: Radoslav Dimitrov Date: Wed, 7 Dec 2022 18:17:17 +0200 Subject: [PATCH 37/46] chore: elevate GitHub token permissions for release.yml workflow (#437) Signed-off-by: Radoslav Dimitrov Signed-off-by: Radoslav Dimitrov --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6de89310..295923ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,8 @@ on: tags: - "v*" name: CI +permissions: + contents: write jobs: tests: uses: ./.github/workflows/tests.yml From 7e8644179b40943d37687d35bf5701efd6195261 Mon Sep 17 00:00:00 2001 From: Baptiste Foy Date: Mon, 9 Jan 2023 16:56:51 +0100 Subject: [PATCH 38/46] fix(localMeta): Add delegated targets back to localMeta (#384) * upgrade(localMeta): Verify delegated targets Adds verification of delegated targets when they go from the local store to the localMeta structure. The verification is done by selecting one target file per delegated targets that verify at least one, then build the delegation path from the top targets to that specific delegated file. Building the path is already verifying every targets in the path, so the whole path is safe to add to the localMeta. Doing so for every delegated targets lets us verify every delegated targets that is used at least once. Signed-off-by: Baptiste Foy --- client/client.go | 74 +++++++++++++++++++++++++++++++++++++- client/delegations.go | 53 ++++++++++++++++++++++----- client/delegations_test.go | 10 ++++++ pkg/targets/delegation.go | 7 ++++ 4 files changed, 134 insertions(+), 10 deletions(-) diff --git a/client/client.go b/client/client.go index f103d802..978ebf1d 100644 --- a/client/client.go +++ b/client/client.go @@ -4,9 +4,11 @@ import ( "bytes" "encoding/hex" "encoding/json" + "fmt" "io" "github.com/theupdateframework/go-tuf/data" + "github.com/theupdateframework/go-tuf/internal/roles" "github.com/theupdateframework/go-tuf/util" "github.com/theupdateframework/go-tuf/verify" ) @@ -399,8 +401,8 @@ func (c *Client) getLocalMeta() error { } } + snapshot := &data.Snapshot{} if snapshotJSON, ok := meta["snapshot.json"]; ok { - snapshot := &data.Snapshot{} if err := c.db.UnmarshalTrusted(snapshotJSON, snapshot, "snapshot"); err != nil { loadFailed = true retErr = err @@ -423,6 +425,35 @@ func (c *Client) getLocalMeta() error { c.loadTargets(targets.Targets) } } + + if loadFailed { + // If any of the metadata failed to be verified, return the reason for that failure + // and fail fast before delegated targets + return retErr + } + + // verifiedDelegatedTargets is a set of verified delegated targets + verifiedDelegatedTargets := make(map[string]bool) + for fileName := range meta { + if !verifiedDelegatedTargets[fileName] && roles.IsDelegatedTargetsManifest(fileName) { + if delegationPath, err := c.getDelegationPathFromRaw(snapshot, meta[fileName]); err != nil { + loadFailed = true + retErr = err + } else { + // Every delegated targets in the path has been verified + // as a side effect of getDelegationPathFromRaw + for _, key := range delegationPath { + fileName := fmt.Sprintf("%s.json", key) + verifiedDelegatedTargets[fileName] = true + } + } + } + } + + for fileName := range verifiedDelegatedTargets { + c.localMeta[fileName] = meta[fileName] + } + if loadFailed { // If any of the metadata failed to be verified, return the reason for that failure return retErr @@ -430,6 +461,47 @@ func (c *Client) getLocalMeta() error { return nil } +// getDelegationPathFromRaw verifies a delegated targets against +// a given snapshot and returns an error if it's invalid +// +// Delegation must have targets to get a path, else an empty list +// will be returned: this is because the delegation iterator is leveraged. +// +// Concrete example: +// targets +// └── a.json +//   └── b.json +//      └── c.json +//        └── target_file.txt +// +// If you try to use that function on "a.json" or "b.json", it'll return an empty list +// with no error, as neither of them declare a target file +// On the other hand, if you use that function on "c.json", it'll return & verify +// [c.json, b.json, a.json]. Running that function on every delegated targets +// guarantees that if a delegated targets is in the path of a target file, then it will +// appear at least once in the result +func (c *Client) getDelegationPathFromRaw(snapshot *data.Snapshot, delegatedTargetsJSON json.RawMessage) ([]string, error) { + // unmarshal the delegated targets first without verifying as + // we need at least one targets file name to leverage the + // getTargetFileMetaDelegationPath method + s := &data.Signed{} + if err := json.Unmarshal(delegatedTargetsJSON, s); err != nil { + return nil, err + } + targets := &data.Targets{} + if err := json.Unmarshal(s.Signed, targets); err != nil { + return nil, err + } + for targetPath := range targets.Targets { + _, resp, err := c.getTargetFileMetaDelegationPath(targetPath, snapshot) + // We only need to test one targets file: + // - If it is valid, it means the delegated targets has been validated + // - If it is not, the delegated targets isn't valid + return resp, err + } + return nil, nil +} + // loadAndVerifyLocalRootMeta decodes and verifies root metadata from // local storage and loads the top-level keys. This method first clears // the DB for top-level keys and then loads the new keys. diff --git a/client/delegations.go b/client/delegations.go index de3e6647..cc0fc482 100644 --- a/client/delegations.go +++ b/client/delegations.go @@ -8,13 +8,23 @@ import ( // getTargetFileMeta searches for a verified TargetFileMeta matching a target // Requires a local snapshot to be loaded and is locked to the snapshot versions. -// Searches through delegated targets following TUF spec 1.0.19 section 5.6. func (c *Client) getTargetFileMeta(target string) (data.TargetFileMeta, error) { snapshot, err := c.loadLocalSnapshot() if err != nil { return data.TargetFileMeta{}, err } + targetFileMeta, _, err := c.getTargetFileMetaDelegationPath(target, snapshot) + if err != nil { + return data.TargetFileMeta{}, err + } + return targetFileMeta, nil +} + +// getTargetFileMetaDelegationPath searches for a verified TargetFileMeta matching a target +// Requires snapshot to be passed and is locked to that specific snapshot versions. +// Searches through delegated targets following TUF spec 1.0.19 section 5.6. +func (c *Client) getTargetFileMetaDelegationPath(target string, snapshot *data.Snapshot) (data.TargetFileMeta, []string, error) { // delegationsIterator covers 5.6.7 // - pre-order depth-first search starting with the top targets // - filter delegations with paths or path_hash_prefixes matching searched target @@ -22,50 +32,75 @@ func (c *Client) getTargetFileMeta(target string) (data.TargetFileMeta, error) { // - 5.6.7.2 terminations delegations, err := targets.NewDelegationsIterator(target, c.db) if err != nil { - return data.TargetFileMeta{}, err + return data.TargetFileMeta{}, nil, err } + targetFileMeta := data.TargetFileMeta{} + delegationRole := "" + for i := 0; i < c.MaxDelegations; i++ { d, ok := delegations.Next() if !ok { - return data.TargetFileMeta{}, ErrUnknownTarget{target, snapshot.Version} + return data.TargetFileMeta{}, nil, ErrUnknownTarget{target, snapshot.Version} } // covers 5.6.{1,2,3,4,5,6} targets, err := c.loadDelegatedTargets(snapshot, d.Delegatee.Name, d.DB) if err != nil { - return data.TargetFileMeta{}, err + return data.TargetFileMeta{}, nil, err } // stop when the searched TargetFileMeta is found if m, ok := targets.Targets[target]; ok { - return m, nil + delegationRole = d.Delegatee.Name + targetFileMeta = m + break } if targets.Delegations != nil { delegationsDB, err := verify.NewDBFromDelegations(targets.Delegations) if err != nil { - return data.TargetFileMeta{}, err + return data.TargetFileMeta{}, nil, err } err = delegations.Add(targets.Delegations.Roles, d.Delegatee.Name, delegationsDB) if err != nil { - return data.TargetFileMeta{}, err + return data.TargetFileMeta{}, nil, err } } } - return data.TargetFileMeta{}, ErrMaxDelegations{ + if len(delegationRole) > 0 { + return targetFileMeta, buildPath(delegations.Parent, delegationRole, ""), nil + } + + return data.TargetFileMeta{}, nil, ErrMaxDelegations{ Target: target, MaxDelegations: c.MaxDelegations, SnapshotVersion: snapshot.Version, } } +func buildPath(parent func(string) string, start string, end string) []string { + if start == end { + return nil + } + + path := []string{start} + current := start + for { + current = parent(current) + if current == end { + break + } + path = append(path, current) + } + return path +} + func (c *Client) loadLocalSnapshot() (*data.Snapshot, error) { if err := c.getLocalMeta(); err != nil { return nil, err } - rawS, ok := c.localMeta["snapshot.json"] if !ok { return nil, ErrNoLocalSnapshot diff --git a/client/delegations_test.go b/client/delegations_test.go index 47fdc229..6d5a7767 100644 --- a/client/delegations_test.go +++ b/client/delegations_test.go @@ -226,17 +226,27 @@ func TestPersistedMeta(t *testing.T) { p, err := c.local.GetMeta() assert.Nil(t, err) persisted := copyStore(p) + persistedLocal := copyStore(c.localMeta) // trim non targets metas for _, notTargets := range []string{"root.json", "snapshot.json", "timestamp.json"} { delete(persisted, notTargets) + delete(persistedLocal, notTargets) } for _, targets := range tt.targets { + // Test local store storedVersion, err := versionOfStoredTargets(targets.name, persisted) assert.Equal(t, targets.version, storedVersion) assert.Nil(t, err) delete(persisted, targets.name) + + // Test localMeta + storedVersion, err = versionOfStoredTargets(targets.name, persistedLocal) + assert.Equal(t, targets.version, storedVersion) + assert.Nil(t, err) + delete(persistedLocal, targets.name) } assert.Empty(t, persisted) + assert.Empty(t, persistedLocal) }) } } diff --git a/pkg/targets/delegation.go b/pkg/targets/delegation.go index ccd52bae..dce61710 100644 --- a/pkg/targets/delegation.go +++ b/pkg/targets/delegation.go @@ -18,6 +18,7 @@ type delegationsIterator struct { stack []Delegation target string visitedRoles map[string]struct{} + parents map[string]string } var ErrTopLevelTargetsRoleMissing = errors.New("tuf: top level targets role missing from top level keys DB") @@ -43,6 +44,7 @@ func NewDelegationsIterator(target string, topLevelKeysDB *verify.DB) (*delegati }, }, visitedRoles: make(map[string]struct{}), + parents: make(map[string]string), } return i, nil } @@ -88,8 +90,13 @@ func (d *delegationsIterator) Add(roles []data.DelegatedRole, delegator string, DB: db, } d.stack = append(d.stack, delegation) + d.parents[r.Name] = delegator } } return nil } + +func (d *delegationsIterator) Parent(role string) string { + return d.parents[role] +} From 3889ddd0b8be629e3575fed738902ae58518ecc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jan 2023 13:57:52 +0200 Subject: [PATCH 39/46] chore(deps): bump actions/setup-python from 4.3.0 to 4.4.0 (#443) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.3.0 to 4.4.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/13ae5bb136fac2878aff31522b9efb785519f984...5ccb29d8773c3f3f653e1705f474dfaa8a06a912) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 83753d6e..42e4c57b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,7 +30,7 @@ jobs: go-version: ${{ matrix.go-version }} - name: Setup - Python - uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 + uses: actions/setup-python@5ccb29d8773c3f3f653e1705f474dfaa8a06a912 with: python-version: "3.10" cache: "pip" From f310d5e92a713b1b392ee9314a494fe743311e67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jan 2023 10:38:55 -0500 Subject: [PATCH 40/46] chore(deps): bump actions/setup-go from 3.4.0 to 3.5.0 (#441) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3.4.0 to 3.5.0. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/d0a58c1c4d2b25278816e339b944508c875f3613...6edd4406fa81c3da01a34fa6f6343087c207a568) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 10b21f94..607788d3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: uses: arnested/go-version-action@b556f8d91b644164318c709d28b9083eaf0c064d id: go-version - name: Set up Go - uses: actions/setup-go@d0a58c1c4d2b25278816e339b944508c875f3613 + uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 with: go-version: ${{ steps.go-version.outputs.minimal }} - name: Run GoReleaser diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 42e4c57b..86d16e71 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v3 - name: Setup - Go ${{ matrix.go-version }} - uses: actions/setup-go@d0a58c1c4d2b25278816e339b944508c875f3613 + uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 with: go-version: ${{ matrix.go-version }} @@ -59,7 +59,7 @@ jobs: runs-on: ${{ matrix.os }} needs: get-go-versions steps: - - uses: actions/setup-go@d0a58c1c4d2b25278816e339b944508c875f3613 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 with: go-version: ${{ matrix.go-version }} - uses: actions/checkout@v3 From a6e32beded459310bab509160bf2f93dd69edba0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jan 2023 10:42:07 -0500 Subject: [PATCH 41/46] chore(deps): bump goreleaser/goreleaser-action from 3.2.0 to 4.1.0 (#442) Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 3.2.0 to 4.1.0. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/b508e2e3ef3b19d4e4146d4f8fb3ba9db644a757...8f67e590f2d095516493f017008adc464e63adb1) --- updated-dependencies: - dependency-name: goreleaser/goreleaser-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 607788d3..54ee03f0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: with: go-version: ${{ steps.go-version.outputs.minimal }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@b508e2e3ef3b19d4e4146d4f8fb3ba9db644a757 + uses: goreleaser/goreleaser-action@8f67e590f2d095516493f017008adc464e63adb1 with: distribution: goreleaser version: "v1.7.0" From 5f964cf3047426fc536e9d963e259fd9fcf79c9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 09:56:19 -0600 Subject: [PATCH 42/46] chore(deps): bump actions/setup-python from 4.4.0 to 4.5.0 (#445) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.4.0 to 4.5.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/5ccb29d8773c3f3f653e1705f474dfaa8a06a912...d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 86d16e71..007387ca 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,7 +30,7 @@ jobs: go-version: ${{ matrix.go-version }} - name: Setup - Python - uses: actions/setup-python@5ccb29d8773c3f3f653e1705f474dfaa8a06a912 + uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 with: python-version: "3.10" cache: "pip" From 8f585b5ce1b0fe5fb53163ce93199c1bd8944819 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 10:11:39 -0600 Subject: [PATCH 43/46] chore(deps): bump requests from 2.28.1 to 2.28.2 (#446) Bumps [requests](https://github.com/psf/requests) from 2.28.1 to 2.28.2. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.28.1...v2.28.2) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: asraa --- requirements-test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-test.txt b/requirements-test.txt index 59333532..d8c8cb3d 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,5 +1,5 @@ iso8601==1.1.0 -requests==2.28.1 +requests==2.28.2 securesystemslib==0.25.0 six==1.16.0 tuf==2.0.0 From 66a4473601c3c47985ea93cfa1d870062292cc5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jan 2023 10:40:15 -0500 Subject: [PATCH 44/46] chore(deps): bump securesystemslib from 0.25.0 to 0.26.0 (#448) Bumps [securesystemslib](https://github.com/secure-systems-lab/securesystemslib) from 0.25.0 to 0.26.0. - [Release notes](https://github.com/secure-systems-lab/securesystemslib/releases) - [Changelog](https://github.com/secure-systems-lab/securesystemslib/blob/master/CHANGELOG.md) - [Commits](https://github.com/secure-systems-lab/securesystemslib/compare/v0.25.0...v0.26.0) --- updated-dependencies: - dependency-name: securesystemslib dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-test.txt b/requirements-test.txt index d8c8cb3d..00f20734 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,5 +1,5 @@ iso8601==1.1.0 requests==2.28.2 -securesystemslib==0.25.0 +securesystemslib==0.26.0 six==1.16.0 tuf==2.0.0 From 2b213572f6052571eb0d03a301812ce0e5f4daa9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jan 2023 09:59:12 -0600 Subject: [PATCH 45/46] chore(deps): bump github.com/dustin/go-humanize from 1.0.0 to 1.0.1 (#447) Bumps [github.com/dustin/go-humanize](https://github.com/dustin/go-humanize) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/dustin/go-humanize/releases) - [Commits](https://github.com/dustin/go-humanize/compare/v1.0.0...v1.0.1) --- updated-dependencies: - dependency-name: github.com/dustin/go-humanize dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: asraa --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ab6d7ada..f1b26376 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/theupdateframework/go-tuf go 1.18 require ( - github.com/dustin/go-humanize v1.0.0 + github.com/dustin/go-humanize v1.0.1 github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e github.com/google/gofuzz v1.2.0 github.com/secure-systems-lab/go-securesystemslib v0.4.0 diff --git a/go.sum b/go.sum index 4acdef41..067d7581 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e h1:Ss/B3/5wWRh8+emnK0++g5zQzwDTi30W10pKxKc4JXI= github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e/go.mod h1:HyVoz1Mz5Co8TFO8EupIdlcpwShBmY98dkT2xeHkvEI= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= From 91c85a09b56850c90201fa919efac8433bf4f907 Mon Sep 17 00:00:00 2001 From: asraa Date: Tue, 24 Jan 2023 10:22:03 -0600 Subject: [PATCH 46/46] test: add tests for rollback protection on snapshot, targets, delegations (#450) * test: add tests for rollback protection Signed-off-by: Asra Ali * golangci-lint Signed-off-by: Asra Ali Signed-off-by: Asra Ali --- client/client_test.go | 119 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/client/client_test.go b/client/client_test.go index b9fcbd81..f4dbd885 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -1223,6 +1223,125 @@ func (s *ClientSuite) TestUpdateHTTP(c *C) { } } +// TestRollbackSnapshot tests a rollback version of snapshot. +func (s *ClientSuite) TestRollbackSnapshot(c *C) { + client := s.updatedClient(c) + + // generate a new snapshot & timestamp v2 and sync with the client + version := client.snapshotVer + c.Assert(version > 0, Equals, true) + c.Assert(s.repo.Snapshot(), IsNil) + c.Assert(s.repo.Timestamp(), IsNil) + c.Assert(s.repo.Commit(), IsNil) + s.syncRemote(c) + _, err := client.Update() + c.Assert(err, IsNil) + c.Assert(client.snapshotVer > version, Equals, true) + + // replace remote snapshot.json with old version and timestamp again. + s.repo.SetSnapshotVersion(version) + c.Assert(s.repo.Snapshot(), IsNil) + c.Assert(s.repo.Timestamp(), IsNil) + c.Assert(s.repo.Commit(), IsNil) + s.syncRemote(c) + + // check update returns ErrLowVersion + _, err = client.Update() + + c.Assert(err, DeepEquals, verify.ErrLowVersion{ + Actual: version, + Current: client.snapshotVer, + }) +} + +func (s *ClientSuite) TestRollbackTopLevelTargets(c *C) { + client := s.updatedClient(c) + + // generate a new targets and sync with the client + version := client.targetsVer + c.Assert(version > 0, Equals, true) + s.addRemoteTarget(c, "bar.txt") + _, err := client.Update() + c.Assert(err, IsNil) + c.Assert(client.targetsVer > version, Equals, true) + + // replace remote snapshot.json with old version and timestamp again. + s.repo.SetTargetsVersion(version) + c.Assert(s.repo.Snapshot(), IsNil) + c.Assert(s.repo.Timestamp(), IsNil) + c.Assert(s.repo.Commit(), IsNil) + s.syncRemote(c) + + // check update returns ErrLowVersion + _, err = client.Update() + c.Assert(err, DeepEquals, verify.ErrLowVersion{ + Actual: version, + Current: client.targetsVer, + }) +} + +func (s *ClientSuite) TestRollbackDelegatedTargets(c *C) { + client := s.updatedClient(c) + // add a delegation + signer, err := keys.GenerateEd25519Key() + c.Assert(err, IsNil) + role := data.DelegatedRole{ + Name: "role", + KeyIDs: signer.PublicData().IDs(), + Paths: []string{"bar.txt", "baz.txt"}, + Threshold: 1, + } + s.store.SaveSigner("role", signer) + s.repo.AddDelegatedRole("targets", role, []*data.PublicKey{signer.PublicData()}) + s.repo.AddTargetToPreferredRole("bar.txt", nil, "role") + c.Assert(s.repo.Snapshot(), IsNil) + c.Assert(s.repo.Timestamp(), IsNil) + c.Assert(s.repo.Commit(), IsNil) + s.syncRemote(c) + + // save v1 delegation + meta, err := s.store.GetMeta() + c.Assert(err, IsNil) + oldRole, ok := meta["role.json"] + if !ok { + c.Fatal("missing role.json") + } + // update client and verify download delegated target + _, err = client.Update() + c.Assert(err, IsNil) + var dest testDestination + c.Assert(client.Download("bar.txt", &dest), IsNil) + + // update delegation to v2 + s.repo.AddTargetToPreferredRole("baz.txt", nil, "role") + c.Assert(s.repo.Snapshot(), IsNil) + c.Assert(s.repo.Timestamp(), IsNil) + c.Assert(s.repo.Commit(), IsNil) + s.syncRemote(c) + + // update client and verify download v2 delegated target + _, err = client.Update() + c.Assert(err, IsNil) + c.Assert(dest.Delete(), IsNil) + c.Assert(client.Download("baz.txt", &dest), IsNil) + + // rollback role.json version. + c.Assert(s.store.SetMeta("role.json", oldRole), IsNil) + repo, err := tuf.NewRepo(s.store) + c.Assert(err, IsNil) + c.Assert(repo.Snapshot(), IsNil) + c.Assert(repo.Timestamp(), IsNil) + c.Assert(repo.Commit(), IsNil) + s.syncRemote(c) + + // check update returns ErrLowVersion + _, err = client.Update() + c.Assert(err, DeepEquals, verify.ErrLowVersion{ + Actual: 1, + Current: 2, + }) +} + type testDestination struct { bytes.Buffer deleted bool