From adab5c53055aa020e0d70da1ad25a394376a9aa6 Mon Sep 17 00:00:00 2001 From: Lily Sturmann Date: Tue, 25 Jan 2022 08:59:46 -0500 Subject: [PATCH] Add logic to GET artifacts via old or new UUID (#587) * Move range.go into sharding package to avoid import cycles Signed-off-by: Lily Sturmann * Change name of FullID to EntryID Signed-off-by: Lily Sturmann * Add unit tests for sharding package Also add a few helper functions and update names. Signed-off-by: Lily Sturmann * Add logic to GET artifacts via old UUID or new EntryID Signed-off-by: Lily Sturmann * Add e2e test for longer EntryID Signed-off-by: Lily Sturmann --- cmd/rekor-cli/app/get.go | 17 ++- cmd/rekor-cli/app/pflags.go | 6 +- cmd/rekor-server/app/flags.go | 14 +- cmd/rekor-server/app/flags_test.go | 8 +- pkg/api/api.go | 7 +- pkg/api/entries.go | 8 +- pkg/{api => sharding}/ranges.go | 2 +- pkg/{api => sharding}/ranges_test.go | 2 +- pkg/sharding/sharding.go | 85 ++++++++--- pkg/sharding/sharding_test.go | 214 +++++++++++++++++++++++++++ tests/e2e_test.go | 8 + 11 files changed, 323 insertions(+), 48 deletions(-) rename pkg/{api => sharding}/ranges.go (98%) rename pkg/{api => sharding}/ranges_test.go (98%) create mode 100644 pkg/sharding/sharding_test.go diff --git a/cmd/rekor-cli/app/get.go b/cmd/rekor-cli/app/get.go index fe66a27a2..836277658 100644 --- a/cmd/rekor-cli/app/get.go +++ b/cmd/rekor-cli/app/get.go @@ -34,6 +34,7 @@ import ( "github.com/sigstore/rekor/pkg/generated/client/entries" "github.com/sigstore/rekor/pkg/generated/models" "github.com/sigstore/rekor/pkg/log" + "github.com/sigstore/rekor/pkg/sharding" "github.com/sigstore/rekor/pkg/types" ) @@ -84,6 +85,11 @@ var getCmd = &cobra.Command{ } logIndex := viper.GetString("log-index") + uuid := viper.GetString("uuid") + if logIndex == "" && uuid == "" { + return nil, errors.New("either --uuid or --log-index must be specified") + } + if logIndex != "" { params := entries.NewGetLogEntryByIndexParams() params.SetTimeout(viper.GetDuration("timeout")) @@ -106,11 +112,14 @@ var getCmd = &cobra.Command{ } } - uuid := viper.GetString("uuid") if uuid != "" { params := entries.NewGetLogEntryByUUIDParams() params.SetTimeout(viper.GetDuration("timeout")) - params.EntryUUID = uuid + + params.EntryUUID, err = sharding.GetUUIDFromIDString(uuid) + if err != nil { + return nil, fmt.Errorf("unable to parse uuid: %w", err) + } resp, err := rekorClient.Entries.GetLogEntryByUUID(params) if err != nil { @@ -118,7 +127,7 @@ var getCmd = &cobra.Command{ } for k, entry := range resp.Payload { - if k != uuid { + if k != params.EntryUUID { continue } @@ -130,7 +139,7 @@ var getCmd = &cobra.Command{ } } - return nil, errors.New("either --uuid or --log-index must be specified") + return nil, errors.New("entry not found") }), } diff --git a/cmd/rekor-cli/app/pflags.go b/cmd/rekor-cli/app/pflags.go index dbf239eb7..832f1bede 100644 --- a/cmd/rekor-cli/app/pflags.go +++ b/cmd/rekor-cli/app/pflags.go @@ -193,10 +193,10 @@ func validateFileOrURL(v string) error { return valGen().Set(v) } -// validateID ensures the ID is either a FullID (TreeID + UUID) or a UUID +// validateID ensures the ID is either an EntryID (TreeID + UUID) or a UUID func validateID(v string) error { - if len(v) != sharding.FullIDHexStringLen && len(v) != sharding.UUIDHexStringLen { - return fmt.Errorf("ID len error, expected %v (FullID) or %v (UUID) but got len %v for ID %v", sharding.FullIDHexStringLen, sharding.UUIDHexStringLen, len(v), v) + if len(v) != sharding.EntryIDHexStringLen && len(v) != sharding.UUIDHexStringLen { + return fmt.Errorf("ID len error, expected %v (EntryID) or %v (UUID) but got len %v for ID %v", sharding.EntryIDHexStringLen, sharding.UUIDHexStringLen, len(v), v) } if err := validateString("required,hexadecimal")(v); err != nil { diff --git a/cmd/rekor-server/app/flags.go b/cmd/rekor-server/app/flags.go index f20412ffc..7cb29a6ac 100644 --- a/cmd/rekor-server/app/flags.go +++ b/cmd/rekor-server/app/flags.go @@ -20,19 +20,19 @@ import ( "strconv" "strings" - "github.com/sigstore/rekor/pkg/api" + "github.com/sigstore/rekor/pkg/sharding" ) type LogRangesFlag struct { - Ranges api.LogRanges + Ranges sharding.LogRanges } func (l *LogRangesFlag) Set(s string) error { ranges := strings.Split(s, ",") - l.Ranges = api.LogRanges{} + l.Ranges = sharding.LogRanges{} var err error - inputRanges := []api.LogRange{} + inputRanges := []sharding.LogRange{} // Only go up to the second to last one, the last one is special cased beow for _, r := range ranges[:len(ranges)-1] { @@ -40,7 +40,7 @@ func (l *LogRangesFlag) Set(s string) error { if len(split) != 2 { return fmt.Errorf("invalid range flag, expected two parts separated by an =, got %s", r) } - lr := api.LogRange{} + lr := sharding.LogRange{} lr.TreeID, err = strconv.ParseUint(split[0], 10, 64) if err != nil { return err @@ -60,7 +60,7 @@ func (l *LogRangesFlag) Set(s string) error { return err } - inputRanges = append(inputRanges, api.LogRange{ + inputRanges = append(inputRanges, sharding.LogRange{ TreeID: lastTreeID, }) @@ -73,7 +73,7 @@ func (l *LogRangesFlag) Set(s string) error { TreeIDs[lr.TreeID] = struct{}{} } - l.Ranges = api.LogRanges{ + l.Ranges = sharding.LogRanges{ Ranges: inputRanges, } return nil diff --git a/cmd/rekor-server/app/flags_test.go b/cmd/rekor-server/app/flags_test.go index 90fa8b4ce..60faba544 100644 --- a/cmd/rekor-server/app/flags_test.go +++ b/cmd/rekor-server/app/flags_test.go @@ -19,20 +19,20 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/sigstore/rekor/pkg/api" + "github.com/sigstore/rekor/pkg/sharding" ) func TestLogRanges_Set(t *testing.T) { tests := []struct { name string arg string - want []api.LogRange + want []sharding.LogRange active uint64 }{ { name: "one, no length", arg: "1234", - want: []api.LogRange{ + want: []sharding.LogRange{ { TreeID: 1234, TreeLength: 0, @@ -43,7 +43,7 @@ func TestLogRanges_Set(t *testing.T) { { name: "two", arg: "1234=10,7234", - want: []api.LogRange{ + want: []sharding.LogRange{ { TreeID: 1234, TreeLength: 10, diff --git a/pkg/api/api.go b/pkg/api/api.go index 5211adede..ae98b678d 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -33,6 +33,7 @@ import ( "github.com/sigstore/rekor/pkg/log" pki "github.com/sigstore/rekor/pkg/pki/x509" + "github.com/sigstore/rekor/pkg/sharding" "github.com/sigstore/rekor/pkg/signer" "github.com/sigstore/rekor/pkg/storage" "github.com/sigstore/sigstore/pkg/cryptoutils" @@ -56,7 +57,7 @@ func dial(ctx context.Context, rpcServer string) (*grpc.ClientConn, error) { type API struct { logClient trillian.TrillianLogClient logID int64 - logRanges *LogRanges + logRanges *sharding.LogRanges pubkey string // PEM encoded public key pubkeyHash string // SHA256 hash of DER-encoded public key signer signature.Signer @@ -65,7 +66,7 @@ type API struct { certChainPem string // PEM encoded timestamping cert chain } -func NewAPI(ranges LogRanges) (*API, error) { +func NewAPI(ranges sharding.LogRanges) (*API, error) { logRPCServer := fmt.Sprintf("%s:%d", viper.GetString("trillian_log_server.address"), viper.GetUint("trillian_log_server.port")) @@ -156,7 +157,7 @@ var ( storageClient storage.AttestationStorage ) -func ConfigureAPI(ranges LogRanges) { +func ConfigureAPI(ranges sharding.LogRanges) { cfg := radix.PoolConfig{} var err error diff --git a/pkg/api/entries.go b/pkg/api/entries.go index 58701e29f..892c9a8d1 100644 --- a/pkg/api/entries.go +++ b/pkg/api/entries.go @@ -39,6 +39,7 @@ import ( "github.com/sigstore/rekor/pkg/generated/models" "github.com/sigstore/rekor/pkg/generated/restapi/operations/entries" "github.com/sigstore/rekor/pkg/log" + "github.com/sigstore/rekor/pkg/sharding" "github.com/sigstore/rekor/pkg/types" "github.com/sigstore/sigstore/pkg/signature" "github.com/sigstore/sigstore/pkg/signature/options" @@ -266,7 +267,12 @@ func getEntryURL(locationURL url.URL, uuid string) strfmt.URI { // GetLogEntryByUUIDHandler gets log entry and inclusion proof for specified UUID aka merkle leaf hash func GetLogEntryByUUIDHandler(params entries.GetLogEntryByUUIDParams) middleware.Responder { ctx := params.HTTPRequest.Context() - hashValue, _ := hex.DecodeString(params.EntryUUID) + + entryUUID, err := sharding.GetUUIDFromIDString(params.EntryUUID) + if err != nil { + return handleRekorAPIError(params, http.StatusBadRequest, err, "") + } + hashValue, _ := hex.DecodeString(entryUUID) tc := NewTrillianClient(params.HTTPRequest.Context()) resp := tc.getLeafAndProofByHash(hashValue) diff --git a/pkg/api/ranges.go b/pkg/sharding/ranges.go similarity index 98% rename from pkg/api/ranges.go rename to pkg/sharding/ranges.go index 9b30e8469..44301ec93 100644 --- a/pkg/api/ranges.go +++ b/pkg/sharding/ranges.go @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package api +package sharding type LogRanges struct { Ranges []LogRange diff --git a/pkg/api/ranges_test.go b/pkg/sharding/ranges_test.go similarity index 98% rename from pkg/api/ranges_test.go rename to pkg/sharding/ranges_test.go index aad6a662f..d8fe1b705 100644 --- a/pkg/api/ranges_test.go +++ b/pkg/sharding/ranges_test.go @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package api +package sharding import "testing" diff --git a/pkg/sharding/sharding.go b/pkg/sharding/sharding.go index e1df418c3..503b4e117 100644 --- a/pkg/sharding/sharding.go +++ b/pkg/sharding/sharding.go @@ -19,18 +19,16 @@ import ( "encoding/hex" "fmt" "strconv" - - "github.com/sigstore/rekor/pkg/api" ) -// A FullID refers to a specific artifact's ID and is made of two components, +// An EntryID refers to a specific artifact's ID and is made of two components, // the TreeID and the UUID. The TreeID is a hex-encoded uint64 (8 bytes) // referring to the specific trillian tree (also known as log or shard) where // the artifact can be found. The UUID is a hex-encoded 32-byte number // referring to the artifact's merkle leaf hash from trillian. Artifact lookup // by UUID occurs by finding the UUID within the tree specified by the TreeID. // -// A FullID is 40 bytes long and looks like this: +// An EntryID is 40 bytes long and looks like this: // FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF // |_______ ________| |_____________________________________ ______________________________________| // \/ \/ @@ -38,52 +36,91 @@ import ( const TreeIDHexStringLen = 16 const UUIDHexStringLen = 64 -const FullIDHexStringLen = TreeIDHexStringLen + UUIDHexStringLen +const EntryIDHexStringLen = TreeIDHexStringLen + UUIDHexStringLen // TODO: replace this with the actual LogRanges struct when logic is hooked up -var dummy = api.LogRanges{ - Ranges: []api.LogRange{}, +var dummyLogRanges = LogRanges{ + Ranges: []LogRange{ + { + TreeID: 0, + TreeLength: 0}}, } -type FullID struct { +type EntryID struct { TreeID string UUID string } -func CreateFullID(treeid string, uuid string) (FullID, error) { - if len(treeid) != TreeIDHexStringLen { +// This function can take a TreeID of equal or greater length than TreeIDHexStringLen. In +// case the TreeID length is less than TreeIDHexStringLen, it will be padded to the correct +// length. +func CreateEntryIDFromParts(treeid string, uuid string) (EntryID, error) { + if len(treeid) > TreeIDHexStringLen { err := fmt.Errorf("invalid treeid len: %v", len(treeid)) - return createEmptyFullID(), err + return createEmptyEntryID(), err } if len(uuid) != UUIDHexStringLen { err := fmt.Errorf("invalid uuid len: %v", len(uuid)) - return createEmptyFullID(), err + return createEmptyEntryID(), err + } + + treeidFormatted, err := PadToTreeIDLen(treeid) + if err != nil { + return createEmptyEntryID(), err } - if _, err := hex.DecodeString(treeid); err != nil { - err := fmt.Errorf("treeid is not a valid hex string: %v", treeid) - return createEmptyFullID(), err + if _, err := hex.DecodeString(treeidFormatted); err != nil { + err := fmt.Errorf("treeid %v is not a valid hex string: %v", treeidFormatted, err) + return createEmptyEntryID(), err } if _, err := hex.DecodeString(uuid); err != nil { - err := fmt.Errorf("uuid is not a valid hex string: %v", uuid) - return createEmptyFullID(), err + err := fmt.Errorf("uuid %v is not a valid hex string: %v", uuid, err) + return createEmptyEntryID(), err } - return FullID{ - TreeID: treeid, + return EntryID{ + TreeID: treeidFormatted, UUID: uuid}, nil } -func createEmptyFullID() FullID { - return FullID{ +func createEmptyEntryID() EntryID { + return EntryID{ TreeID: "", UUID: ""} } -func PrependActiveTreeID(uuid string) (FullID, error) { +func CreateEntryIDWithActiveTreeID(uuid string) (EntryID, error) { // TODO: Update this to be the global LogRanges struct - active := dummy.ActiveIndex() - return CreateFullID(strconv.FormatUint(active, 10), uuid) + treeid := strconv.FormatUint(dummyLogRanges.ActiveIndex(), 10) + return CreateEntryIDFromParts(treeid, uuid) +} + +func (e EntryID) ReturnEntryIDString() string { + return e.TreeID + e.UUID +} + +func PadToTreeIDLen(t string) (string, error) { + switch { + case len(t) == TreeIDHexStringLen: + return t, nil + case len(t) > TreeIDHexStringLen: + return "", fmt.Errorf("invalid treeID %v: too long", t) + default: + return fmt.Sprintf("%016s", t), nil + } +} + +// Returns UUID (with no prepended TreeID) from a UUID or EntryID string +func GetUUIDFromIDString(id string) (string, error) { + if len(id) != UUIDHexStringLen && len(id) != EntryIDHexStringLen { + return "", fmt.Errorf("invalid ID len %v for %v", len(id), id) + } + + if _, err := hex.DecodeString(id); err != nil { + return "", fmt.Errorf("id %v is not a valid hex string: %v", id, err) + } + + return id[len(id)-UUIDHexStringLen:], nil } diff --git a/pkg/sharding/sharding_test.go b/pkg/sharding/sharding_test.go new file mode 100644 index 000000000..61f115f11 --- /dev/null +++ b/pkg/sharding/sharding_test.go @@ -0,0 +1,214 @@ +// +// Copyright 2021 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sharding + +import ( + "strconv" + "testing" +) + +// Create some test data +// Good data +const validTreeID1 = "FFFFFFFFFFFFFFFF" +const validTreeID2 = "0000000000000000" +const validTreeID3 = "7241b7903737211c" +const shortTreeID = "12345" + +const validUUID = "f794467401d57241b7903737211c721cb3315648d077a9f02ceefb6e404a05de" + +const validEntryID1 = validTreeID1 + validUUID +const validEntryID2 = validTreeID2 + validUUID +const validEntryID3 = validTreeID3 + validUUID + +var validTreeIDs = []string{validTreeID1, validTreeID2, validTreeID3, shortTreeID} +var validEntryIDs = []string{validEntryID1, validEntryID2, validEntryID3} + +// Bad data +// Wrong length +const tooLongTreeID = validTreeID1 + "e" + +const tooLongUUID = validUUID + "e" + +var tooShortUUID = validUUID[:len(validUUID)-1] + +const tooLongEntryID = validEntryID1 + "e" + +var tooShortEntryID = validEntryID1[:len(validEntryID1)-1] + +var wrongLengthTreeIDs = []string{tooLongTreeID, validEntryID3, validUUID} +var wrongLengthUUIDs = []string{tooShortUUID, tooLongUUID, validEntryID3, validTreeID1} +var wrongLengthEntryandUUIDs = []string{tooLongEntryID, tooShortEntryID, tooLongUUID, tooShortUUID, validTreeID3} + +// Not valid hex +const notHexTreeID1 = "ZZZZZZZZZZZZZZZZ" +const notHexTreeID2 = "FFFFFFF_FFFFFFFF" +const notHexTreeID3 = "xxFFFFFFFFFFFFFF" + +const notHexUUID1 = "94467401d57241b7903737211c721cb3315648d077a9f02ceefb6e404a05dezq" +const notHexUUID2 = "y794467401d57241b7903737211c721cb3315648d077a9f02ceefb6e404a05de" +const notHexUUID3 = "f794467401d57241b7903737211c721cbp3315648d077a9f02ceefb6e404a05d" + +const notHexEntryID1 = notHexTreeID1 + validUUID +const notHexEntryID2 = validTreeID2 + notHexUUID1 +const notHexEntryID3 = notHexTreeID2 + notHexUUID3 + +var notHexTreeIDs = []string{notHexTreeID1, notHexTreeID2, notHexTreeID3} +var notHexUUIDs = []string{notHexUUID1, notHexUUID2, notHexUUID3} +var notHexEntryandUUIDs = []string{notHexEntryID1, notHexEntryID2, notHexEntryID3, notHexUUID1, notHexUUID2, notHexUUID3} + +// Test functions +func TestCreateEntryID(t *testing.T) { + for _, s := range wrongLengthTreeIDs { + if _, err := CreateEntryIDFromParts(s, validUUID); err == nil { + t.Errorf("expected length error for wrong TreeID of invalid len: %v", s) + } + } + + for _, s := range wrongLengthUUIDs { + if _, err := CreateEntryIDFromParts(validTreeID1, s); err == nil { + t.Errorf("expected length error for wrong UUID of invalid len: %v", s) + } + } + + for _, s := range notHexTreeIDs { + if _, err := CreateEntryIDFromParts(s, validUUID); err == nil { + t.Errorf("expected hex error for TreeID: %v", s) + } + } + for _, s := range notHexUUIDs { + if _, err := CreateEntryIDFromParts(validTreeID3, s); err == nil { + t.Errorf("expected hex error for UUID: %v", s) + } + } + + for _, tid := range validTreeIDs { + entryID, err := CreateEntryIDFromParts(tid, validUUID) + if err != nil { + t.Errorf("failed to create entryID from %v + %v: %v", tid, validUUID, err) + } + + expectedTid, _ := PadToTreeIDLen(tid) + if entryID.TreeID != expectedTid { + t.Errorf("created entryID with incorrect treeID: expected %v, got %v", tid, entryID.TreeID) + } + + if entryID.UUID != validUUID { + t.Errorf("created entryID with incorrect UUID: expected %v, got %v", validUUID, entryID.UUID) + } + } + +} + +func TestCreateEmptyEntryID(t *testing.T) { + emptyEntryID := createEmptyEntryID() + + if emptyEntryID.TreeID != "" { + t.Errorf("expected empty EntryID.TreeID but got %v", emptyEntryID.TreeID) + } + + if emptyEntryID.UUID != "" { + t.Errorf("expected empty EntryID.UUID but got %v", emptyEntryID.UUID) + } +} + +func TestCreateEntryIDWithActiveTreeID(t *testing.T) { + entryID, err := CreateEntryIDWithActiveTreeID(validUUID) + if err != nil { + t.Errorf("unable to create entryID: %v", err) + } + + // TODO: Update dummy to be the global LogRanges struct + activeIndexString := strconv.FormatUint(dummyLogRanges.ActiveIndex(), 10) + expectedTreeID, err := PadToTreeIDLen(activeIndexString) + if err != nil { + t.Errorf("unable to pad %v to treeIDLen: %v", activeIndexString, err) + } + if entryID.TreeID != expectedTreeID { + t.Errorf("expected entryID.TreeID %v but got %v", dummyLogRanges.ActiveIndex(), entryID.TreeID) + } + + if entryID.UUID != validUUID { + t.Errorf("expected entryID.TreeID %v but got %v", validUUID, entryID.UUID) + } +} + +func TestPadToTreeIDLen(t *testing.T) { + short := "12345678" + shortPadded := "0000000012345678" + medium := "1234567812345678" + long := "12345678901234567890" + + result1, err1 := PadToTreeIDLen(short) + if result1 != shortPadded || err1 != nil { + t.Errorf("error padding %v: expected (%v, nil), got (%v, %v)", short, shortPadded, result1, err1) + } + + result2, err2 := PadToTreeIDLen(medium) + if result2 != medium || err2 != nil { + t.Errorf("error padding %v: expected (%v, nil), got (%v, %v)", medium, medium, result2, err2) + } + + result3, err3 := PadToTreeIDLen(long) + if result3 != "" || err3 == nil { + t.Errorf("expected error in padding %v, but got %v", long, result3) + } +} + +func TestReturnEntryIDString(t *testing.T) { + entryID, _ := CreateEntryIDFromParts(validTreeID1, validUUID) + + IDString := entryID.ReturnEntryIDString() + + if IDString != validEntryID1 { + t.Errorf("expected entryID string %v but got %v", validEntryID1, IDString) + } +} + +func TestGetUUIDFromIDString(t *testing.T) { + for _, s := range wrongLengthEntryandUUIDs { + // TODO: check for correct error + if _, err := GetUUIDFromIDString(s); err == nil { + t.Errorf("expected length error for GetUUIDFromIDString(%v) but no error was found", s) + } + } + + for _, s := range notHexEntryandUUIDs { + // TODO: check for correct error + if _, err := GetUUIDFromIDString(s); err == nil { + t.Errorf("expected invalid hex error for GetUUIDFromIDString(%v) but no error was found", s) + } + } + + // Return entire UUID + res, err := GetUUIDFromIDString(validUUID) + if err != nil { + t.Errorf("unexpected error for GetUUIDFromIDString(%v): %v", validUUID, err) + } + if res != validUUID { + t.Errorf("expected result %v for GetUUIDFromIDString(%v) but got %v", validUUID, validUUID, res) + } + + // Return UUID from EntryID + for _, s := range validEntryIDs { + res, err := GetUUIDFromIDString(s) + if err != nil { + t.Errorf("unexpected error for GetUUIDFromIDString(%v): %v", s, err) + } + if res != validUUID { + t.Errorf("expected result %v for GetUUIDFromIDString(%v) but got %v", validUUID, s, res) + } + } +} diff --git a/tests/e2e_test.go b/tests/e2e_test.go index 94f2a87d3..5412c5a9a 100644 --- a/tests/e2e_test.go +++ b/tests/e2e_test.go @@ -54,6 +54,7 @@ import ( "github.com/sigstore/rekor/pkg/generated/client/entries" "github.com/sigstore/rekor/pkg/generated/client/timestamp" "github.com/sigstore/rekor/pkg/generated/models" + "github.com/sigstore/rekor/pkg/sharding" "github.com/sigstore/rekor/pkg/signer" rekord "github.com/sigstore/rekor/pkg/types/rekord/v0.0.1" "github.com/sigstore/rekor/pkg/util" @@ -255,6 +256,13 @@ func TestGet(t *testing.T) { out = runCli(t, "search", "--sha", fmt.Sprintf("sha256:%s", hex.EncodeToString(sha[:]))) outputContains(t, out, uuid) + + // Exercise GET with the new EntryID (TreeID + UUID) + entryID, err := sharding.CreateEntryIDFromParts("0", uuid) + if err != nil { + t.Error(err) + } + out = runCli(t, "get", "--format=json", "--uuid", entryID.ReturnEntryIDString()) } func TestSearchNoEntriesRC1(t *testing.T) {