Skip to content

Commit 8735c73

Browse files
authored
Merge pull request #361 from bitecodes/disable_introspection
Add config option to disable introspection query
2 parents 3117b60 + cbe26a1 commit 8735c73

File tree

8 files changed

+89
-0
lines changed

8 files changed

+89
-0
lines changed

DependencyInjection/Configuration.php

+1
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ private function securitySection()
166166
->children()
167167
->append($this->securityQuerySection('query_max_depth', QueryDepth::DISABLED))
168168
->append($this->securityQuerySection('query_max_complexity', QueryComplexity::DISABLED))
169+
->booleanNode('enable_introspection')->defaultTrue()->end()
169170
->booleanNode('handle_cors')->defaultFalse()->end()
170171
->end()
171172
->end();

DependencyInjection/OverblogGraphQLExtension.php

+5
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ private function treatConfigs(array $configs, ContainerBuilder $container, $forc
162162

163163
private function setSecurity(array $config, ContainerBuilder $container)
164164
{
165+
if (false === $config['security']['enable_introspection']) {
166+
$executorDefinition = $container->getDefinition($this->getAlias().'.request_executor');
167+
$executorDefinition->addMethodCall('disableIntrospectionQuery');
168+
}
169+
165170
foreach ($config['security'] as $key => $value) {
166171
$container->setParameter(sprintf('%s.%s', $this->getAlias(), $key), $value);
167172
}

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Documentation
6767
- [Fields public control](Resources/doc/security/fields-public-control.md)
6868
- [Limiting query depth](Resources/doc/security/limiting-query-depth.md)
6969
- [Query complexity analysis](Resources/doc/security/query-complexity-analysis.md)
70+
- [Disable introspection](Resources/doc/security/disable_introspection.md)
7071
- [Errors handling](Resources/doc/error-handling/index.md)
7172
- [Events](Resources/doc/events/index.md)
7273

Request/Executor.php

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use GraphQL\Executor\Promise\PromiseAdapter;
88
use GraphQL\Type\Schema;
99
use GraphQL\Validator\DocumentValidator;
10+
use GraphQL\Validator\Rules\DisableIntrospection;
1011
use GraphQL\Validator\Rules\QueryComplexity;
1112
use GraphQL\Validator\Rules\QueryDepth;
1213
use Overblog\GraphQLBundle\Event\Events;
@@ -113,6 +114,11 @@ public function setMaxQueryComplexity($maxQueryComplexity)
113114
$queryComplexity->setMaxQueryComplexity($maxQueryComplexity);
114115
}
115116

117+
public function disableIntrospectionQuery()
118+
{
119+
DocumentValidator::addRule(new DisableIntrospection());
120+
}
121+
116122
/**
117123
* @param null|string $schemaName
118124
* @param array $request
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Disable introspection
2+
=====================
3+
4+
This bundle supports [webonyx/graphql-php validation rule to disable introspection queries](http://webonyx.github.io/graphql-php/security/#disabling-introspection).
5+
6+
Introspection is a mechanism for fetching schema structure. It is used by tools like GraphiQL for auto-completion, query validation, etc.
7+
8+
It means that anybody can get a full description of your schema by sending a special query containing meta fields __type and __schema.
9+
10+
If you are not planning to expose your API to the general public, it makes sense to disable this feature in production. By disabling, tools like GraphiQL won't work anymore.
11+
12+
```yaml
13+
#app/config/config.yml
14+
overblog_graphql:
15+
security:
16+
enable_introspection: '%kernel.debug%'
17+
```
18+
19+
Introspection is enabled by default.

Resources/doc/security/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ Security
66
* [Fields public control](fields-public-control.md)
77
* [Limiting query depth](limiting-query-depth.md)
88
* [Query complexity analysis](query-complexity-analysis.md)
9+
* [Disable introspection](disable_introspection.md)
910

1011
Next step [handling errors](../error-handling/index.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
imports:
2+
- { resource: ../config.yml }
3+
- { resource: ../connection/services.yml }
4+
5+
overblog_graphql:
6+
security:
7+
enable_introspection: false
8+
definitions:
9+
class_namespace: "Overblog\\GraphQLBundle\\QueryComplexity\\__DEFINITIONS__"
10+
schema:
11+
query: Query
12+
mutation: ~
13+
mappings:
14+
types:
15+
-
16+
type: yaml
17+
dir: "%kernel.root_dir%/config/queryComplexity/mapping"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Overblog\GraphQLBundle\Tests\Functional\Security;
4+
5+
use Overblog\GraphQLBundle\Tests\Functional\TestCase;
6+
7+
class DisableIntrospectionTest extends TestCase
8+
{
9+
private $introspectionQuery = <<<'EOF'
10+
query {
11+
__schema {
12+
types {
13+
name
14+
description
15+
}
16+
}
17+
}
18+
EOF;
19+
20+
public function testIntrospectionDisabled()
21+
{
22+
$expected = [
23+
'errors' => [
24+
[
25+
'message' => 'GraphQL introspection is not allowed, but the query contained __schema or __type',
26+
'category' => 'graphql',
27+
'locations' => [
28+
[
29+
'line' => 2,
30+
'column' => 3,
31+
],
32+
],
33+
],
34+
],
35+
];
36+
37+
$this->assertResponse($this->introspectionQuery, $expected, self::ANONYMOUS_USER, 'disableIntrospection');
38+
}
39+
}

0 commit comments

Comments
 (0)