diff --git a/Makefile b/Makefile index ad3317a727b2c0999454158f26de56c1f29ab83b..6c40e6e8b6f000285c745541a5e92f4eb7d07212 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ .PHONY: all test clean lint gosec +NONGENSRCS := $(shell find cmd -name "*.go") $(shell find pkg -name "*.go"|grep -v "pkg/generated") pkg/generated/restapi/configure_rekor_server.go GENSRCS := $(shell find pkg/generated -name "*.go"|grep -v "configure_rekor_server.go") -SRCS := $(wildcard cmd/**/**.go) ${GENSRCS} $(shell find pkg -name "*.go"|grep -v "pkg/generated") pkg/generated/restapi/configure_rekor_server.go +SRCS := $(NONGENSRCS) ${GENSRCS} all: cli server @@ -15,10 +16,10 @@ lint: $(SRCS) gosec: $(SRCS) $(GOBIN)/gosec ./... -cli: $(SRCS) +cli: $(SRCS) openapi.yaml go build ./cmd/cli -server: $(SRCS) +server: $(SRCS) openapi.yaml go build ./cmd/server test: diff --git a/cmd/cli/app/log_info.go b/cmd/cli/app/log_info.go index d2132e2866dd2456e22424389649678dc102c13e..45734f05123bc657def201bbc7fbacda15669fe6 100644 --- a/cmd/cli/app/log_info.go +++ b/cmd/cli/app/log_info.go @@ -18,18 +18,27 @@ package app import ( "fmt" "net/url" + "os" "github.com/projectrekor/rekor/pkg/generated/client" + "github.com/projectrekor/rekor/pkg/generated/client/tlog" "github.com/projectrekor/rekor/pkg/log" "github.com/spf13/cobra" "github.com/spf13/viper" ) -// verifyCmd represents the get command +// logInfoCmd represents the current information about the transparency log var logInfoCmd = &cobra.Command{ Use: "loginfo", Short: "Rekor loginfo command", Long: `Prints info about the transparency log`, + PreRun: func(cmd *cobra.Command, args []string) { + if err := validateRekorServerURL(); err != nil { + log.Logger.Error(err) + _ = cmd.Help() + os.Exit(1) + } + }, Run: func(cmd *cobra.Command, args []string) { log := log.Logger rekorServer := viper.GetString("rekor_server") @@ -42,7 +51,9 @@ var logInfoCmd = &cobra.Command{ tc := client.DefaultTransportConfig().WithHost(url.Host) rc := client.NewHTTPClientWithConfig(nil, tc) - result, err := rc.Tlog.GetLogInfo(nil) + params := tlog.NewGetLogInfoParams() + + result, err := rc.Tlog.GetLogInfo(params) if err != nil { log.Fatal(err) } diff --git a/cmd/cli/app/log_proof.go b/cmd/cli/app/log_proof.go new file mode 100644 index 0000000000000000000000000000000000000000..edd732a6d0a32a205c63bd9505e318b9794e3627 --- /dev/null +++ b/cmd/cli/app/log_proof.go @@ -0,0 +1,105 @@ +/* +Copyright © 2020 Bob Callaway <bcallawa@redhat.com> + +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 app + +import ( + "fmt" + "net/url" + "os" + + "github.com/projectrekor/rekor/pkg/generated/client" + "github.com/projectrekor/rekor/pkg/generated/client/tlog" + "github.com/projectrekor/rekor/pkg/log" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// logProof represents the consistency proof +var logProofCmd = &cobra.Command{ + Use: "logproof", + Short: "Rekor logproof command", + Long: `Prints information required to compute the consistency proof of the transparency log`, + PreRun: func(cmd *cobra.Command, args []string) { + // these are bound here so that they are not overwritten by other commands + if err := viper.BindPFlags(cmd.Flags()); err != nil { + log.Logger.Fatal("Error initializing cmd line args: ", err) + } + if err := validateRekorServerURL(); err != nil { + log.Logger.Error(err) + _ = cmd.Help() + os.Exit(1) + } + if viper.GetUint64("first-size") > viper.GetUint64("last-size") { + log.Logger.Error("last-size must be >= to first-size") + os.Exit(1) + } + if viper.GetUint64("first-size") == 0 { + log.Logger.Error("first-size must be > 0") + os.Exit(1) + } + if viper.GetUint64("last-size") == 0 { + log.Logger.Error("last-size must be > 0") + os.Exit(1) + } + }, + Run: func(cmd *cobra.Command, args []string) { + log := log.Logger + rekorServer := viper.GetString("rekor_server") + + url, err := url.Parse(rekorServer) + if err != nil { + log.Fatal(err) + } + + tc := client.DefaultTransportConfig().WithHost(url.Host) + rc := client.NewHTTPClientWithConfig(nil, tc) + + firstSize := int64(viper.GetUint64("first-size")) + lastSize := int64(viper.GetUint64("last-size")) + + params := tlog.NewGetLogProofParams() + params.FirstSize = &firstSize + params.LastSize = lastSize + + result, err := rc.Tlog.GetLogProof(params) + if err != nil { + log.Fatal(err) + } + + consistencyProof := result.GetPayload() + fmt.Printf("Root Hash: %v\n", *consistencyProof.RootHash) + fmt.Printf("Hashes: [") + for i, hash := range consistencyProof.Hashes { + if i+1 == len(consistencyProof.Hashes) { + fmt.Printf("%v", hash) + } else { + fmt.Printf("%v,", hash) + } + } + fmt.Printf("]\n") + }, +} + +func init() { + logProofCmd.Flags().Uint64("first-size", 1, "the size of the log where the proof should begin") + logProofCmd.Flags().Uint64("last-size", 1, "the size of the log where the proof should end") + if err := logProofCmd.MarkFlagRequired("last-size"); err != nil { + fmt.Println(err) + os.Exit(1) + } + + rootCmd.AddCommand(logProofCmd) +} diff --git a/cmd/cli/app/root.go b/cmd/cli/app/root.go index 78c31f960f53c9bec2a07f86c4be43295011d7c7..b7b5cf8c2462216bc37635f4b14b2656728cb408 100644 --- a/cmd/cli/app/root.go +++ b/cmd/cli/app/root.go @@ -16,8 +16,11 @@ limitations under the License. package app import ( + "errors" "fmt" + "net/url" "os" + "strings" "github.com/spf13/cobra" @@ -88,3 +91,23 @@ func initConfig() { fmt.Println("Using config file:", viper.ConfigFileUsed()) } } + +func validateRekorServerURL() error { + rekorServerURL := viper.GetString("rekor_server") + if rekorServerURL != "" { + url, err := url.Parse(rekorServerURL) + if err != nil { + return fmt.Errorf("malformed rekor_server URL: %w", err) + } + if !url.IsAbs() { + return errors.New("rekor_server URL must be absolute") + } + lowercaseScheme := strings.ToLower(url.Scheme) + if lowercaseScheme != "http" && lowercaseScheme != "https" { + return errors.New("rekor_server must be a valid HTTP or HTTPS URL") + } + } else { + return errors.New("rekor_server must be specified") + } + return nil +} diff --git a/cmd/cli/app/upload.go b/cmd/cli/app/upload.go index 124b40d232c598afe90e2d8b42a318305fc1ba43..82b8ea32749443b413b121c57717ff5c99f4bb47 100644 --- a/cmd/cli/app/upload.go +++ b/cmd/cli/app/upload.go @@ -21,6 +21,7 @@ import ( "encoding/json" "io/ioutil" "net/http" + "os" "path/filepath" "time" @@ -47,6 +48,17 @@ var uploadCmd = &cobra.Command{ Short: "Upload a rekord file", Long: `This command takes the public key, signature and URL of the release artifact and uploads it to the rekor server.`, + PreRun: func(cmd *cobra.Command, args []string) { + // these are bound here so that they are not overwritten by other commands + if err := viper.BindPFlags(cmd.Flags()); err != nil { + log.Logger.Fatal("Error initializing cmd line args: ", err) + } + if err := validateRekorServerURL(); err != nil { + log.Logger.Error(err) + _ = cmd.Help() + os.Exit(1) + } + }, Run: func(cmd *cobra.Command, args []string) { log := log.Logger rekorServerURL := viper.GetString("rekor_server") + "/api/v1/add" diff --git a/cmd/cli/app/verify.go b/cmd/cli/app/verify.go index 4c1c0936fcc8967be63e73f00af4e928c11942da..35d28b4a34cbd0991895f404d7960fdb99183a9a 100644 --- a/cmd/cli/app/verify.go +++ b/cmd/cli/app/verify.go @@ -35,6 +35,17 @@ var verifyCmd = &cobra.Command{ Use: "verify", Short: "Rekor verify command", Long: `Verifies a signature and checks that it exists in the transparency log`, + PreRun: func(cmd *cobra.Command, args []string) { + // these are bound here so that they are not overwritten by other commands + if err := viper.BindPFlags(cmd.Flags()); err != nil { + log.Logger.Fatal("Error initializing cmd line args: ", err) + } + if err := validateRekorServerURL(); err != nil { + log.Logger.Error(err) + _ = cmd.Help() + os.Exit(1) + } + }, Run: func(cmd *cobra.Command, args []string) { log := log.Logger rekorServer := viper.GetString("rekor_server") diff --git a/openapi.yaml b/openapi.yaml index a2aa6bbfa209787ec975a934983bbefd61f24d03..daf0530f889f6917f18bae0a73bb89a6dde72366 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -36,22 +36,24 @@ paths: - in: query name: firstSize type: integer - default: 0 - minimum: 0 + default: 1 + minimum: 1 description: > - The size of the tree that you wish to prove consistency from (0 means the beginning of the log) - Defaults to 0 if not specified + The size of the tree that you wish to prove consistency from (1 means the beginning of the log) + Defaults to 1 if not specified - in: query name: lastSize type: integer required: true - minimum: 0 + minimum: 1 description: The size of the tree that you wish to prove consistency to responses: 200: description: All hashes required to compute the consistency proof schema: $ref: '#/definitions/ConsistencyProof' + 400: + $ref: '#/responses/BadContent' default: $ref: '#/responses/InternalServerError' @@ -93,6 +95,7 @@ paths: name: logIndex type: integer required: true + minimum: 1 description: specifies the index of the entry in the transparency log to be retrieved responses: 200: @@ -245,6 +248,7 @@ definitions: properties: logIndex: type: integer + minimum: 1 signature: type: object properties: @@ -285,6 +289,7 @@ definitions: items: type: integer minItems: 1 + minimum: 1 entries: type: array items: @@ -297,9 +302,11 @@ definitions: rootHash: type: string description: The current hash value stored at the root of the merkle tree + pattern: '^[0-9a-fA-F]{64}$' treeSize: type: integer description: The current number of nodes in the merkle tree + minimum: 1 required: - rootHash - treeSize @@ -307,20 +314,18 @@ definitions: ConsistencyProof: type: object properties: - firstRootHash: - type: string - description: The hash value stored at the root of the merkle tree at the first size specified - lastRootHash: + rootHash: type: string - description: The hash value stored at the root of the merkle tree at the last size specified + description: The hash value stored at the root of the merkle tree at time the proof was generated + pattern: '^[0-9a-fA-F]{64}$' hashes: type: array items: type: string + description: SHA256 hash value expressed in hexadecimal format pattern: '^[0-9a-fA-F]{64}$' required: - - firstRootHash - - lastRootHash + - rootHash - hashes InclusionProof: @@ -329,13 +334,15 @@ definitions: logIndex: type: integer description: The index of the entry in the transparency log + minimum: 1 rootHash: - description: The hash value stored at the root of the merkle tree + description: The hash value stored at the root of the merkle tree at the time the proof was generated type: string pattern: '^[0-9a-fA-F]{64}$' treeSize: type: integer description: The size of the merkle tree at the time the inclusion proof was generated + minimum: 1 hashes: description: A list of hashes required to compute the inclusion proof, sorted in order from leaf to root type: array diff --git a/pkg/api/tlog.go b/pkg/api/tlog.go index 7916510bf4b079320db87085033d6fbf9aa5ae47..777ce1fe1f63da5fff000b3852d9800d4045f887 100644 --- a/pkg/api/tlog.go +++ b/pkg/api/tlog.go @@ -22,7 +22,7 @@ import ( "github.com/projectrekor/rekor/pkg/generated/models" "github.com/go-openapi/runtime/middleware" - ttypes "github.com/google/trillian/types" + "github.com/google/trillian/types" "github.com/projectrekor/rekor/pkg/generated/restapi/operations/tlog" ) @@ -36,7 +36,7 @@ func GetLogInfoHandler(params tlog.GetLogInfoParams) middleware.Responder { return tlog.NewGetLogInfoDefault(http.StatusInternalServerError).WithPayload(errorMsg("title", "type", err.Error(), http.StatusInternalServerError)) } - var root ttypes.LogRootV1 + var root types.LogRootV1 if err := root.UnmarshalBinary(resp.getLatestResult.SignedLogRoot.LogRoot); err != nil { return tlog.NewGetLogInfoDefault(http.StatusInternalServerError).WithPayload(errorMsg("title", "type", err.Error(), http.StatusInternalServerError)) } @@ -52,5 +52,37 @@ func GetLogInfoHandler(params tlog.GetLogInfoParams) middleware.Responder { } func GetLogProofHandler(params tlog.GetLogProofParams) middleware.Responder { - return middleware.NotImplemented("getLogProof not yet implemented") + if *params.FirstSize > params.LastSize { + return tlog.NewGetLogProofBadRequest().WithPayload(errorMsg("title", "type", "firstSize must be greater than or equal to lastSize", http.StatusBadRequest)) + } + api, _ := NewAPI() + + server := serverInstance(api.logClient, api.tLogID) + + cpResp, err := server.getConsistencyProof(api.tLogID, *params.FirstSize, params.LastSize) + if err != nil { + return tlog.NewGetLogProofDefault(http.StatusInternalServerError).WithPayload(errorMsg("title", "type", err.Error(), http.StatusInternalServerError)) + } + result := cpResp.getConsistencyProofResult + + var root types.LogRootV1 + if err := root.UnmarshalBinary(result.SignedLogRoot.LogRoot); err != nil { + return tlog.NewGetLogProofDefault(http.StatusInternalServerError).WithPayload(errorMsg("title", "type", err.Error(), http.StatusInternalServerError)) + } + + hashString := hex.EncodeToString(root.RootHash) + proofHashes := []string{} + + if proof := result.GetProof(); proof != nil { + for _, hash := range proof.Hashes { + proofHashes = append(proofHashes, hex.EncodeToString(hash)) + } + } + + consistencyProof := models.ConsistencyProof{ + RootHash: &hashString, + Hashes: proofHashes, + } + + return tlog.NewGetLogProofOK().WithPayload(&consistencyProof) } diff --git a/pkg/api/trillian_client.go b/pkg/api/trillian_client.go index 30a836422cc1e80ee4ef142085352a34a5d14962..2ce71bc57c6ce2c877fe521b0034d4f777b78a6c 100644 --- a/pkg/api/trillian_client.go +++ b/pkg/api/trillian_client.go @@ -41,11 +41,12 @@ type trillianclient struct { } type Response struct { - status codes.Code - getLeafResult *trillian.GetLeavesByHashResponse - getProofResult *trillian.GetInclusionProofByHashResponse - getLeafByIndexResult *trillian.GetLeavesByIndexResponse - getLatestResult *trillian.GetLatestSignedLogRootResponse + status codes.Code + getLeafResult *trillian.GetLeavesByHashResponse + getProofResult *trillian.GetInclusionProofByHashResponse + getLeafByIndexResult *trillian.GetLeavesByIndexResponse + getLatestResult *trillian.GetLatestSignedLogRootResponse + getConsistencyProofResult *trillian.GetConsistencyProofResponse } func serverInstance(client trillian.TrillianLogClient, tLogID int64) *trillianclient { @@ -174,6 +175,9 @@ func (s *trillianclient) getLatest(tLogID int64, leafSizeInt int64) (*Response, LogId: tLogID, FirstTreeSize: leafSizeInt, }) + if err != nil { + return nil, err + } return &Response{ status: status.Code(err), @@ -181,6 +185,27 @@ func (s *trillianclient) getLatest(tLogID int64, leafSizeInt int64) (*Response, }, nil } +func (s *trillianclient) getConsistencyProof(tLogID int64, firstSize, lastSize int64) (*Response, error) { + + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + + resp, err := s.client.GetConsistencyProof(ctx, + &trillian.GetConsistencyProofRequest{ + LogId: tLogID, + FirstTreeSize: firstSize, + SecondTreeSize: lastSize, + }) + if err != nil { + return nil, err + } + + return &Response{ + status: status.Code(err), + getConsistencyProofResult: resp, + }, nil +} + func createAndInitTree(ctx context.Context, adminClient trillian.TrillianAdminClient, logClient trillian.TrillianLogClient) (*trillian.Tree, error) { // First look for and use an existing tree trees, err := adminClient.ListTrees(ctx, &trillian.ListTreesRequest{}) diff --git a/pkg/generated/client/tlog/get_log_proof_parameters.go b/pkg/generated/client/tlog/get_log_proof_parameters.go index 4e97a443bf81892958c7aa369de56fc16d84a670..736e43475d980c588b3fb71b9925eda869ea45e3 100644 --- a/pkg/generated/client/tlog/get_log_proof_parameters.go +++ b/pkg/generated/client/tlog/get_log_proof_parameters.go @@ -21,7 +21,7 @@ import ( // with the default values initialized. func NewGetLogProofParams() *GetLogProofParams { var ( - firstSizeDefault = int64(0) + firstSizeDefault = int64(1) ) return &GetLogProofParams{ FirstSize: &firstSizeDefault, @@ -34,7 +34,7 @@ func NewGetLogProofParams() *GetLogProofParams { // with the default values initialized, and the ability to set a timeout on a request func NewGetLogProofParamsWithTimeout(timeout time.Duration) *GetLogProofParams { var ( - firstSizeDefault = int64(0) + firstSizeDefault = int64(1) ) return &GetLogProofParams{ FirstSize: &firstSizeDefault, @@ -47,7 +47,7 @@ func NewGetLogProofParamsWithTimeout(timeout time.Duration) *GetLogProofParams { // with the default values initialized, and the ability to set a context for a request func NewGetLogProofParamsWithContext(ctx context.Context) *GetLogProofParams { var ( - firstSizeDefault = int64(0) + firstSizeDefault = int64(1) ) return &GetLogProofParams{ FirstSize: &firstSizeDefault, @@ -60,7 +60,7 @@ func NewGetLogProofParamsWithContext(ctx context.Context) *GetLogProofParams { // with the default values initialized, and the ability to set a custom HTTPClient for a request func NewGetLogProofParamsWithHTTPClient(client *http.Client) *GetLogProofParams { var ( - firstSizeDefault = int64(0) + firstSizeDefault = int64(1) ) return &GetLogProofParams{ FirstSize: &firstSizeDefault, @@ -74,7 +74,7 @@ for the get log proof operation typically these are written to a http.Request type GetLogProofParams struct { /*FirstSize - The size of the tree that you wish to prove consistency from (0 means the beginning of the log) Defaults to 0 if not specified + The size of the tree that you wish to prove consistency from (1 means the beginning of the log) Defaults to 1 if not specified */ diff --git a/pkg/generated/client/tlog/get_log_proof_responses.go b/pkg/generated/client/tlog/get_log_proof_responses.go index d99b1d82e1ce9ebfebbe52f8e4ba552a0633e4ea..d542d739e987a2eed71dc089a9899872e4cf15ed 100644 --- a/pkg/generated/client/tlog/get_log_proof_responses.go +++ b/pkg/generated/client/tlog/get_log_proof_responses.go @@ -29,6 +29,12 @@ func (o *GetLogProofReader) ReadResponse(response runtime.ClientResponse, consum return nil, err } return result, nil + case 400: + result := NewGetLogProofBadRequest() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result default: result := NewGetLogProofDefault(response.Code()) if err := result.readResponse(response, consumer, o.formats); err != nil { @@ -74,6 +80,39 @@ func (o *GetLogProofOK) readResponse(response runtime.ClientResponse, consumer r return nil } +// NewGetLogProofBadRequest creates a GetLogProofBadRequest with default headers values +func NewGetLogProofBadRequest() *GetLogProofBadRequest { + return &GetLogProofBadRequest{} +} + +/*GetLogProofBadRequest handles this case with default header values. + +The content supplied to the server was invalid +*/ +type GetLogProofBadRequest struct { + Payload *models.Error +} + +func (o *GetLogProofBadRequest) Error() string { + return fmt.Sprintf("[GET /api/v1/log/proof][%d] getLogProofBadRequest %+v", 400, o.Payload) +} + +func (o *GetLogProofBadRequest) GetPayload() *models.Error { + return o.Payload +} + +func (o *GetLogProofBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + o.Payload = new(models.Error) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + // NewGetLogProofDefault creates a GetLogProofDefault with default headers values func NewGetLogProofDefault(code int) *GetLogProofDefault { return &GetLogProofDefault{ diff --git a/pkg/generated/models/consistency_proof.go b/pkg/generated/models/consistency_proof.go index 2da0f59e3e0a90e6377bb1d847da07cb3f548852..5b50e276fbe32905c7c9e697fa28a61b3a62474c 100644 --- a/pkg/generated/models/consistency_proof.go +++ b/pkg/generated/models/consistency_proof.go @@ -19,32 +19,25 @@ import ( // swagger:model ConsistencyProof type ConsistencyProof struct { - // The hash value stored at the root of the merkle tree at the first size specified - // Required: true - FirstRootHash *string `json:"firstRootHash"` - // hashes // Required: true Hashes []string `json:"hashes"` - // The hash value stored at the root of the merkle tree at the last size specified + // The hash value stored at the root of the merkle tree at time the proof was generated // Required: true - LastRootHash *string `json:"lastRootHash"` + // Pattern: ^[0-9a-fA-F]{64}$ + RootHash *string `json:"rootHash"` } // Validate validates this consistency proof func (m *ConsistencyProof) Validate(formats strfmt.Registry) error { var res []error - if err := m.validateFirstRootHash(formats); err != nil { - res = append(res, err) - } - if err := m.validateHashes(formats); err != nil { res = append(res, err) } - if err := m.validateLastRootHash(formats); err != nil { + if err := m.validateRootHash(formats); err != nil { res = append(res, err) } @@ -54,15 +47,6 @@ func (m *ConsistencyProof) Validate(formats strfmt.Registry) error { return nil } -func (m *ConsistencyProof) validateFirstRootHash(formats strfmt.Registry) error { - - if err := validate.Required("firstRootHash", "body", m.FirstRootHash); err != nil { - return err - } - - return nil -} - func (m *ConsistencyProof) validateHashes(formats strfmt.Registry) error { if err := validate.Required("hashes", "body", m.Hashes); err != nil { @@ -80,9 +64,13 @@ func (m *ConsistencyProof) validateHashes(formats strfmt.Registry) error { return nil } -func (m *ConsistencyProof) validateLastRootHash(formats strfmt.Registry) error { +func (m *ConsistencyProof) validateRootHash(formats strfmt.Registry) error { + + if err := validate.Required("rootHash", "body", m.RootHash); err != nil { + return err + } - if err := validate.Required("lastRootHash", "body", m.LastRootHash); err != nil { + if err := validate.Pattern("rootHash", "body", string(*m.RootHash), `^[0-9a-fA-F]{64}$`); err != nil { return err } diff --git a/pkg/generated/models/inclusion_proof.go b/pkg/generated/models/inclusion_proof.go index 061f59d3f3d6210937189fc57a1f5c9eb2595503..66c8e8ee0f399231978eb219bb06b50f98a6f36a 100644 --- a/pkg/generated/models/inclusion_proof.go +++ b/pkg/generated/models/inclusion_proof.go @@ -25,15 +25,17 @@ type InclusionProof struct { // The index of the entry in the transparency log // Required: true + // Minimum: 1 LogIndex *int64 `json:"logIndex"` - // The hash value stored at the root of the merkle tree + // The hash value stored at the root of the merkle tree at the time the proof was generated // Required: true // Pattern: ^[0-9a-fA-F]{64}$ RootHash *string `json:"rootHash"` // The size of the merkle tree at the time the inclusion proof was generated // Required: true + // Minimum: 1 TreeSize *int64 `json:"treeSize"` } @@ -86,6 +88,10 @@ func (m *InclusionProof) validateLogIndex(formats strfmt.Registry) error { return err } + if err := validate.MinimumInt("logIndex", "body", int64(*m.LogIndex), 1, false); err != nil { + return err + } + return nil } @@ -108,6 +114,10 @@ func (m *InclusionProof) validateTreeSize(formats strfmt.Registry) error { return err } + if err := validate.MinimumInt("treeSize", "body", int64(*m.TreeSize), 1, false); err != nil { + return err + } + return nil } diff --git a/pkg/generated/models/log_entry.go b/pkg/generated/models/log_entry.go index acb8df58e82bfeec2207b5553ced16e561072520..9808746306d95e1d4f238a605a9d9a1b027bf8f9 100644 --- a/pkg/generated/models/log_entry.go +++ b/pkg/generated/models/log_entry.go @@ -50,6 +50,7 @@ type LogEntryAnon struct { // log index // Required: true + // Minimum: 1 LogIndex *int64 `json:"logIndex"` // signature @@ -90,6 +91,10 @@ func (m *LogEntryAnon) validateLogIndex(formats strfmt.Registry) error { return err } + if err := validate.MinimumInt("logIndex", "body", int64(*m.LogIndex), 1, false); err != nil { + return err + } + return nil } diff --git a/pkg/generated/models/log_info.go b/pkg/generated/models/log_info.go index 9ad8adf5855dcb5c40eb27faffab95e88e41992c..12a6b08d3686f8e945b75e8d881c59dc2e4087da 100644 --- a/pkg/generated/models/log_info.go +++ b/pkg/generated/models/log_info.go @@ -19,10 +19,12 @@ type LogInfo struct { // The current hash value stored at the root of the merkle tree // Required: true + // Pattern: ^[0-9a-fA-F]{64}$ RootHash *string `json:"rootHash"` // The current number of nodes in the merkle tree // Required: true + // Minimum: 1 TreeSize *int64 `json:"treeSize"` } @@ -50,6 +52,10 @@ func (m *LogInfo) validateRootHash(formats strfmt.Registry) error { return err } + if err := validate.Pattern("rootHash", "body", string(*m.RootHash), `^[0-9a-fA-F]{64}$`); err != nil { + return err + } + return nil } @@ -59,6 +65,10 @@ func (m *LogInfo) validateTreeSize(formats strfmt.Registry) error { return err } + if err := validate.MinimumInt("treeSize", "body", int64(*m.TreeSize), 1, false); err != nil { + return err + } + return nil } diff --git a/pkg/generated/models/search_log_query.go b/pkg/generated/models/search_log_query.go index 2264b19023a38316a5e5c683f8318f0b4e08a7a7..bf31437244997faa058e292c5caa1c401cd84fab 100644 --- a/pkg/generated/models/search_log_query.go +++ b/pkg/generated/models/search_log_query.go @@ -11,6 +11,7 @@ import ( "github.com/go-openapi/errors" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" + "github.com/go-openapi/validate" ) // SearchLogQuery search log query @@ -91,6 +92,10 @@ func (m *SearchLogQuery) validateLogIndexes(formats strfmt.Registry) error { for i := 0; i < len(m.LogIndexes); i++ { + if err := validate.MinimumInt("logIndexes"+"."+strconv.Itoa(i), "body", int64(m.LogIndexes[i]), 1, false); err != nil { + return err + } + } return nil diff --git a/pkg/generated/restapi/embedded_spec.go b/pkg/generated/restapi/embedded_spec.go index 8156b904884504c6418db40a19ada705d748be85..c82cca5f60eaa6d9a311e0c145877bc6142b8cc7 100644 --- a/pkg/generated/restapi/embedded_spec.go +++ b/pkg/generated/restapi/embedded_spec.go @@ -61,6 +61,7 @@ func init() { "operationId": "getLogEntryByIndex", "parameters": [ { + "minimum": 1, "type": "integer", "description": "specifies the index of the entry in the transparency log to be retrieved", "name": "logIndex", @@ -230,13 +231,15 @@ func init() { "operationId": "getLogProof", "parameters": [ { + "minimum": 1, "type": "integer", - "default": 0, - "description": "The size of the tree that you wish to prove consistency from (0 means the beginning of the log) Defaults to 0 if not specified\n", + "default": 1, + "description": "The size of the tree that you wish to prove consistency from (1 means the beginning of the log) Defaults to 1 if not specified\n", "name": "firstSize", "in": "query" }, { + "minimum": 1, "type": "integer", "description": "The size of the tree that you wish to prove consistency to", "name": "lastSize", @@ -251,6 +254,9 @@ func init() { "$ref": "#/definitions/ConsistencyProof" } }, + "400": { + "$ref": "#/responses/BadContent" + }, "default": { "$ref": "#/responses/InternalServerError" } @@ -262,25 +268,22 @@ func init() { "ConsistencyProof": { "type": "object", "required": [ - "firstRootHash", - "lastRootHash", + "rootHash", "hashes" ], "properties": { - "firstRootHash": { - "description": "The hash value stored at the root of the merkle tree at the first size specified", - "type": "string" - }, "hashes": { "type": "array", "items": { + "description": "SHA256 hash value expressed in hexadecimal format", "type": "string", "pattern": "^[0-9a-fA-F]{64}$" } }, - "lastRootHash": { - "description": "The hash value stored at the root of the merkle tree at the last size specified", - "type": "string" + "rootHash": { + "description": "The hash value stored at the root of the merkle tree at time the proof was generated", + "type": "string", + "pattern": "^[0-9a-fA-F]{64}$" } } }, @@ -326,16 +329,18 @@ func init() { }, "logIndex": { "description": "The index of the entry in the transparency log", - "type": "integer" + "type": "integer", + "minimum": 1 }, "rootHash": { - "description": "The hash value stored at the root of the merkle tree", + "description": "The hash value stored at the root of the merkle tree at the time the proof was generated", "type": "string", "pattern": "^[0-9a-fA-F]{64}$" }, "treeSize": { "description": "The size of the merkle tree at the time the inclusion proof was generated", - "type": "integer" + "type": "integer", + "minimum": 1 } } }, @@ -356,7 +361,8 @@ func init() { } }, "logIndex": { - "type": "integer" + "type": "integer", + "minimum": 1 }, "signature": { "type": "object", @@ -395,11 +401,13 @@ func init() { "properties": { "rootHash": { "description": "The current hash value stored at the root of the merkle tree", - "type": "string" + "type": "string", + "pattern": "^[0-9a-fA-F]{64}$" }, "treeSize": { "description": "The current number of nodes in the merkle tree", - "type": "integer" + "type": "integer", + "minimum": 1 } } }, @@ -484,6 +492,7 @@ func init() { "type": "array", "items": { "type": "integer", + "minimum": 1, "minItems": 1 } } @@ -565,6 +574,7 @@ func init() { "operationId": "getLogEntryByIndex", "parameters": [ { + "minimum": 1, "type": "integer", "description": "specifies the index of the entry in the transparency log to be retrieved", "name": "logIndex", @@ -761,15 +771,15 @@ func init() { "operationId": "getLogProof", "parameters": [ { - "minimum": 0, + "minimum": 1, "type": "integer", - "default": 0, - "description": "The size of the tree that you wish to prove consistency from (0 means the beginning of the log) Defaults to 0 if not specified\n", + "default": 1, + "description": "The size of the tree that you wish to prove consistency from (1 means the beginning of the log) Defaults to 1 if not specified\n", "name": "firstSize", "in": "query" }, { - "minimum": 0, + "minimum": 1, "type": "integer", "description": "The size of the tree that you wish to prove consistency to", "name": "lastSize", @@ -784,6 +794,12 @@ func init() { "$ref": "#/definitions/ConsistencyProof" } }, + "400": { + "description": "The content supplied to the server was invalid", + "schema": { + "$ref": "#/definitions/Error" + } + }, "default": { "description": "There was an internal error in the server while processing the request", "schema": { @@ -798,25 +814,22 @@ func init() { "ConsistencyProof": { "type": "object", "required": [ - "firstRootHash", - "lastRootHash", + "rootHash", "hashes" ], "properties": { - "firstRootHash": { - "description": "The hash value stored at the root of the merkle tree at the first size specified", - "type": "string" - }, "hashes": { "type": "array", "items": { + "description": "SHA256 hash value expressed in hexadecimal format", "type": "string", "pattern": "^[0-9a-fA-F]{64}$" } }, - "lastRootHash": { - "description": "The hash value stored at the root of the merkle tree at the last size specified", - "type": "string" + "rootHash": { + "description": "The hash value stored at the root of the merkle tree at time the proof was generated", + "type": "string", + "pattern": "^[0-9a-fA-F]{64}$" } } }, @@ -862,16 +875,18 @@ func init() { }, "logIndex": { "description": "The index of the entry in the transparency log", - "type": "integer" + "type": "integer", + "minimum": 1 }, "rootHash": { - "description": "The hash value stored at the root of the merkle tree", + "description": "The hash value stored at the root of the merkle tree at the time the proof was generated", "type": "string", "pattern": "^[0-9a-fA-F]{64}$" }, "treeSize": { "description": "The size of the merkle tree at the time the inclusion proof was generated", - "type": "integer" + "type": "integer", + "minimum": 1 } } }, @@ -896,7 +911,8 @@ func init() { } }, "logIndex": { - "type": "integer" + "type": "integer", + "minimum": 1 }, "signature": { "type": "object", @@ -955,11 +971,13 @@ func init() { "properties": { "rootHash": { "description": "The current hash value stored at the root of the merkle tree", - "type": "string" + "type": "string", + "pattern": "^[0-9a-fA-F]{64}$" }, "treeSize": { "description": "The current number of nodes in the merkle tree", - "type": "integer" + "type": "integer", + "minimum": 1 } } }, @@ -1114,6 +1132,7 @@ func init() { "type": "array", "items": { "type": "integer", + "minimum": 1, "minItems": 1 } } diff --git a/pkg/generated/restapi/operations/entries/get_log_entry_by_index_parameters.go b/pkg/generated/restapi/operations/entries/get_log_entry_by_index_parameters.go index 266d5e66170a9de0edd2e886699e00822e7879d4..bd2b13ac78f3419125dc0bb14f039111b5da1f2a 100644 --- a/pkg/generated/restapi/operations/entries/get_log_entry_by_index_parameters.go +++ b/pkg/generated/restapi/operations/entries/get_log_entry_by_index_parameters.go @@ -34,6 +34,7 @@ type GetLogEntryByIndexParams struct { /*specifies the index of the entry in the transparency log to be retrieved Required: true + Minimum: 1 In: query */ LogIndex int64 @@ -83,5 +84,19 @@ func (o *GetLogEntryByIndexParams) bindLogIndex(rawData []string, hasKey bool, f } o.LogIndex = value + if err := o.validateLogIndex(formats); err != nil { + return err + } + + return nil +} + +// validateLogIndex carries on validations for parameter LogIndex +func (o *GetLogEntryByIndexParams) validateLogIndex(formats strfmt.Registry) error { + + if err := validate.MinimumInt("logIndex", "query", int64(o.LogIndex), 1, false); err != nil { + return err + } + return nil } diff --git a/pkg/generated/restapi/operations/tlog/get_log_proof_parameters.go b/pkg/generated/restapi/operations/tlog/get_log_proof_parameters.go index ddd46718264c43ad880623b7acec7d70f6bce096..3ec8406ee8010062395a937f5843f4e40c47e3ee 100644 --- a/pkg/generated/restapi/operations/tlog/get_log_proof_parameters.go +++ b/pkg/generated/restapi/operations/tlog/get_log_proof_parameters.go @@ -23,7 +23,7 @@ func NewGetLogProofParams() GetLogProofParams { var ( // initialize parameters with default values - firstSizeDefault = int64(0) + firstSizeDefault = int64(1) ) return GetLogProofParams{ @@ -40,16 +40,16 @@ type GetLogProofParams struct { // HTTP Request Object HTTPRequest *http.Request `json:"-"` - /*The size of the tree that you wish to prove consistency from (0 means the beginning of the log) Defaults to 0 if not specified + /*The size of the tree that you wish to prove consistency from (1 means the beginning of the log) Defaults to 1 if not specified - Minimum: 0 + Minimum: 1 In: query - Default: 0 + Default: 1 */ FirstSize *int64 /*The size of the tree that you wish to prove consistency to Required: true - Minimum: 0 + Minimum: 1 In: query */ LastSize int64 @@ -112,7 +112,7 @@ func (o *GetLogProofParams) bindFirstSize(rawData []string, hasKey bool, formats // validateFirstSize carries on validations for parameter FirstSize func (o *GetLogProofParams) validateFirstSize(formats strfmt.Registry) error { - if err := validate.MinimumInt("firstSize", "query", int64(*o.FirstSize), 0, false); err != nil { + if err := validate.MinimumInt("firstSize", "query", int64(*o.FirstSize), 1, false); err != nil { return err } @@ -151,7 +151,7 @@ func (o *GetLogProofParams) bindLastSize(rawData []string, hasKey bool, formats // validateLastSize carries on validations for parameter LastSize func (o *GetLogProofParams) validateLastSize(formats strfmt.Registry) error { - if err := validate.MinimumInt("lastSize", "query", int64(o.LastSize), 0, false); err != nil { + if err := validate.MinimumInt("lastSize", "query", int64(o.LastSize), 1, false); err != nil { return err } diff --git a/pkg/generated/restapi/operations/tlog/get_log_proof_responses.go b/pkg/generated/restapi/operations/tlog/get_log_proof_responses.go index 1e842ea43fab581b50e5d5b337cc636073e00683..8f50202070861204e5002e85cfc635d8f9c4964d 100644 --- a/pkg/generated/restapi/operations/tlog/get_log_proof_responses.go +++ b/pkg/generated/restapi/operations/tlog/get_log_proof_responses.go @@ -57,6 +57,50 @@ func (o *GetLogProofOK) WriteResponse(rw http.ResponseWriter, producer runtime.P } } +// GetLogProofBadRequestCode is the HTTP code returned for type GetLogProofBadRequest +const GetLogProofBadRequestCode int = 400 + +/*GetLogProofBadRequest The content supplied to the server was invalid + +swagger:response getLogProofBadRequest +*/ +type GetLogProofBadRequest struct { + + /* + In: Body + */ + Payload *models.Error `json:"body,omitempty"` +} + +// NewGetLogProofBadRequest creates GetLogProofBadRequest with default headers values +func NewGetLogProofBadRequest() *GetLogProofBadRequest { + + return &GetLogProofBadRequest{} +} + +// WithPayload adds the payload to the get log proof bad request response +func (o *GetLogProofBadRequest) WithPayload(payload *models.Error) *GetLogProofBadRequest { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get log proof bad request response +func (o *GetLogProofBadRequest) SetPayload(payload *models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetLogProofBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(400) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + /*GetLogProofDefault There was an internal error in the server while processing the request swagger:response getLogProofDefault