Skip to content
Snippets Groups Projects
Unverified Commit 8b972796 authored by Bob Callaway's avatar Bob Callaway Committed by GitHub
Browse files

block to return for insertion until leaf has been added (#139)

parent 68c5f36d
No related branches found
No related tags found
No related merge requests found
......@@ -20,6 +20,7 @@ import (
"fmt"
"os"
"github.com/go-openapi/swag"
"github.com/projectrekor/rekor/cmd/cli/app/format"
"github.com/projectrekor/rekor/pkg/generated/client/entries"
"github.com/projectrekor/rekor/pkg/generated/models"
......@@ -30,11 +31,12 @@ import (
type uploadCmdOutput struct {
Location string
Index int64
}
func (u *uploadCmdOutput) String() string {
if u.Location != "" {
return fmt.Sprintf("Created entry at: %v%v\n", viper.GetString("rekor_server"), u.Location)
return fmt.Sprintf("Created entry at index %d, available at: %v%v\n", u.Index, viper.GetString("rekor_server"), u.Location)
}
return "Entry already exists.\n"
}
......@@ -90,8 +92,14 @@ var uploadCmd = &cobra.Command{
}
}
var newIndex int64
for _, entry := range resp.Payload {
newIndex = swag.Int64Value(entry.LogIndex)
}
return &uploadCmdOutput{
Location: string(resp.Location),
Index: newIndex,
}, nil
}),
}
......
......@@ -22,6 +22,7 @@ import (
"time"
"github.com/google/trillian"
"github.com/google/trillian/client"
"github.com/google/trillian/crypto/keyspb"
radix "github.com/mediocregopher/radix/v4"
"github.com/projectrekor/rekor/pkg/log"
......@@ -45,6 +46,7 @@ type API struct {
logClient trillian.TrillianLogClient
logID int64
pubkey *keyspb.PublicKey
verifier *client.LogVerifier
}
func NewAPI() (*API, error) {
......@@ -74,11 +76,16 @@ func NewAPI() (*API, error) {
if err != nil {
return nil, err
}
verifier, err := client.NewLogVerifierFromTree(t)
if err != nil {
return nil, err
}
return &API{
logClient: logClient,
logID: tLogID,
pubkey: t.PublicKey,
verifier: verifier,
}, nil
}
......@@ -101,12 +108,3 @@ func ConfigureAPI() {
}
}
}
func NewTrillianClient(ctx context.Context) TrillianClient {
return TrillianClient{
client: api.logClient,
logID: api.logID,
context: ctx,
pubkey: api.pubkey,
}
}
......@@ -113,8 +113,8 @@ func CreateLogEntryHandler(params entries.CreateLogEntryParams) middleware.Respo
logEntry := models.LogEntry{
uuid: models.LogEntryAnon{
//LogIndex is not given here because it is always returned as 0
Body: queuedLeaf.GetLeafValue(),
LogIndex: swag.Int64(queuedLeaf.LeafIndex),
Body: queuedLeaf.GetLeafValue(),
},
}
......
......@@ -28,16 +28,25 @@ import (
"github.com/google/trillian/client"
"github.com/google/trillian/crypto/keyspb"
"github.com/google/trillian/crypto/sigpb"
"github.com/google/trillian/merkle"
"github.com/google/trillian/merkle/rfc6962"
"github.com/google/trillian/types"
)
type TrillianClient struct {
client trillian.TrillianLogClient
logID int64
context context.Context
pubkey *keyspb.PublicKey
client trillian.TrillianLogClient
logID int64
context context.Context
pubkey *keyspb.PublicKey
verifier *client.LogVerifier
}
func NewTrillianClient(ctx context.Context) TrillianClient {
return TrillianClient{
client: api.logClient,
logID: api.logID,
context: ctx,
pubkey: api.pubkey,
verifier: api.verifier,
}
}
type Response struct {
......@@ -76,6 +85,44 @@ func (t *TrillianClient) addLeaf(byteValue []byte) *Response {
}
resp, err := t.client.QueueLeaf(t.context, rqst)
// check for error
if err != nil || (resp.QueuedLeaf.Status != nil && resp.QueuedLeaf.Status.Code != int32(codes.OK)) {
return &Response{
status: status.Code(err),
err: err,
getAddResult: resp,
}
}
root, err := t.root()
if err != nil {
return &Response{
status: status.Code(err),
err: err,
getAddResult: resp,
}
}
logClient := client.New(t.logID, t.client, t.verifier, root)
if err := logClient.WaitForInclusion(t.context, byteValue); err != nil {
return &Response{
status: status.Code(err),
err: err,
getAddResult: resp,
}
}
leafResp := t.getLeafByHash([][]byte{resp.QueuedLeaf.Leaf.MerkleLeafHash})
if leafResp.err != nil {
return &Response{
status: status.Code(leafResp.err),
err: leafResp.err,
getAddResult: resp,
}
}
//overwrite queued leaf that doesn't have index set
resp.QueuedLeaf.Leaf = leafResp.getLeafResult.Leaves[0]
return &Response{
status: status.Code(err),
err: err,
......@@ -136,11 +183,9 @@ func (t *TrillianClient) getProofByHash(hashValue []byte) *Response {
TreeSize: int64(root.TreeSize),
})
v := merkle.NewLogVerifier(rfc6962.DefaultHasher)
if resp != nil {
for _, proof := range resp.Proof {
if err := v.VerifyInclusionProof(proof.LeafIndex, int64(root.TreeSize), proof.GetHashes(), root.RootHash, hashValue); err != nil {
if err := t.verifier.VerifyInclusionByHash(&root, hashValue, proof); err != nil {
return &Response{
status: status.Code(err),
err: err,
......
......@@ -9,9 +9,17 @@ import (
"strconv"
"strings"
"testing"
"time"
)
func getUUIDFromUploadOutput(t *testing.T, out string) string {
t.Helper()
// Output looks like "Created entry at index X, available at $URL/UUID", so grab the UUID:
urlTokens := strings.Split(strings.TrimSpace(out), " ")
url := urlTokens[len(urlTokens)-1]
splitUrl := strings.Split(url, "/")
return splitUrl[len(splitUrl)-1]
}
func TestDuplicates(t *testing.T) {
artifactPath := filepath.Join(t.TempDir(), "artifact")
sigPath := filepath.Join(t.TempDir(), "signature.asc")
......@@ -59,9 +67,6 @@ func TestUploadVerifyRekord(t *testing.T) {
out := runCli(t, "upload", "--artifact", artifactPath, "--signature", sigPath, "--public-key", pubPath)
outputContains(t, out, "Created entry at")
// We have to wait some time for the log to get signed and included.
time.Sleep(3 * time.Second)
// Now we should be able to verify it.
out = runCli(t, "verify", "--artifact", artifactPath, "--signature", sigPath, "--public-key", pubPath)
outputContains(t, out, "Inclusion Proof:")
......@@ -88,9 +93,6 @@ func TestUploadVerifyRpm(t *testing.T) {
out := runCli(t, "upload", "--type=rpm", "--artifact", rpmPath, "--public-key", pubPath)
outputContains(t, out, "Created entry at")
// We have to wait some time for the log to get signed and included.
time.Sleep(3 * time.Second)
// Now we should be able to verify it.
out = runCli(t, "verify", "--type=rpm", "--artifact", rpmPath, "--public-key", pubPath)
outputContains(t, out, "Inclusion Proof:")
......@@ -117,13 +119,7 @@ func TestGet(t *testing.T) {
out := runCli(t, "upload", "--artifact", artifactPath, "--signature", sigPath, "--public-key", pubPath)
outputContains(t, out, "Created entry at")
// Wait a second for the entry to be added.
time.Sleep(1 * time.Second)
// Output looks like "Created entry at $URL/UUID", so grab the UUID:
url := strings.Split(strings.TrimSpace(out), " ")[3]
splitUrl := strings.Split(url, "/")
uuid := splitUrl[len(splitUrl)-1]
uuid := getUUIDFromUploadOutput(t, out)
out = runCli(t, "get", "--format=json", "--uuid", uuid)
// The output here should be in JSON with this structure:
......@@ -172,13 +168,7 @@ func TestMinisign(t *testing.T) {
"--public-key", pubPath, "--pki-format", "minisign")
outputContains(t, out, "Created entry at")
// Output looks like "Created entry at $URL/UUID", so grab the UUID:
url := strings.Split(strings.TrimSpace(out), " ")[3]
splitUrl := strings.Split(url, "/")
uuid := splitUrl[len(splitUrl)-1]
// Wait and check it.
time.Sleep(3 * time.Second)
uuid := getUUIDFromUploadOutput(t, out)
out = runCli(t, "verify", "--artifact", artifactPath, "--signature", sigPath,
"--public-key", pubPath, "--pki-format", "minisign")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment