Skip to content

Commit 795a236

Browse files
authored
add client method to generate TLE struct (#1498)
* add client method to generate TLE protobuf Signed-off-by: Bob Callaway <[email protected]> * go mod tidy Signed-off-by: Bob Callaway <[email protected]> * remove CLI usage Signed-off-by: Bob Callaway <[email protected]> * add unit tests Signed-off-by: Bob Callaway <[email protected]> * fix lint issues Signed-off-by: Bob Callaway <[email protected]> * add back CLI output option for rekor-cli get Signed-off-by: Bob Callaway <[email protected]> * fix func comment Signed-off-by: Bob Callaway <[email protected]> --------- Signed-off-by: Bob Callaway <[email protected]>
1 parent 161a796 commit 795a236

File tree

7 files changed

+301
-1
lines changed

7 files changed

+301
-1
lines changed

cmd/rekor-cli/app/format/wrap.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ import (
1919
"encoding/json"
2020
"fmt"
2121

22+
rekor_pb "github.com/sigstore/protobuf-specs/gen/pb-go/rekor/v1"
23+
24+
"github.com/sigstore/rekor/pkg/client"
2225
"github.com/sigstore/rekor/pkg/log"
2326
"github.com/spf13/cobra"
2427
"github.com/spf13/viper"
@@ -46,6 +49,16 @@ func WrapCmd(f formatCmd) CobraCmd {
4649
}
4750
case "json":
4851
fmt.Println(toJSON(obj))
52+
case "tle":
53+
if tle, ok := obj.(*rekor_pb.TransparencyLogEntry); ok {
54+
json, err := client.MarshalTLEToJSON(tle)
55+
if err != nil {
56+
log.CliLogger.Fatalf("error converting to transparency log entry: %v", err)
57+
}
58+
fmt.Println(string(json))
59+
} else {
60+
log.CliLogger.Fatal("unable to print transparency log entry")
61+
}
4962
}
5063
}
5164
}

cmd/rekor-cli/app/get.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ func compareEntryUUIDs(requestEntryUUID string, responseEntryUUID string) error
203203
}
204204

205205
func parseEntry(uuid string, e models.LogEntryAnon) (interface{}, error) {
206+
if viper.GetString("format") == "tle" {
207+
return client.GenerateTransparencyLogEntry(e)
208+
}
209+
206210
b, err := base64.StdEncoding.DecodeString(e.Body.(string))
207211
if err != nil {
208212
return nil, err

cmd/rekor-cli/app/pflags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func initializePFlagMap() {
111111
},
112112
formatFlag: func() pflag.Value {
113113
// this validates the output format requested
114-
return valueFactory(formatFlag, validateString("required,oneof=json default"), "")
114+
return valueFactory(formatFlag, validateString("required,oneof=json default tle"), "")
115115
},
116116
timeoutFlag: func() pflag.Value {
117117
// this validates the timeout is >= 0

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ require (
5858
github.com/hashicorp/go-cleanhttp v0.5.2
5959
github.com/hashicorp/go-retryablehttp v0.7.2
6060
github.com/redis/go-redis/v9 v9.0.4
61+
github.com/sigstore/protobuf-specs v0.1.0
6162
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
6263
)
6364

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,6 +1845,8 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR
18451845
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
18461846
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
18471847
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
1848+
github.com/sigstore/protobuf-specs v0.1.0 h1:X0l/E2C2c79t/rI/lmSu8WAoKWsQtMqDzAMiDdEMGr8=
1849+
github.com/sigstore/protobuf-specs v0.1.0/go.mod h1:5shUCxf82hGnjUEFVWiktcxwzdtn6EfeeJssxZ5Q5HE=
18481850
github.com/sigstore/sigstore v1.6.4 h1:jH4AzR7qlEH/EWzm+opSpxCfuUcjHL+LJPuQE7h40WE=
18491851
github.com/sigstore/sigstore v1.6.4/go.mod h1:pjR64lBxnjoSrAr+Ydye/FV73IfrgtoYlAI11a8xMfA=
18501852
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=

pkg/client/rekor_client.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
package client
1616

1717
import (
18+
"bytes"
1819
"crypto/tls"
20+
"encoding/base64"
21+
"encoding/hex"
22+
"fmt"
1923
"net/http"
2024
"net/url"
2125

@@ -24,8 +28,13 @@ import (
2428
"github.com/go-openapi/strfmt"
2529
"github.com/hashicorp/go-cleanhttp"
2630
retryablehttp "github.com/hashicorp/go-retryablehttp"
31+
rekor_pb_common "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
32+
rekor_pb "github.com/sigstore/protobuf-specs/gen/pb-go/rekor/v1"
2733
"github.com/sigstore/rekor/pkg/generated/client"
34+
"github.com/sigstore/rekor/pkg/generated/models"
35+
"github.com/sigstore/rekor/pkg/types"
2836
"github.com/sigstore/rekor/pkg/util"
37+
"google.golang.org/protobuf/encoding/protojson"
2938
)
3039

3140
func GetRekorClient(rekorServerURL string, opts ...Option) (*client.Rekor, error) {
@@ -64,3 +73,70 @@ func GetRekorClient(rekorServerURL string, opts ...Option) (*client.Rekor, error
6473
registry.Add("signedCheckpoint", &util.SignedNote{}, util.SignedCheckpointValidator)
6574
return client.New(rt, registry), nil
6675
}
76+
77+
// GenerateTransparencyLogEntry returns a sigstore/protobuf-specs compliant message containing a
78+
// TransparencyLogEntry as defined at https://github.com/sigstore/protobuf-specs/blob/main/protos/sigstore_rekor.proto
79+
func GenerateTransparencyLogEntry(anon models.LogEntryAnon) (*rekor_pb.TransparencyLogEntry, error) {
80+
logIDHash, err := hex.DecodeString(*anon.LogID)
81+
if err != nil {
82+
return nil, fmt.Errorf("decoding logID string: %w", err)
83+
}
84+
85+
rootHash, err := hex.DecodeString(*anon.Verification.InclusionProof.RootHash)
86+
if err != nil {
87+
return nil, fmt.Errorf("decoding inclusion proof root hash: %w", err)
88+
}
89+
90+
inclusionProofHashes := make([][]byte, len(anon.Verification.InclusionProof.Hashes))
91+
for i, hash := range anon.Verification.InclusionProof.Hashes {
92+
hashBytes, err := hex.DecodeString(hash)
93+
if err != nil {
94+
return nil, fmt.Errorf("decoding inclusion proof hash: %w", err)
95+
}
96+
inclusionProofHashes[i] = hashBytes
97+
}
98+
99+
b, err := base64.StdEncoding.DecodeString(anon.Body.(string))
100+
if err != nil {
101+
return nil, fmt.Errorf("base64 decoding body: %w", err)
102+
}
103+
104+
pe, err := models.UnmarshalProposedEntry(bytes.NewReader(b), runtime.JSONConsumer())
105+
if err != nil {
106+
return nil, err
107+
}
108+
eimpl, err := types.UnmarshalEntry(pe)
109+
if err != nil {
110+
return nil, err
111+
}
112+
113+
return &rekor_pb.TransparencyLogEntry{
114+
LogIndex: *anon.LogIndex,
115+
LogId: &rekor_pb_common.LogId{
116+
KeyId: logIDHash,
117+
},
118+
KindVersion: &rekor_pb.KindVersion{
119+
Kind: pe.Kind(),
120+
Version: eimpl.APIVersion(),
121+
},
122+
IntegratedTime: *anon.IntegratedTime,
123+
InclusionPromise: &rekor_pb.InclusionPromise{
124+
SignedEntryTimestamp: anon.Verification.SignedEntryTimestamp,
125+
},
126+
InclusionProof: &rekor_pb.InclusionProof{
127+
LogIndex: *anon.LogIndex,
128+
RootHash: rootHash,
129+
TreeSize: *anon.Verification.InclusionProof.TreeSize,
130+
Hashes: inclusionProofHashes,
131+
Checkpoint: &rekor_pb.Checkpoint{
132+
Envelope: *anon.Verification.InclusionProof.Checkpoint,
133+
},
134+
},
135+
CanonicalizedBody: b, // we don't call eimpl.Canonicalize in the case that the logic is different in this caller vs when it was persisted in the log
136+
}, nil
137+
}
138+
139+
// MarshalTLEToJSON marshals a TransparencyLogEntry message to JSON according to the protobuf JSON encoding rules
140+
func MarshalTLEToJSON(tle *rekor_pb.TransparencyLogEntry) ([]byte, error) {
141+
return protojson.Marshal(tle)
142+
}

0 commit comments

Comments
 (0)