From bf255b198cb6c9f44cd183c49743c9ffdaa44ce7 Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Mon, 29 Jun 2026 17:38:16 +0200 Subject: [PATCH] Bound GraphQL request cost to prevent alias-flooding DoS The GraphQL endpoint built its gqlgen server with bare handler.New and no limits, so a single request with thousands of aliased resolver calls was parsed, validated, executed, and marshalled in full. Under load this let an unauthenticated client drive excessive CPU and memory use against POST /api/connect/v1/graphql and the console and trust endpoints, which share the same constructor (GHSA-prh2-g8pv-m7p9). Add configurable guards in the shared gqlutils.NewHandler: a parser token limit rejects oversized queries at lex time before any execution, a fixed complexity limit caps field-selection count, an LRU query cache avoids repeated parsing, and field suggestions are disabled. The limits flow from a new APIConfig.GraphQL section through server and api config into all three GraphQL handlers, with PROBOD_API_GRAPHQL_* env vars and Helm values exposed for per-environment tuning. Defaults are sized with generous headroom over real traffic: the parser token limit (15000) and complexity limit (2000) sit far above the largest legitimate frontend query yet well below the proof-of-concept flood, so normal usage is unaffected while floods are rejected cheaply. Signed-off-by: Bryan Frimin --- .../charts/probo/templates/deployment.yaml | 8 +++++ .../probo/values-production.yaml.example | 9 +++++ contrib/helm/charts/probo/values.yaml | 14 ++++++++ go.mod | 2 +- pkg/bootstrap/builder.go | 6 ++++ pkg/bootstrap/builder_test.go | 12 +++++++ pkg/probod/aliases.go | 1 + pkg/probod/probod.go | 13 +++++++ pkg/probodconfig/api_config.go | 8 +++++ pkg/server/api/api.go | 5 +++ pkg/server/api/connect/v1/graphql_handler.go | 4 +-- pkg/server/api/connect/v1/resolver.go | 4 ++- pkg/server/api/console/v1/graphql_handler.go | 3 +- pkg/server/api/console/v1/resolver.go | 3 ++ pkg/server/api/trust/v1/graphql_handler.go | 3 +- pkg/server/api/trust/v1/resolver.go | 3 ++ pkg/server/gqlutils/handler.go | 36 ++++++++++++++++--- pkg/server/server.go | 3 ++ 18 files changed, 127 insertions(+), 10 deletions(-) diff --git a/contrib/helm/charts/probo/templates/deployment.yaml b/contrib/helm/charts/probo/templates/deployment.yaml index cfc310d8d..bd8c9f1bb 100644 --- a/contrib/helm/charts/probo/templates/deployment.yaml +++ b/contrib/helm/charts/probo/templates/deployment.yaml @@ -75,6 +75,14 @@ spec: value: ":{{ .Values.service.port }}" - name: PROBOD_API_CORS_ALLOWED_ORIGINS value: {{ join "," .Values.probo.cors.allowedOrigins | quote }} + - name: PROBOD_API_GRAPHQL_PARSER_TOKEN_LIMIT + value: {{ .Values.probo.graphql.parserTokenLimit | quote }} + - name: PROBOD_API_GRAPHQL_COMPLEXITY_LIMIT + value: {{ .Values.probo.graphql.complexityLimit | quote }} + - name: PROBOD_API_GRAPHQL_QUERY_CACHE_SIZE + value: {{ .Values.probo.graphql.queryCacheSize | quote }} + - name: PROBOD_API_GRAPHQL_DISABLE_SUGGESTION + value: {{ .Values.probo.graphql.disableSuggestion | quote }} # PostgreSQL Database - name: PROBOD_PG_ADDR value: {{ printf "%s:%v" (include "probo.postgresql.host" .) (include "probo.postgresql.port" .) | quote }} diff --git a/contrib/helm/charts/probo/values-production.yaml.example b/contrib/helm/charts/probo/values-production.yaml.example index ee5861ecf..251b0d5c4 100644 --- a/contrib/helm/charts/probo/values-production.yaml.example +++ b/contrib/helm/charts/probo/values-production.yaml.example @@ -111,6 +111,15 @@ probo: allowedOrigins: - "https://probo.example.com" + # GraphQL request-cost guards (application-layer DoS protection). + # Defaults are production-safe; tune only if a legitimate query is rejected + # or to enable complexity analysis. A value of 0 disables the guard. + graphql: + parserTokenLimit: 15000 + complexityLimit: 2000 + queryCacheSize: 1000 + disableSuggestion: true + # Extra HTTP headers to add to responses extraHeaderFields: {} # X-Custom-Header: "custom-value" diff --git a/contrib/helm/charts/probo/values.yaml b/contrib/helm/charts/probo/values.yaml index a52fe7998..4b73b9e77 100644 --- a/contrib/helm/charts/probo/values.yaml +++ b/contrib/helm/charts/probo/values.yaml @@ -201,6 +201,20 @@ probo: - "https://probo.example.com" - "http://probo.example.com" + # GraphQL request-cost guards (application-layer DoS protection). + # A value of 0 disables the corresponding guard. + graphql: + # Maximum number of lexer tokens accepted per query. Oversized queries + # (e.g. alias flooding) are rejected at parse time before execution. + parserTokenLimit: 15000 + # Maximum query complexity (field-selection count). 0 disables complexity + # analysis. + complexityLimit: 2000 + # Size of the LRU cache of parsed query documents. + queryCacheSize: 1000 + # Disable field suggestions on invalid queries. + disableSuggestion: true + # Show Probo branding branding: true diff --git a/go.mod b/go.mod index 7be1de050..4b3e5a686 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.53.4 github.com/aws/aws-sdk-go-v2/service/s3 v1.103.2 github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.42.3 + github.com/aws/aws-sdk-go-v2/service/ssm v1.69.3 github.com/brianvoe/gofakeit/v7 v7.15.0 github.com/charmbracelet/huh v1.0.0 github.com/charmbracelet/lipgloss v1.1.0 @@ -60,7 +61,6 @@ require ( github.com/atotto/clipboard v0.1.4 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.28 // indirect github.com/aws/aws-sdk-go-v2/service/signin v1.1.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ssm v1.69.3 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.31.2 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.5 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.43.2 // indirect diff --git a/pkg/bootstrap/builder.go b/pkg/bootstrap/builder.go index 36846c056..37a904906 100644 --- a/pkg/bootstrap/builder.go +++ b/pkg/bootstrap/builder.go @@ -79,6 +79,12 @@ func (b *Builder) Build() (*probodconfig.FullConfig, error) { AllowedOrigins: b.parseOriginsList(b.resolver.getEnvOrDefault("PROBOD_API_CORS_ALLOWED_ORIGINS", "http://localhost:8080")), }, ExtraHeaderFields: make(map[string]string), + GraphQL: probodconfig.GraphQLConfig{ + ParserTokenLimit: b.resolver.getEnvIntOrDefault("PROBOD_API_GRAPHQL_PARSER_TOKEN_LIMIT", 15000), + ComplexityLimit: b.resolver.getEnvIntOrDefault("PROBOD_API_GRAPHQL_COMPLEXITY_LIMIT", 2000), + QueryCacheSize: b.resolver.getEnvIntOrDefault("PROBOD_API_GRAPHQL_QUERY_CACHE_SIZE", 1000), + DisableSuggestion: b.resolver.getEnvBoolOrDefault("PROBOD_API_GRAPHQL_DISABLE_SUGGESTION", true), + }, }, Pg: probodconfig.PgConfig{ Addr: b.resolver.getEnvOrDefault("PROBOD_PG_ADDR", "localhost:5432"), diff --git a/pkg/bootstrap/builder_test.go b/pkg/bootstrap/builder_test.go index 850938076..6f7f1454c 100644 --- a/pkg/bootstrap/builder_test.go +++ b/pkg/bootstrap/builder_test.go @@ -146,6 +146,10 @@ func TestBuilder_Build_Defaults(t *testing.T) { assert.Equal(t, ":8080", cfg.Probod.Api.Addr) assert.Nil(t, cfg.Probod.Api.ProxyProtocol.TrustedProxies) assert.Equal(t, []string{"http://localhost:8080"}, cfg.Probod.Api.Cors.AllowedOrigins) + assert.Equal(t, 15000, cfg.Probod.Api.GraphQL.ParserTokenLimit) + assert.Equal(t, 2000, cfg.Probod.Api.GraphQL.ComplexityLimit) + assert.Equal(t, 1000, cfg.Probod.Api.GraphQL.QueryCacheSize) + assert.True(t, cfg.Probod.Api.GraphQL.DisableSuggestion) // PG config assert.Equal(t, "localhost:5432", cfg.Probod.Pg.Addr) @@ -295,6 +299,10 @@ func TestBuilder_Build_CustomValues(t *testing.T) { env["PROBOD_API_ADDR"] = "0.0.0.0:8080" env["PROBOD_API_CORS_ALLOWED_ORIGINS"] = "https://app.example.com,https://admin.example.com" env["PROBOD_API_PROXY_PROTOCOL_TRUSTED_PROXIES"] = "10.0.0.1,10.0.0.2" + env["PROBOD_API_GRAPHQL_PARSER_TOKEN_LIMIT"] = "20000" + env["PROBOD_API_GRAPHQL_COMPLEXITY_LIMIT"] = "5000" + env["PROBOD_API_GRAPHQL_QUERY_CACHE_SIZE"] = "2000" + env["PROBOD_API_GRAPHQL_DISABLE_SUGGESTION"] = "false" // PG env["PROBOD_PG_ADDR"] = "postgres.example.com:5432" env["PROBOD_PG_USERNAME"] = "probo" @@ -425,6 +433,10 @@ func TestBuilder_Build_CustomValues(t *testing.T) { assert.Equal(t, "0.0.0.0:8080", cfg.Probod.Api.Addr) assert.Equal(t, []string{"10.0.0.1", "10.0.0.2"}, cfg.Probod.Api.ProxyProtocol.TrustedProxies) assert.Equal(t, []string{"https://app.example.com", "https://admin.example.com"}, cfg.Probod.Api.Cors.AllowedOrigins) + assert.Equal(t, 20000, cfg.Probod.Api.GraphQL.ParserTokenLimit) + assert.Equal(t, 5000, cfg.Probod.Api.GraphQL.ComplexityLimit) + assert.Equal(t, 2000, cfg.Probod.Api.GraphQL.QueryCacheSize) + assert.False(t, cfg.Probod.Api.GraphQL.DisableSuggestion) // PG assert.Equal(t, "postgres.example.com:5432", cfg.Probod.Pg.Addr) assert.Equal(t, "probo", cfg.Probod.Pg.Username) diff --git a/pkg/probod/aliases.go b/pkg/probod/aliases.go index e1028ffbe..4eed943fd 100644 --- a/pkg/probod/aliases.go +++ b/pkg/probod/aliases.go @@ -26,6 +26,7 @@ type ( TrustCenterConfig = probodconfig.TrustCenterConfig APIConfig = probodconfig.APIConfig CorsConfig = probodconfig.CorsConfig + GraphQLConfig = probodconfig.GraphQLConfig ProxyProtocolConfig = probodconfig.ProxyProtocolConfig AuthConfig = probodconfig.AuthConfig OAuth2ServerConfig = probodconfig.OAuth2ServerConfig diff --git a/pkg/probod/probod.go b/pkg/probod/probod.go index b53844fc0..240f231ea 100644 --- a/pkg/probod/probod.go +++ b/pkg/probod/probod.go @@ -70,6 +70,7 @@ import ( "go.probo.inc/probo/pkg/riskmanagement" "go.probo.inc/probo/pkg/securecookie" "go.probo.inc/probo/pkg/server" + "go.probo.inc/probo/pkg/server/gqlutils" "go.probo.inc/probo/pkg/server/trustedproxy" "go.probo.inc/probo/pkg/slack" "go.probo.inc/probo/pkg/thirdparty" @@ -93,6 +94,12 @@ func New() *Implm { BaseURL: "http://localhost:8080", Api: APIConfig{ Addr: "localhost:8080", + GraphQL: GraphQLConfig{ + ParserTokenLimit: 15000, + ComplexityLimit: 2000, + QueryCacheSize: 1000, + DisableSuggestion: true, + }, }, Pg: PgConfig{ Addr: "localhost:5432", @@ -640,6 +647,12 @@ func (impl *Implm) Run( ConnectorRegistry: defaultConnectorRegistry, ProviderRegistry: providerRegistry, BaseURL: baseURL, + GraphQLLimits: gqlutils.Limits{ + ParserTokenLimit: impl.cfg.Api.GraphQL.ParserTokenLimit, + ComplexityLimit: impl.cfg.Api.GraphQL.ComplexityLimit, + QueryCacheSize: impl.cfg.Api.GraphQL.QueryCacheSize, + DisableSuggestion: impl.cfg.Api.GraphQL.DisableSuggestion, + }, CustomDomainCname: impl.cfg.CustomDomains.CnameTarget, TokenSecret: impl.cfg.Auth.Cookie.Secret, diff --git a/pkg/probodconfig/api_config.go b/pkg/probodconfig/api_config.go index 1974cca4e..eceeb9bd6 100644 --- a/pkg/probodconfig/api_config.go +++ b/pkg/probodconfig/api_config.go @@ -22,9 +22,17 @@ type ProxyProtocolConfig struct { TrustedProxies []string `json:"trusted-proxies"` } +type GraphQLConfig struct { + ParserTokenLimit int `json:"parser-token-limit"` + ComplexityLimit int `json:"complexity-limit"` + QueryCacheSize int `json:"query-cache-size"` + DisableSuggestion bool `json:"disable-suggestion"` +} + type APIConfig struct { Addr string `json:"addr"` ProxyProtocol ProxyProtocolConfig `json:"proxy-protocol"` Cors CorsConfig `json:"cors"` ExtraHeaderFields map[string]string `json:"extra-header-fields"` + GraphQL GraphQLConfig `json:"graphql"` } diff --git a/pkg/server/api/api.go b/pkg/server/api/api.go index 0fb4df5db..f06cb6e73 100644 --- a/pkg/server/api/api.go +++ b/pkg/server/api/api.go @@ -47,6 +47,7 @@ import ( mcp_v1 "go.probo.inc/probo/pkg/server/api/mcp/v1" slack_v1 "go.probo.inc/probo/pkg/server/api/slack/v1" trust_v1 "go.probo.inc/probo/pkg/server/api/trust/v1" + "go.probo.inc/probo/pkg/server/gqlutils" "go.probo.inc/probo/pkg/slack" "go.probo.inc/probo/pkg/thirdparty" "go.probo.inc/probo/pkg/trust" @@ -75,6 +76,7 @@ type ( ConnectorRegistry *connector.ConnectorRegistry ProviderRegistry *provider.Registry CustomDomainCname string + GraphQLLimits gqlutils.Limits Logger *log.Logger } @@ -188,6 +190,7 @@ func NewServer(cfg Config) (*Server, error) { cfg.Cookie, cfg.TokenSecret, cfg.BaseURL, + cfg.GraphQLLimits, ), consoleHandler: console_v1.NewMux( cfg.Logger.Named("console.v1"), @@ -208,6 +211,7 @@ func NewServer(cfg Config) (*Server, error) { cfg.CustomDomainCname, cfg.ThirdParty, cfg.RiskManagement, + cfg.GraphQLLimits, ), cookieBannerHandler: cookiebanner_v1.NewMux( cfg.Logger.Named("cookiebanner.v1"), @@ -261,6 +265,7 @@ func NewServer(cfg Config) (*Server, error) { _, err := cfg.Trust.GetByDomainName(ctx, host) return err == nil }, + cfg.GraphQLLimits, ), }, nil } diff --git a/pkg/server/api/connect/v1/graphql_handler.go b/pkg/server/api/connect/v1/graphql_handler.go index e27d43d8c..c1f10031b 100644 --- a/pkg/server/api/connect/v1/graphql_handler.go +++ b/pkg/server/api/connect/v1/graphql_handler.go @@ -30,7 +30,7 @@ import ( "go.probo.inc/probo/pkg/server/gqlutils/directives/session" ) -func NewGraphQLHandler(svc *iam.Service, logger *log.Logger, fileManagerSvc *filemanager.Service, baseURL *baseurl.BaseURL, cookieConfig securecookie.Config) http.Handler { +func NewGraphQLHandler(svc *iam.Service, logger *log.Logger, fileManagerSvc *filemanager.Service, baseURL *baseurl.BaseURL, cookieConfig securecookie.Config, limits gqlutils.Limits) http.Handler { config := schema.Config{ Resolvers: &Resolver{ authorize: authz.NewAuthorizeFunc(svc, logger), @@ -49,7 +49,7 @@ func NewGraphQLHandler(svc *iam.Service, logger *log.Logger, fileManagerSvc *fil } es := schema.NewExecutableSchema(config) - gqlh := gqlutils.NewHandler(es, logger) + gqlh := gqlutils.NewHandler(es, logger, limits) return gqlh } diff --git a/pkg/server/api/connect/v1/resolver.go b/pkg/server/api/connect/v1/resolver.go index 0d2443487..1c86cbac8 100644 --- a/pkg/server/api/connect/v1/resolver.go +++ b/pkg/server/api/connect/v1/resolver.go @@ -46,6 +46,7 @@ import ( "go.probo.inc/probo/pkg/server/api/authn" "go.probo.inc/probo/pkg/server/api/authz" "go.probo.inc/probo/pkg/server/api/connect/v1/types" + "go.probo.inc/probo/pkg/server/gqlutils" ) type ( @@ -70,6 +71,7 @@ func NewMux( baseURL *baseurl.BaseURL, allowedRedirectHost saferedirect.AllowedHostFunc, isTrustCenterDomain IsTrustCenterDomainFunc, + graphqlLimits gqlutils.Limits, ) *chi.Mux { r := chi.NewMux() @@ -77,7 +79,7 @@ func NewMux( apiKeyMiddleware := authn.NewAPIKeyMiddleware(svc, tokenSecret) oauth2Middleware := authn.NewOAuth2AccessTokenMiddleware(svc) identityPresenceMiddleware := authn.NewIdentityPresenceMiddleware(baseURL) - graphqlHandler := NewGraphQLHandler(svc, logger, fileManagerSvc, baseURL, cookieConfig) + graphqlHandler := NewGraphQLHandler(svc, logger, fileManagerSvc, baseURL, cookieConfig, graphqlLimits) samlHandler := NewSAMLHandler(svc, cookieConfig, baseURL, logger) scimHandler := NewSCIMHandler(svc, logger.Named("scim")) diff --git a/pkg/server/api/console/v1/graphql_handler.go b/pkg/server/api/console/v1/graphql_handler.go index 1b293f55b..2f12d5919 100644 --- a/pkg/server/api/console/v1/graphql_handler.go +++ b/pkg/server/api/console/v1/graphql_handler.go @@ -55,6 +55,7 @@ func NewGraphQLHandler( riskManagementSvc *riskmanagement.Service, fileManagerSvc *filemanager.Service, baseURL *baseurl.BaseURL, + limits gqlutils.Limits, ) http.Handler { config := schema.Config{ Resolvers: &Resolver{ @@ -80,7 +81,7 @@ func NewGraphQLHandler( } es := schema.NewExecutableSchema(config) - gqlh := gqlutils.NewHandler(es, logger) + gqlh := gqlutils.NewHandler(es, logger, limits) return gqlh } diff --git a/pkg/server/api/console/v1/resolver.go b/pkg/server/api/console/v1/resolver.go index 36726f679..0604cb1a9 100644 --- a/pkg/server/api/console/v1/resolver.go +++ b/pkg/server/api/console/v1/resolver.go @@ -47,6 +47,7 @@ import ( "go.probo.inc/probo/pkg/server/api/authz" "go.probo.inc/probo/pkg/server/api/console/v1/dataloader" "go.probo.inc/probo/pkg/server/api/console/v1/types" + "go.probo.inc/probo/pkg/server/gqlutils" "go.probo.inc/probo/pkg/thirdparty" ) @@ -92,6 +93,7 @@ func NewMux( customDomainCname string, thirdPartySvc *thirdparty.Service, riskManagementSvc *riskmanagement.Service, + graphqlLimits gqlutils.Limits, ) *chi.Mux { r := chi.NewMux() @@ -114,6 +116,7 @@ func NewMux( riskManagementSvc, fileManagerSvc, baseURL, + graphqlLimits, ) r.Group(func(r chi.Router) { diff --git a/pkg/server/api/trust/v1/graphql_handler.go b/pkg/server/api/trust/v1/graphql_handler.go index d9336c726..f6822a321 100644 --- a/pkg/server/api/trust/v1/graphql_handler.go +++ b/pkg/server/api/trust/v1/graphql_handler.go @@ -44,6 +44,7 @@ func NewGraphQLHandler( baseURL *baseurl.BaseURL, cookieConfig securecookie.Config, tokenSecret string, + limits gqlutils.Limits, ) http.Handler { config := schema.Config{ Resolvers: &Resolver{ @@ -65,7 +66,7 @@ func NewGraphQLHandler( } es := schema.NewExecutableSchema(config) - gqlh := gqlutils.NewHandler(es, logger) + gqlh := gqlutils.NewHandler(es, logger, limits) return gqlh } diff --git a/pkg/server/api/trust/v1/resolver.go b/pkg/server/api/trust/v1/resolver.go index 1f2980984..0bedcb05c 100644 --- a/pkg/server/api/trust/v1/resolver.go +++ b/pkg/server/api/trust/v1/resolver.go @@ -46,6 +46,7 @@ import ( "go.probo.inc/probo/pkg/securecookie" "go.probo.inc/probo/pkg/server/api/authn" "go.probo.inc/probo/pkg/server/api/compliancepage" + "go.probo.inc/probo/pkg/server/gqlutils" "go.probo.inc/probo/pkg/trust" ) @@ -85,6 +86,7 @@ func NewMux( cookieConfig securecookie.Config, tokenSecret string, baseURL *baseurl.BaseURL, + graphqlLimits gqlutils.Limits, ) *chi.Mux { r := chi.NewMux() @@ -112,6 +114,7 @@ func NewMux( baseURL, cookieConfig, tokenSecret, + graphqlLimits, ) r.Group( diff --git a/pkg/server/gqlutils/handler.go b/pkg/server/gqlutils/handler.go index 647115491..2fcf6261b 100644 --- a/pkg/server/gqlutils/handler.go +++ b/pkg/server/gqlutils/handler.go @@ -21,13 +21,27 @@ import ( "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/extension" + "github.com/99designs/gqlgen/graphql/handler/lru" "github.com/99designs/gqlgen/graphql/handler/transport" + "github.com/vektah/gqlparser/v2/ast" "go.gearno.de/kit/log" ) -type Handler struct { - gqlhandler *handler.Server -} +type ( + Handler struct { + gqlhandler *handler.Server + } + + // Limits bounds the per-request cost of a GraphQL operation to protect + // against alias-flooding and other application-layer denial-of-service + // vectors. A zero value disables the corresponding guard. + Limits struct { + ParserTokenLimit int + ComplexityLimit int + QueryCacheSize int + DisableSuggestion bool + } +) var ( mb int64 = 1024 * 1024 @@ -42,13 +56,27 @@ var ( introspectionExtension = extension.Introspection{} ) -func NewHandler[S graphql.ExecutableSchema](executableSchema S, logger *log.Logger) *Handler { +func NewHandler[S graphql.ExecutableSchema](executableSchema S, logger *log.Logger, limits Limits) *Handler { handler := handler.New(executableSchema) handler.AddTransport(postTransport) handler.AddTransport(optionsTransport) handler.AddTransport(multipartTransport) + if limits.QueryCacheSize > 0 { + handler.SetQueryCache(lru.New[*ast.QueryDocument](limits.QueryCacheSize)) + } + + if limits.ParserTokenLimit > 0 { + handler.SetParserTokenLimit(limits.ParserTokenLimit) + } + + if limits.ComplexityLimit > 0 { + handler.Use(extension.FixedComplexityLimit(limits.ComplexityLimit)) + } + + handler.SetDisableSuggestion(limits.DisableSuggestion) + handler.Use(introspectionExtension) handler.Use(NewTracingExtension(logger)) diff --git a/pkg/server/server.go b/pkg/server/server.go index f879360f8..87143dad8 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -42,6 +42,7 @@ import ( "go.probo.inc/probo/pkg/securecookie" "go.probo.inc/probo/pkg/server/api" "go.probo.inc/probo/pkg/server/api/compliancepage" + "go.probo.inc/probo/pkg/server/gqlutils" "go.probo.inc/probo/pkg/server/mailactions" trust_web "go.probo.inc/probo/pkg/server/trust" console_web "go.probo.inc/probo/pkg/server/web" @@ -74,6 +75,7 @@ type Config struct { ConnectorRegistry *connector.ConnectorRegistry ProviderRegistry *provider.Registry CustomDomainCname string + GraphQLLimits gqlutils.Limits Logger *log.Logger } @@ -114,6 +116,7 @@ func NewServer(cfg Config) (*Server, error) { ConnectorRegistry: cfg.ConnectorRegistry, ProviderRegistry: cfg.ProviderRegistry, CustomDomainCname: cfg.CustomDomainCname, + GraphQLLimits: cfg.GraphQLLimits, Logger: cfg.Logger.Named("api"), }