Skip to main content

Protects graphene, graphql or strawberry against malicious queries

Project description

What does this project solve?

It provides protection against malicious grapqhl requests (resource exhaustion). Despite its name it can be used with graphql (pure), graphene, strawberry. It is implemented via a custom ValidationRule, supports error reporting and early bail out strategies as well as limits for single fields

Installation

pip install graphene-protector

Integration

Django

This adds to django the following setting:

  • GRAPHENE_PROTECTOR_DEPTH_LIMIT: max depth
  • GRAPHENE_PROTECTOR_SELECTIONS_LIMIT: max selections
  • GRAPHENE_PROTECTOR_COMPLEXITY_LIMIT: max (depth * selections)

Integrate with:

graphene:

# schema.py
# replace normal Schema import with:
from graphene_protector.django.graphene import Schema
schema = Schema(query=Query, mutation=Mutation)

and add in django settings to GRAPHENE

GRAPHENE = {
    ...
    "SCHEMA": "path.to.schema",
}

or strawberry:

# schema.py
# replace normal Schema import with:
from graphene_protector.django.strawberry import Schema
schema = Schema(query=Query, mutation=Mutation)

manual way (note: import from django for including defaults from settings)

from graphene_protector.django.graphene import Schema
# or
# from graphene_protector.django.strawberry import Schema
schema = Schema(query=Query)
result = schema.execute(query_string)

manual way with custom default Limits

from graphene_protector import Limits
from graphene_protector.django.graphene import Schema
# or
# from graphene_protector.django.strawberry import Schema
schema = graphene.Schema(query=Query, limits=Limits(complexity=None))
result = schema.execute(
    query_string
)

Graphene & Strawberry

limits keyword with Limits object is supported.

from graphene_protector import Limits
from graphene_protector.graphene import Schema
# or
# from graphene_protector.strawberry import Schema
schema = Schema(query=Query, limits=Limits(depth=20, selections=None, complexity=100))
result = schema.execute(query_string)

pure graphql

from graphene_protector import LimitsValidationRule
from graphql.type.schema import Schema
schema = Schema(
    query=Query,
)
query_ast = parse("{ hello }")
self.assertFalse(validate(schema, query_ast, [LimitsValidationRule]))

or with custom defaults

from graphene_protector import Limits, LimitsValidationRule
from graphql.type.schema import Schema

class CustomLimitsValidationRule(LimitsValidationRule):
    default_limits = Limits(depth=20, selections=None, complexity=100)

schema = Schema(
    query=Query,
)
query_ast = parse("{ hello }")
self.assertFalse(validate(schema, query_ast, [LimitsValidationRule]))

strawberry extension variant

from graphene_protector import Limits
from graphene_protector.strawberry import CustomGrapheneProtector
from strawberry import Schema
schema = Schema(query=Query, extensions=[CustomGrapheneProtector(Limits(depth=20, selections=None, complexity=100))])
result = schema.execute(query_string)

or with custom defaults via Mixin

from graphene_protector import Limits, SchemaMixin, LimitsValidationRule
from graphql.type.schema import Schema

class CustomSchema(SchemaMixin, Schema):
    default_limits = Limits(depth=20, selections=None, complexity=100)

schema = CustomSchema(
    query=Query,
)
query_ast = parse("{ hello }")
self.assertFalse(validate(schema, query_ast, [LimitsValidationRule]))

strawberry extension variant with mixin

from graphene_protector import Limits, SchemaMixin
from graphene_protector.strawberry import CustomGrapheneProtector
from strawberry import Schema

class CustomSchema(SchemaMixin, Schema):
    default_limits = Limits(depth=20, selections=None, complexity=100)

schema = Schema(query=Query, extensions=[CustomGrapheneProtector()])
result = schema.execute(query_string)

Limits

A Limits object has following attributes:

  • depth: max depth (default: 20, None disables feature)
  • selections: max selections (default: None, None disables feature)
  • complexity: max (depth subtree * selections subtree) (default: 100, None disables feature)

they overwrite django settings if specified.

decorating single fields

Sometimes single fields should have different limits:

    person1 = Limits(depth=10)(graphene.Field(Person))

Limits are inherited for unspecified parameters

one-time disable limit checks

to disable checks for one operation use check_limits=False (works for: execute, execute_async (if available), subscribe (if available)):

from graphene_protector import Limits
from graphene_protector.graphene import Schema
schema = Schema(query=Query, limits=Limits(depth=20, selections=None, complexity=100))
result = schema.execute(query_string, check_limits=False)

Development

I am open for new ideas. If you want some new or better algorithms integrated just make a PR

related projects:

  • secure-graphene: lacks django integration, some features and has a not so easy findable name. But I accept: it is the "not invented here"-syndrome

TODO

  • test mutations

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graphene_protector-0.9.1.tar.gz (9.5 kB view details)

Uploaded Source

Built Distribution

graphene_protector-0.9.1-py3-none-any.whl (9.8 kB view details)

Uploaded Python 3

File details

Details for the file graphene_protector-0.9.1.tar.gz.

File metadata

  • Download URL: graphene_protector-0.9.1.tar.gz
  • Upload date:
  • Size: 9.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.2 CPython/3.10.9 Linux/6.1.7-arch1-1

File hashes

Hashes for graphene_protector-0.9.1.tar.gz
Algorithm Hash digest
SHA256 688c4bf737e738aab2827b6520c5528ef9bcbeb23f9f57ffbd1c8116d41161a1
MD5 de2c8ee43469270733aa92b0fb1d1df3
BLAKE2b-256 b4351f8905c25768c0f4c0d0e64a1c197438593d05b9fbe77336bef315f9a38d

See more details on using hashes here.

File details

Details for the file graphene_protector-0.9.1-py3-none-any.whl.

File metadata

File hashes

Hashes for graphene_protector-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2460b080e7d156c5a9a181d35578f6dbc830e70dfc5c236dca28769020b3cdf2
MD5 31a6e3d854f51877f1a1c6fd0e47acec
BLAKE2b-256 1abefed7ac5537ba4915c7ebbf834fa3ea91e4f40fa5f790dbf1977efc16320e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page