Skip to content

Commit

Permalink
Upload generated timestamps (#336)
Browse files Browse the repository at this point in the history
* upload all generated timestamps

Signed-off-by: Asra Ali <asraa@google.com>

* address bazooka comments

Signed-off-by: Asra Ali <asraa@google.com>

* simplify params

Signed-off-by: Asra Ali <asraa@google.com>

* address changes

Signed-off-by: Asra Ali <asraa@google.com>

* forgot to run swagger

Signed-off-by: Asra Ali <asraa@google.com>
  • Loading branch information
asraa authored Jun 23, 2021
1 parent 0882cde commit 34caf45
Show file tree
Hide file tree
Showing 14 changed files with 334 additions and 94 deletions.
16 changes: 1 addition & 15 deletions cmd/rekor-cli/app/pflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,27 +250,13 @@ func CreateIntotoFromPFlags() (models.ProposedEntry, error) {

func CreateRFC3161FromPFlags() (models.ProposedEntry, error) {
//TODO: how to select version of item to create
returnVal := models.Rfc3161{}

rfc3161 := viper.GetString("artifact")
b, err := ioutil.ReadFile(filepath.Clean(rfc3161))
if err != nil {
return nil, fmt.Errorf("error reading public key file: %w", err)
}

b64 := strfmt.Base64(b)
re := rfc3161_v001.V001Entry{
Rfc3161Obj: models.Rfc3161V001Schema{
Tsr: &models.Rfc3161V001SchemaTsr{
Content: &b64,
},
},
}

returnVal.Spec = re.Rfc3161Obj
returnVal.APIVersion = swag.String(re.APIVersion())

return &returnVal, nil
return rfc3161_v001.NewEntryFromBytes(b), nil
}

func CreateRpmFromPFlags() (models.ProposedEntry, error) {
Expand Down
27 changes: 18 additions & 9 deletions cmd/rekor-cli/app/timestamp.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"path/filepath"
"strconv"
"strings"
"time"

"github.com/sassoftware/relic/lib/pkcs9"
"github.com/sassoftware/relic/lib/x509tools"
Expand Down Expand Up @@ -94,7 +95,6 @@ func addTimestampFlags(cmd *cobra.Command) error {

cmd.Flags().String("out", "response.tsr", "path to a file to write response.")

// TODO: Add a flag to upload a pre-formed timestamp response to the log.
// TODO: Add a flag to indicate a JSON formatted timestamp request/response.
return nil
}
Expand Down Expand Up @@ -175,13 +175,15 @@ func createRequestFromFlags() (*pkcs9.TimeStampReq, error) {
}

type timestampCmdOutput struct {
Location string
Timestamp time.Time
Location string
UUID string
Index int64
}

func (t *timestampCmdOutput) String() string {
return fmt.Sprintf(`
Wrote response to: %v
`, t.Location)
return fmt.Sprintf("Artifact timestamped at %s\nWrote timestamp response to %v\nCreated entry at index %d, available at: %v%v\n",
t.Timestamp, t.Location, t.Index, viper.GetString("rekor_server"), t.UUID)
}

var timestampCmd = &cobra.Command{
Expand Down Expand Up @@ -218,12 +220,17 @@ var timestampCmd = &cobra.Command{
params.Request = ioutil.NopCloser(bytes.NewReader(requestBytes))

var respBytes bytes.Buffer
_, err = rekorClient.Timestamp.GetTimestampResponse(params, &respBytes)
resp, err := rekorClient.Timestamp.GetTimestampResponse(params, &respBytes)
if err != nil {
return nil, err
}
// Sanity check response and check if the TimeStampToken was successfully created
if _, err = timestampReq.ParseResponse(respBytes.Bytes()); err != nil {
psd, err := timestampReq.ParseResponse(respBytes.Bytes())
if err != nil {
return nil, err
}
genTime, err := util.GetSigningTime(psd)
if err != nil {
return nil, err
}

Expand All @@ -236,9 +243,11 @@ var timestampCmd = &cobra.Command{
return nil, err
}

// TODO: Add log index after support for uploading to transparency log is added.
return &timestampCmdOutput{
Location: outStr,
Location: outStr,
UUID: string(resp.Location),
Timestamp: genTime.Round(time.Second),
Index: resp.Index,
}, nil
}),
}
Expand Down
18 changes: 14 additions & 4 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,7 @@ paths:

/api/v1/timestamp:
post:
# TODO: Add uploads to transparency log.
summary: Returns a timestamp response generated by Rekor
summary: Generates a new timestamp response and creates a new log entry for the timestamp in the transparency log
operationId: getTimestampResponse
tags:
- timestamp
Expand All @@ -244,11 +243,22 @@ paths:
type: string
format: binary
responses:
200:
description: Returns a timestamp response
201:
description: Returns a timestamp response and the location of the log entry in the transprency log
schema:
type: string
format: binary
headers:
ETag:
type: string
description: UUID of the log entry made for the timestamp response
Location:
type: string
description: URI location of the log entry made for the timestamp response
format: uri
Index:
type: integer
description: Log index of the log entry made for the timestamp response
400:
$ref: '#/responses/BadContent'
501:
Expand Down
39 changes: 27 additions & 12 deletions pkg/api/entries.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,26 +127,23 @@ func GetLogEntryByIndexHandler(params entries.GetLogEntryByIndexParams) middlewa
return entries.NewGetLogEntryByIndexOK().WithPayload(logEntry)
}

// CreateLogEntryHandler creates new entry into log
func CreateLogEntryHandler(params entries.CreateLogEntryParams) middleware.Responder {
func createLogEntry(params entries.CreateLogEntryParams) (models.LogEntry, middleware.Responder) {
ctx := params.HTTPRequest.Context()
httpReq := params.HTTPRequest
entry, err := types.NewEntry(params.ProposedEntry)
if err != nil {
return handleRekorAPIError(params, http.StatusBadRequest, err, err.Error())
return nil, handleRekorAPIError(params, http.StatusBadRequest, err, err.Error())
}

leaf, err := entry.Canonicalize(httpReq.Context())
leaf, err := entry.Canonicalize(ctx)
if err != nil {
return handleRekorAPIError(params, http.StatusInternalServerError, err, failedToGenerateCanonicalEntry)
return nil, handleRekorAPIError(params, http.StatusInternalServerError, err, failedToGenerateCanonicalEntry)
}

tc := NewTrillianClient(httpReq.Context())
tc := NewTrillianClient(ctx)

resp := tc.addLeaf(leaf)
// this represents overall GRPC response state (not the results of insertion into the log)
if resp.status != codes.OK {
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("grpc error: %w", resp.err), trillianUnexpectedResult)
return nil, handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("grpc error: %w", resp.err), trillianUnexpectedResult)
}

// this represents the results of inserting the proposed leaf into the log; status is nil in success path
Expand All @@ -156,9 +153,11 @@ func CreateLogEntryHandler(params entries.CreateLogEntryParams) middleware.Respo
case int32(code.Code_OK):
case int32(code.Code_ALREADY_EXISTS), int32(code.Code_FAILED_PRECONDITION):
existingUUID := hex.EncodeToString(rfc6962.DefaultHasher.HashLeaf(leaf))
return handleRekorAPIError(params, http.StatusConflict, fmt.Errorf("grpc error: %v", insertionStatus.String()), fmt.Sprintf(entryAlreadyExists, existingUUID), "entryURL", getEntryURL(*httpReq.URL, existingUUID))
err := fmt.Errorf("grpc error: %v", insertionStatus.String())
return nil, handleRekorAPIError(params, http.StatusConflict, err, fmt.Sprintf(entryAlreadyExists, existingUUID), "entryURL", getEntryURL(*params.HTTPRequest.URL, existingUUID))
default:
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("grpc error: %v", insertionStatus.String()), trillianUnexpectedResult)
err := fmt.Errorf("grpc error: %v", insertionStatus.String())
return nil, handleRekorAPIError(params, http.StatusInternalServerError, err, trillianUnexpectedResult)
}
}

Expand Down Expand Up @@ -201,7 +200,7 @@ func CreateLogEntryHandler(params entries.CreateLogEntryParams) middleware.Respo

signature, err := signEntry(ctx, api.signer, logEntryAnon)
if err != nil {
return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("signing entry error: %v", err), signingError)
return nil, handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("signing entry error: %v", err), signingError)
}

logEntryAnon.Verification = &models.LogEntryAnonVerification{
Expand All @@ -211,6 +210,22 @@ func CreateLogEntryHandler(params entries.CreateLogEntryParams) middleware.Respo
logEntry := models.LogEntry{
uuid: logEntryAnon,
}
return logEntry, nil
}

// CreateLogEntryHandler creates new entry into log
func CreateLogEntryHandler(params entries.CreateLogEntryParams) middleware.Responder {
httpReq := params.HTTPRequest

logEntry, err := createLogEntry(params)
if err != nil {
return err
}

var uuid string
for location := range logEntry {
uuid = location
}

return entries.NewCreateLogEntryCreated().WithPayload(logEntry).WithLocation(getEntryURL(*httpReq.URL, uuid)).WithETag(uuid)
}
Expand Down
32 changes: 27 additions & 5 deletions pkg/api/timestamp.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ import (
"github.com/go-openapi/runtime/middleware"
"github.com/pkg/errors"
"github.com/sassoftware/relic/lib/pkcs9"
"github.com/sigstore/rekor/pkg/generated/restapi/operations/entries"
"github.com/sigstore/rekor/pkg/generated/restapi/operations/timestamp"
"github.com/sigstore/rekor/pkg/log"
rfc3161_v001 "github.com/sigstore/rekor/pkg/types/rfc3161/v0.0.1"
"github.com/sigstore/rekor/pkg/util"
)

Expand Down Expand Up @@ -62,15 +63,36 @@ func TimestampResponseHandler(params timestamp.GetTimestampResponseParams) middl
}

// Create response
ctx := params.HTTPRequest.Context()
httpReq := params.HTTPRequest
ctx := httpReq.Context()
resp, err := RequestFromRekor(ctx, *req)
if err != nil {
return handleRekorAPIError(params, http.StatusInternalServerError, err, failedToGenerateTimestampResponse)
}

// TODO: Upload to transparency log and add entry UUID to location header.
log.Logger.Errorf("generated OK")
return timestamp.NewGetTimestampResponseOK().WithPayload(ioutil.NopCloser(bytes.NewReader(resp)))
// Upload to transparency log and add entry UUID to location header.
cleReq := *httpReq
cleURL := entries.CreateLogEntryURL{}
cleReq.URL = cleURL.Must(cleURL.Build())
entryParams := entries.CreateLogEntryParams{
HTTPRequest: &cleReq,
ProposedEntry: rfc3161_v001.NewEntryFromBytes(resp),
}

// If middleware is returned, this indicates an error.
logEntry, middleware := createLogEntry(entryParams)
if middleware != nil {
return middleware
}

var uuid string
var newIndex int64
for location, entry := range logEntry {
uuid = location
newIndex = *entry.LogIndex
}

return timestamp.NewGetTimestampResponseCreated().WithPayload(ioutil.NopCloser(bytes.NewReader(resp))).WithLocation(getEntryURL(*cleReq.URL, uuid)).WithETag(uuid).WithIndex(newIndex)
}

func GetTimestampCertChainHandler(params timestamp.GetTimestampCertChainParams) middleware.Responder {
Expand Down
70 changes: 58 additions & 12 deletions pkg/generated/client/timestamp/get_timestamp_response_responses.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 34caf45

Please sign in to comment.