Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve security best practices in documentation #1501

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/execution/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ Execution
dataloader
fileuploading
subscriptions
queryvalidation
123 changes: 0 additions & 123 deletions docs/execution/queryvalidation.rst

This file was deleted.

1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Contents:
types/index
execution/index
relay/index
security/index
testing/index
api/index

Expand Down
52 changes: 52 additions & 0 deletions docs/security/customvalidation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
Implementing custom validators
==============================

GraphQL uses query validators to check if Query AST is valid and can be executed. Every GraphQL server implements standard query validators.

For example, a validator tests if a queried field exists on queried type, making the query fail with a "Cannot query field on type" error if it does not.

If you need more complex validation than presented before, you can implement your own query validators.

Implementing your custom validators
-----------------------------------

All custom query validators should extend the `ValidationRule`_ base class importable from the ``graphql.validation.rules`` module.
Query validators are `Visitor`_ classes.

Your custom validator should implement some methods of

In order to perform validation, your validator class should define some one or more of ``enter_*`` or ``leave_*`` methods.

Foreach methods, you will receive a node object to test:

- You can now choose to raise an error by calling ``report_error`` method with an instance of GraphQLError describing the failure reason.
- Or you can continue the parsing by returning ``None``.

Example
-------

Here is an example query validator that only allows queries fields with a name of even length.

.. code:: python

from graphql import GraphQLError
from graphql.language import FieldNode
from graphql.validation import ValidationRule


class MyCustomValidationRule(ValidationRule):
def enter_field(self, node: FieldNode, *_args):
if len(node.name.value) % 2 == 0:
# Here the query length is even, so we allow it.
return
else:
# Here the query length is odd, so we don't want to allow it.
# Calling self.report_error will make the query fail with the error message.
self.report_error(
GraphQLError(
f"Cannot query '{field_name}': length is odd.", node,
)
)

.. _ValidationRule: https://github.com/graphql-python/graphql-core/blob/v3.0.5/src/graphql/validation/rules/__init__.py#L37
.. _Visitor: https://github.com/graphql-python/graphql-core/blob/d90bf9902ca1639365639d5632861d1e18d672a9/src/graphql/language/visitor.py#L111
32 changes: 32 additions & 0 deletions docs/security/dast.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Dynamic Application Security Testing
====================================

Continuous security testing
---------------------------

One of the best way to stop wondering about security for your API is to be able to scan it each time you deploy it into
staging or production environments. As you run your unit tests in your CI/CD pipeline, you can bullet-proof your GraphQL
application before it even reaches a production environment.

Security testing tools
----------------------

graphql.security
________________

`graphql.security`_ is a free, quick graphql security testing tool, allowing you to quickly assess the most common
vulnerabilities in your application.

Escape
______

`Escape`_ is a GraphQL security SaaS platform running an automated pentest tool.

You can effortlessly incorporate this platform into your current CI/CD pipeline such as Github Actions or Gitlab CIs
which makes it convenient to set up.

The security notifications will be automatically communicated to your CI/CD platform, enabling you to promptly attend to
them.

.. _graphql.security: https://graphql.security/
.. _Escape: https://escape.tech/
21 changes: 21 additions & 0 deletions docs/security/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
======================
Security consideration
======================

This section will discuss the most common security risks and how to mitigate them.

As GraphQL is a query language, it allows users to use a wider pannel of inputs than traditional REST APIs.

Due to this feature, GraphQL APIs are inherently prone to various security risks, but they can be reduced by taking appropriate precautions. Neglecting them can expose the API to vulnerabilities like credential leakage or denial of service attacks.

As Graphene is only an engine to run GraphQL queries, it is not responsible for the HTTP layer, and this security must be handled by the web framework you are using. For example, if you are using Django-GraphQL, you may also want to check out the `Django documentation`_ on securing your API.

.. toctree::
:maxdepth: 1

maxdepth
introspection
customvalidation
dast

.. _Django documentation: https://docs.djangoproject.com/en/4.1/topics/security/
49 changes: 49 additions & 0 deletions docs/security/introspection.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
Disable Introspection
=====================

What is the introspection ?
---------------------------

The introspection query is a query that allows you to ask the server what queries and mutations are supported. If you are a REST user, you can view it as an openapi or swagger schema.

Should I disable my introspection ?
-----------------------------------

Whether you are building a private or a public API, you might want to disable introspection :

- If you are building a public API, the introspection allows consumers (developers) to know what they can do with your API. If you disable it, it will be harder for them to use your API.
- However, if you are building a private API, the only consumers of your API will be your developers. In this case, keep the introspection open in staging environments but close it in production to reduce the attack surface.

Remember that disabling introspection does not prevent hackers from sending queries to your API. It just makes it harder to know what they can do with it.

Implementation
--------------

Graphene provides a validation rule to disable introspection. It ensures that your schema cannot be introspected.

You just need to import the ``DisableIntrospection`` class from ``graphene.validation``.

Here is a code example of how you can disable introspection for your schema.

.. code:: python

from graphql import validate, parse
from graphene import ObjectType, Schema, String
from graphene.validation import DisableIntrospection


class MyQuery(ObjectType):
name = String(required=True)


schema = Schema(query=MyQuery)

# introspection queries will not be executed.

validation_errors = validate(
schema=schema.graphql_schema,
document_ast=parse('THE QUERY'),
rules=(
DisableIntrospection,
)
)
Loading