spring-graphql icon indicating copy to clipboard operation
spring-graphql copied to clipboard

Auto-registration of max query complexity/depth instrumentations if property is set

Open marceloverdijk opened this issue 3 years ago • 4 comments

spring-graphql auto-configuration already supports picking Instrumentation beans and registering them in the GraphQlSource. So it's just a matter of creating an instrumentation bean and it works 👍

One of the important (security) aspects to consider when developing a GraphQL server, is to make sure clients will not exhaust it by querying too many levels or fields. E.g. when having a circular model a bad client could request many many levels deep almost causing an infinite loop.

So a good practice is:

  • to have a limit on the length of the GraphQL query passed to the engine itself
  • to have a limit on query depth
  • to have a limit on query complexity (number of fields requested)

For the latter 2 graphql-java provides 2 instrumentation already.

I would be nice if user could enable these instrumentation by just providing an application property like:

spring.graphql.instrumentation.max-query-complexity=200
spring.graphql.instrumentation.max-query-depth=20

The starter could then contain something like below to register the beans: (this is actually what I have now in my own application)

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "spring.graphql.instrumentation", name = "max-query-complexity")
    public MaxQueryComplexityInstrumentation maxQueryComplexityInstrumentation(@Value("${spring.graphql.instrumentation.max-query-complexity}") int maxComplexity) {
        return new MaxQueryComplexityInstrumentation(maxComplexity);
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "spring.graphql.instrumentation", name = "max-query-depth")
    public MaxQueryDepthInstrumentation maxQueryDepthInstrumentation(@Value("${spring.graphql.instrumentation.max-query-depth}") int maxDepth) {
        return new MaxQueryDepthInstrumentation(maxDepth);
    }

(off course better to add the instrumentation properties to the actual GraphQlProperties class)

If interested I could create a PR for this?

marceloverdijk avatar Jan 11 '22 10:01 marceloverdijk

Thanks for creating this issue, this is something we'd like to explore more generally. I'd like to repurpose this issue for a broader query complexity/depth support with:

  1. check whether we can add some instrumentation around query complexity/depth for metrics
  2. see if there's a need for a specific mechanism in Spring Boot or Spring for GraphQL for auto-registration/auto-detection of field complexity calculator
  3. optionally register the instrumentation implementations mentioned in this issue

bclozel avatar Jan 13 '22 11:01 bclozel

Moving this issue back to Spring for GraphQL, as this is likely to happen in the 1.1.x line and projects should provide Observation support directly with Micrometer 1.10.

bclozel avatar Aug 19 '22 14:08 bclozel

The query complexity calculator is moving out of Instrumentation - we should use this new infrastructure when it's available.

bclozel avatar Jun 02 '23 12:06 bclozel

I found some interesting materials on graphql cost analysis

  • https://arxiv.org/pdf/2009.05632.pdf
  • https://ibm.github.io/graphql-specs/cost-spec.html

juliuskrah avatar Jan 06 '24 21:01 juliuskrah