Skip to content

Commit

Permalink
Add bounds on number of elements in api/v1/log/entries/retrieve (#1011)
Browse files Browse the repository at this point in the history
* Add bounds on number of elements in api/v1/log/entries/retrieve

Currently set the limit to 10 entries, we can increase it if users request it.

Signed-off-by: Priya Wadhwa <priya@chainguard.dev>

* Add maxItems:10 for SearchLogQuery

Signed-off-by: Priya Wadhwa <priya@chainguard.dev>

Signed-off-by: Priya Wadhwa <priya@chainguard.dev>
  • Loading branch information
priyawadhwa committed Aug 29, 2022
1 parent 568e31a commit ae429bb
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 5 deletions.
7 changes: 5 additions & 2 deletions openapi.yaml
Expand Up @@ -519,21 +519,24 @@ definitions:
properties:
entryUUIDs:
type: array
minItems: 1
maxItems: 10
items:
type: string
minItems: 1
pattern: '^([0-9a-fA-F]{64}|[0-9a-fA-F]{80})$'
logIndexes:
type: array
minItems: 1
maxItems: 10
items:
type: integer
minimum: 0
entries:
type: array
minItems: 1
maxItems: 10
items:
$ref: '#/definitions/ProposedEntry'
minItems: 1

LogInfo:
type: object
Expand Down
9 changes: 9 additions & 0 deletions pkg/api/entries.go
Expand Up @@ -46,6 +46,10 @@ import (
"github.com/sigstore/sigstore/pkg/signature/options"
)

const (
maxSearchQueries = 10
)

func signEntry(ctx context.Context, signer signature.Signer, entry models.LogEntryAnon) ([]byte, error) {
payload, err := entry.MarshalBinary()
if err != nil {
Expand Down Expand Up @@ -316,6 +320,11 @@ func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Respo
resultPayload := []models.LogEntry{}
tc := NewTrillianClient(httpReqCtx)

totalQueries := len(params.Entry.EntryUUIDs) + len(params.Entry.Entries()) + len(params.Entry.LogIndexes)
if totalQueries > maxSearchQueries {
return handleRekorAPIError(params, http.StatusUnprocessableEntity, fmt.Errorf(maxSearchQueryLimit, maxSearchQueries), fmt.Sprintf(maxSearchQueryLimit, maxSearchQueries))
}

if len(params.Entry.EntryUUIDs) > 0 || len(params.Entry.Entries()) > 0 {
g, _ := errgroup.WithContext(httpReqCtx)

Expand Down
1 change: 1 addition & 0 deletions pkg/api/error.go
Expand Up @@ -48,6 +48,7 @@ const (
sthGenerateError = "Error generating signed tree head"
unsupportedPKIFormat = "The PKI format requested is not supported by this server"
unexpectedInactiveShardError = "Unexpected error communicating with inactive shard"
maxSearchQueryLimit = "more than max allowed %d entries in request"
)

func errorMsg(message string, code int) *models.Error {
Expand Down
27 changes: 27 additions & 0 deletions pkg/generated/models/search_log_query.go

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

14 changes: 11 additions & 3 deletions pkg/generated/restapi/embedded_spec.go

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

51 changes: 51 additions & 0 deletions tests/e2e_test.go
Expand Up @@ -1168,3 +1168,54 @@ func TestHostnameInSTH(t *testing.T) {
t.Errorf("logInfo contains rekor.sigstore.dev which should not be set by default")
}
}

func TestSearchQueryLimit(t *testing.T) {
tests := []struct {
description string
limit int
shouldErr bool
}{
{
description: "request 6 entries",
limit: 6,
}, {
description: "request 10 entries",
limit: 10,
}, {
description: "request more than max",
limit: 12,
shouldErr: true,
},
}

for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
b := bytes.NewReader(getBody(t, test.limit))
resp, err := http.Post("http://localhost:3000/api/v1/log/entries/retrieve", "application/json", b)
if err != nil {
t.Fatal(err)
}
c, _ := ioutil.ReadAll(resp.Body)
t.Log(string(c))
if resp.StatusCode != 200 && !test.shouldErr {
t.Fatalf("expected test to pass but it failed")
}
if resp.StatusCode != 422 && test.shouldErr {
t.Fatal("expected test to fail but it passed")
}
if test.shouldErr && !strings.Contains(string(c), "logIndexes in body should have at most 10 items") {
t.Fatal("expected max limit error but didn't get it")
}
})
}
}

func getBody(t *testing.T, limit int) []byte {
t.Helper()
s := fmt.Sprintf("{\"logIndexes\": [%d", limit)
for i := 1; i < limit; i++ {
s = fmt.Sprintf("%s, %d", s, i)
}
s += "]}"
return []byte(s)
}

0 comments on commit ae429bb

Please sign in to comment.