1
0
Fork 0
mirror of https://git.sr.ht/~sircmpwn/core-go synced 2024-10-07 16:48:33 +02:00

Enforce complexity limit on webhook payload

This commit is contained in:
Drew DeVault 2021-08-20 15:22:33 +02:00
parent 1371ba4bbb
commit 5f76a1f40d
2 changed files with 17 additions and 8 deletions

View file

@ -56,6 +56,8 @@ type Server struct {
service string
queues []*work.Queue
email *work.Queue
MaxComplexity int
}
// Creates a new common server context for a SourceHut GraphQL daemon.
@ -81,22 +83,19 @@ func (server *Server) WithSchema(
schema graphql.ExecutableSchema, scopes []string) *Server {
server.Schema = schema
var (
complexity int
err error
)
var err error
if limit, ok := server.conf.Get(
server.service+"::api", "max-complexity"); ok {
complexity, err = strconv.Atoi(limit)
server.MaxComplexity, err = strconv.Atoi(limit)
if err != nil {
panic(err)
}
} else {
complexity = 250
server.MaxComplexity = 250
}
srv := handler.GraphQL(schema,
handler.ComplexityLimit(complexity),
handler.ComplexityLimit(server.MaxComplexity),
handler.RecoverFunc(EmailRecover),
handler.UploadMaxSize(1073741824)) // 1 GiB (TODO: configurable?)
@ -234,6 +233,7 @@ func (server *Server) WithQueues(queues ...*work.Queue) *Server {
ctx = database.Context(ctx, server.db)
ctx = redis.Context(ctx, server.redis)
ctx = email.Context(ctx, server.email)
ctx = context.WithValue(ctx, serverCtxKey, server)
server.queues = append(server.queues, queues...)
for _, queue := range queues {

View file

@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"github.com/99designs/gqlgen/complexity"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/executor"
"github.com/google/uuid"
@ -64,7 +65,6 @@ func (webhook *WebhookContext) Exec(ctx context.Context,
return nil, err
}
// TODO: Set complexity limit
exec := executor.New(schema)
params := graphql.RawParams{
Query: sub.Query,
@ -80,6 +80,15 @@ func (webhook *WebhookContext) Exec(ctx context.Context,
}
rc.RecoverFunc = server.EmailRecover
op := rc.Doc.Operations.ForName(rc.OperationName)
complexity := complexity.Calculate(schema, op, rc.Variables)
srv := server.ForContext(ctx)
if complexity > srv.MaxComplexity {
// TODO: This doesn't bubble up to the user well
return nil, fmt.Errorf("operation has complexity %d, which exceeds the maximum of %d",
complexity, srv.MaxComplexity)
}
var resp graphql.ResponseHandler
ctx = graphql.WithOperationContext(ctx, rc)
resp, ctx = exec.DispatchOperation(ctx, rc)