refactor: rewording

Signed-off-by: QuentinN42 <quentin@lieumont.fr>
This commit is contained in:
QuentinN42 2023-03-16 16:55:27 -07:00
parent 672ab9110b
commit 1016ba0aab
No known key found for this signature in database
GPG Key ID: 2CD7D563712B3A50
4 changed files with 99 additions and 50 deletions

View File

@ -1,21 +1,30 @@
Implementing custom validators Implementing custom validators
============================== ==============================
GraphQL uses query validators to check if Query AST is valid and can be executed. Every GraphQL server implements GraphQL uses query validators to check if Query AST is valid and can be executed. Every GraphQL server implements standard query validators.
standard query validators. For example, there is an validator that tests if queried field exists on queried type, that
makes query fail with "Cannot query field on type" error if it doesn't.
If you need more complex validation than presented before, you can implement your own query validators. All custom query 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.
validators should extend the `ValidationRule`_ base class importable from the ``graphql.validation.rules`` module. Query
validators are visitor classes. They are instantiated at the time of query validation with one required argument If you need more complex validation than presented before, you can implement your own query validators.
(context: ASTValidationContext). In order to perform validation, your validator class should define one or more of
``enter_*`` and ``leave_*`` methods. For possible enter/leave items as well as details on function documentation, please
see contents of the visitor module. To make validation fail, you should call validator's report_error method with the
instance of GraphQLError describing failure reason.
Implementing your custom 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. Here is an example query validator that only allows queries fields with a name of even length.
.. code:: python .. code:: python
@ -40,3 +49,4 @@ Here is an example query validator that only allows queries fields with a name o
) )
.. _ValidationRule: https://github.com/graphql-python/graphql-core/blob/v3.0.5/src/graphql/validation/rules/__init__.py#L37 .. _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

View File

@ -2,16 +2,13 @@
Security consideration Security consideration
====================== ======================
In this section, we will discuss the most common security risks and how to mitigate them. 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. 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 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.
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 how to secure your API. 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:: .. toctree::
:maxdepth: 1 :maxdepth: 1

View File

@ -4,27 +4,24 @@ Disable Introspection
What is the 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 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.
comes from REST, you can view it as a openapi or swagger schema.
Disabling it or not ? Should I disable my introspection ?
--------------------- -----------------------------------
Depending if you are building a private or a public API, you might want to disable introspection or not. If you are Whether you are building a private or a public API, you might want to disable introspection :
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. But if you are building a private API, the only consumers of
your API will be your own developers. In this case, you might want to keep the introspection open in staging
environments but close it in production to reduce the attack surface.
Keep in mind that disabling introspection does not prevent hackers to send queries to your API. It just makes it harder - 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.
to know what they can do with it. - 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 Implementation
-------------- --------------
Graphene provides a validation rule to disable introspection. It ensures that your schema cannot be introspected. You Graphene provides a validation rule to disable introspection. It ensures that your schema cannot be introspected.
just need to import the ``DisableIntrospection`` class from ``graphene.validation``.
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. Here is a code example of how you can disable introspection for your schema.

View File

@ -1,9 +1,9 @@
Depth limit Validator Depth limit Validator
===================== =====================
By default, GraphQL queries can be arbitrarily deep. This can lead to a denial of service attack where a client can send By default, GraphQL queries can be arbitrarily deep. But a profound query can lead to a denial of service attack where a client can send a deeply nested query that will take a long time to execute.
a deeply nested query that will take a long time to execute. For that, you must find a cycle in the graph and iterate
over. If you find a cycle in the graph, you can iterate over it to generate big queries to put an extreme load on the backend.
Example Example
------- -------
@ -27,15 +27,21 @@ For example a simple app that allows you to find your friends and their friends
} }
} }
This is not a common use case, your dev team will not do that in the first place. But as your endpoint is publicly This is not a common use case; your dev team will not do that in the first place. However, as your endpoint is publicly
available, you can't be sure that someone will not try to do so. available, you cannot be sure that someone will not try to do so.
Remediation Remediation
----------- -----------
Graphene provides a depth limit validator that can be used to prevent this kind of attack. It can be configured to limit Graphene provides a depth limit validator that can be used to prevent this kind of attack. It can be configured to limit
the depth of all the queries or only some specific ones. The only required argument is ``max_depth`` which is the the depth of all the queries or only some specific ones.
maximum allowed depth for any operation in a GraphQL document. The other optional parameters are the following ones :
Arguments
_________
The only required argument is ``max_depth`` which is the maximum allowed depth for any operation in a GraphQL document.
The other optional parameters are the following ones :
- ``ignore``: A list of patterns that, if matched stops recursive depth checking. It can be one of the following : - ``ignore``: A list of patterns that, if matched stops recursive depth checking. It can be one of the following :
- ``Callable : (dict[str, int]) -> bool``: A function that receives the current operation and returns a boolean. - ``Callable : (dict[str, int]) -> bool``: A function that receives the current operation and returns a boolean.
@ -55,21 +61,60 @@ Here is an example of how you would implement depth-limiting on your schema.
from graphene.validation import depth_limit_validator from graphene.validation import depth_limit_validator
class MyQuery(ObjectType): class Me(ObjectType):
name = String(required=True) id = String()
schema = Schema(query=Me)
schema = Schema(query=MyQuery) VALID_QUERY = """
query valid {
me {
# depth is 1
id friends {
# depth is 2
id friends {
# depth is 3
id
}
}
}
}
"""
# queries which have a depth more than 20 INVALID_QUERY = """
# will not be executed. query evil {
me {
# depth is 1
id friends {
# depth is 2
id friends {
# depth is 3
id friends {
# depth is 4
id
}
}
}
}
}
"""
validation_errors = validate( RULES = (depth_limit_validator(max_depth=3), )
VALID_RESPONSE = validate(
schema=schema.graphql_schema, schema=schema.graphql_schema,
document_ast=parse('THE QUERY'), document_ast=parse(VALID_QUERY),
rules=( rules=RULES
depth_limit_validator(
max_depth=20
),
) )
assert len(VALID_RESPONSE) == 0
INVALID_RESPONSE = validate(
schema=schema.graphql_schema,
document_ast=parse(INVALID_QUERY),
rules=RULES
) )
assert len(INVALID_RESPONSE) == 1
assert INVALID_RESPONSE[0].message == "'evil' exceeds maximum operation depth of 3."