Skip to content

Commit 9ee652b

Browse files
committed
feat: Add raw graphQL content
1 parent 76a04dd commit 9ee652b

File tree

1 file changed

+374
-1
lines changed

1 file changed

+374
-1
lines changed

content/waf/policies/graphql-protection.md

Lines changed: 374 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,377 @@ nd-content-type: reference
1010
# Intended for internal catalogue and search, case sensitive:
1111
# Agent, N4Azure, NIC, NIM, NGF, NAP-DOS, NAP-WAF, NGINX One, NGINX+, Solutions, Unit
1212
nd-product: NAP-WAF
13-
---
13+
---
14+
15+
GraphQL is an API technology that has grown rapidly in recent years and is continuing to gain traction. GraphQL is a query language designed for APIs to use in the development of client applications that access large data sets with intricate relations among themselves. It provides an intuitive application and flexible syntax for describing data requirements.
16+
17+
GraphQL provides a more efficient, powerful and flexible alternative to REST APIs. This makes it easier to retrieve the data you require in a single request and helps in overcoming challenges which include under-fetching and over-fetching of data. GraphQL also enables faster front-end development without the need for new API endpoints (GraphQL works on a single endpoint), great backend analytics using GraphQL queries and a structured schema and type system.
18+
19+
GraphQL also allows the client to specify exactly what data it needs, reducing the amount of data transferred over the network and improving the overall performance of the application.
20+
21+
In the following sections, you will learn more about enabling GraphQL configuration (using basic and advanced configuration) plus GraphQL security, GraphQL profile and URL settings.
22+
23+
### GraphQL Security
24+
25+
Securing GraphQL APIs with F5 WAF for NGINX involves using WAF to monitor and protect against security threats and attacks. GraphQL, like REST, is usually [served over HTTP](http://graphql.org/learn/serving-over-http/), using GET and POST requests and a proprietary [query language](https://graphql.org/learn/schema/#the-query-and-mutation-types). It is prone to the typical Web APIs security vulnerabilities, such as injection attacks, Denial of Service (DoS) attacks and abuse of flawed authorization.
26+
27+
Unlike REST, where Web resources are identified by multiple URLs, GraphQL server operates on a single URL/endpoint, usually **/graphql**. All GraphQL requests for a given service should be directed to this endpoint.
28+
29+
## Enabling GraphQL with Basic Configuration
30+
31+
This section describes how to configure GraphQL with minimal configuration. Refer to the following sections for GraphQL elements definitions and details about advanced configuration options.
32+
33+
{{< call-out "note" >}} GraphQL is supported on F5 WAF for NGINX version starting 4.2. Make sure you're running F5 WAF for NGINX version 4.2 or later to get GraphQL to work properly.{{< /call-out >}}
34+
35+
GraphQL policy consists of three basic elements: GraphQL Profile, GraphQL Violations and GraphQL URL.
36+
37+
You can enable GraphQL on App Protect by following these steps:
38+
39+
1. Create a GraphQL policy that includes the policy name. Note that GraphQL profile and GraphQL violation will be enabled by default in the default policy.
40+
You can enable GraphQL on App Protect with minimum effort by using the following GraphQL policy example.
41+
1. Add the GraphQL URL to the policy and associate the GraphQL default profile with it.
42+
1. Optionally, if the app that uses this policy serves only GraphQL traffic, then delete the wildcard URL "*" from the policy so that requests to any URL other than **/graphql** will trigger a violation. In the example below we assume this is the case.
43+
1. Update the `nginx.conf` file. To enforce GraphQL settings, update the `app_protect_policy_file` field with the GraphQL policy name in `nginx.conf` file. Perform nginx reload once `nginx.conf` file is updated to enforce the GraphQL settings.
44+
45+
In the following policy example, the GraphQL "policy name" i.e. "graphql_policy", and graphql "urls" settings are defined.
46+
47+
```shell
48+
{
49+
    "name": "graphql_policy",
50+
    "template": {
51+
        "name": "POLICY_TEMPLATE_NGINX_BASE"
52+
    },
53+
    "applicationLanguage": "utf-8",
54+
    "caseInsensitive": false,
55+
    "enforcementMode": "blocking",
56+
    "urls": [
57+
        {
58+
            "$action": "delete",
59+
            "method": "*",
60+
            "name": "*",
61+
            "type": "wildcard"
62+
        },
63+
        {
64+
            "name": "/graphql",
65+
            "type": "explicit",
66+
            "urlContentProfiles": [
67+
                {
68+
                    "contentProfile": {
69+
                        "name": "Default"
70+
                    },
71+
                    "headerValue": "*",
72+
                    "headerName": "*",
73+
                    "headerOrder": "default",
74+
                    "type": "graphql"
75+
                }
76+
            ]
77+
        }
78+
    ]
79+
}
80+
```
81+
82+
As described in point 4 above, here is an example `nginx.conf` file:
83+
84+
```nginx
85+
user nginx;
86+
worker_processes 4;
87+
88+
load_module modules/ngx_http_app_protect_module.so;
89+
90+
error_log /var/log/nginx/error.log debug;
91+
92+
events {
93+
worker_connections 65536;
94+
}
95+
96+
http {
97+
include /etc/nginx/mime.types;
98+
default_type application/octet-stream;
99+
sendfile on;
100+
keepalive_timeout 65;
101+
102+
app_protect_enable on; # This is how you enable F5 WAF for NGINX in the relevant context/block
103+
app_protect_policy_file "/etc/app_protect/conf/NginxDefaultPolicy.json"; # This is a reference to the policy file to use. If not defined, the default policy is used
104+
app_protect_security_log_enable on; # This section enables the logging capability
105+
app_protect_security_log "/etc/app_protect/conf/log_default.json" syslog:server=127.0.0.1:514; # This is where the remote logger is defined in terms of: logging options (defined in the referenced file), log server IP, log server port
106+
107+
108+
server {
109+
listen 80;
110+
server_name localhost;
111+
proxy_http_version 1.1;
112+
113+
location / {
114+
client_max_body_size 0;
115+
default_type text/html;
116+
proxy_pass http://172.29.38.211:80$request_uri;
117+
}
118+
119+
location /graphql {
120+
            client_max_body_size 0;
121+
            default_type text/html;
122+
            app_protect_policy_file "/etc/app_protect/conf/graphQL_policy.json"; # This location will invoke the custom GraphQL policy 
123+
            proxy_pass http://172.29.38.211:80$request_uri;
124+
}
125+
}
126+
}
127+
```
128+
129+
## GraphQL Advanced Configuration
130+
131+
The below sections provides details about enabling GraphQL with advanced configuration.
132+
133+
In advanced configuration, GraphQL policy consists of GraphQL Violations, GraphQL Profile and the URL section.
134+
135+
### GraphQL Violations
136+
137+
F5 WAF for NGINX introduces four new violations specific to GraphQL: `VIOL_GRAPHQL_FORMAT`, `VIOL_GRAPHQL_MALFORMED`, `VIOL_GRAPHQL_INTROSPECTION_QUERY` and `VIOL_GRAPHQL_ERROR_RESPONSE`. <br>
138+
139+
Under the "blocking-settings," user can either enable or disable these violations. Note that these violations will be enabled by default. Any changes to these violation settings here will override the default settings. The details regarding logs will be recorded in the security log. <br>
140+
141+
See also the [Violations](#violations) section for more details.
142+
143+
While configuring GraphQL, since the GraphQL violations are enabled by default, you can change the GraphQL violations settings i.e. alarm: `true` and block: `false` under the "blocking settings". In this manner, the GraphQL profile detects violations but does not block the request. They may contribute to the Violation Rating, which, if raised above 3, will automatically block the request.
144+
145+
However, setting the alarm and block to `true` will enforce block settings and App Protect will block any violating requests.
146+
147+
See below example for more details:
148+
149+
```shell
150+
{
151+
"name": "graphql_policy",
152+
"template": {
153+
"name": "POLICY_TEMPLATE_NGINX_BASE"
154+
},
155+
"applicationLanguage": "utf-8",
156+
"caseInsensitive": false,
157+
"enforcementMode": "blocking",
158+
"blocking-settings": {
159+
"violations": [
160+
{
161+
"name": "VIOL_GRAPHQL_FORMAT",
162+
"alarm": true,
163+
"block": false
164+
},
165+
{
166+
"name": "VIOL_GRAPHQL_MALFORMED",
167+
"alarm": true,
168+
"block": false
169+
},
170+
{
171+
"name": "VIOL_GRAPHQL_INTROSPECTION_QUERY",
172+
"alarm": true,
173+
"block": false
174+
},
175+
{
176+
"name": "VIOL_GRAPHQL_ERROR_RESPONSE",
177+
"alarm": true,
178+
"block": false
179+
}
180+
]
181+
}
182+
}
183+
```
184+
185+
### GraphQL Profile
186+
187+
{{< call-out "note" >}} For GraphQL profile default values and GraphQL violations reference, see NGINX App Protect WAF [Declarative Policy guide.]({{< ref "/nap-waf/v5/declarative-policy/policy.md" >}}) {{< /call-out >}}
188+
189+
The GraphQL Profile defines the GraphQL properties that are enforced by the security policy.
190+
191+
The profile can be added by the security engineers to make sure that GraphQL apps are bound to the same security settings defined in the profile. Different GraphQL apps can have different profiles based on the security needs.
192+
193+
The GraphQL Profile includes:
194+
195+
- **Security enforcement**: whether to detect signatures and/or metacharacters and optionally an exception (a.k.a override) list of signatures that need to be disabled in the context of this profile.
196+
- **Defense attributes**: special restrictions applied to the GraphQL traffic. The below example shows the customized GraphQL properties.
197+
- **responseEnforcement**: whether to block Disallowed patterns and provide the list of patterns against the `disallowedPatterns` property.
198+
199+
GraphQL profile example:
200+
201+
In the GraphQL profile example below, we changed the "defenseAttributes" to custom values. You can customize these values under the "defenseAttributes" property. Add a list of disallowed patterns to the "disallowedPatterns" field (for example, here we've added pattern1 and pattern2).
202+
203+
```shell
204+
"graphql-profiles" : [
205+
{
206+
"attackSignaturesCheck" : true,
207+
"defenseAttributes" : {
208+
"allowIntrospectionQueries" : false,
209+
"maximumBatchedQueries" : 10,
210+
"maximumQueryCost" : "any",
211+
"maximumStructureDepth" : 10,
212+
"maximumTotalLength" : 100000,
213+
"maximumValueLength" : 100000,
214+
"tolerateParsingWarnings" : false
215+
},
216+
"description" : "",
217+
"metacharElementCheck" : false,
218+
"name" : "response_block",
219+
"responseEnforcement" : {
220+
"blockDisallowedPatterns" : true,
221+
"disallowedPatterns":["pattern1","pattern2"]
222+
}
223+
}
224+
]
225+
```
226+
227+
### Define URL settings
228+
229+
he second step to configure GraphQL is to define the URL settings. Set the values for "isAllowed": **true**, "name": **/graphql** in the URLs section, which means URLs with **/graphql** name are permitted. This path will be used for all GraphQL API requests.
230+
231+
Under the "urlContentProfiles" settings define the GraphQL profile name, headerValue: `*` (wildcard), headerName: `*` (wildcard), headerOrder: `default` (allowing any GraphQL URL request with any headerValue, headerName and type should be `graphql`.
232+
233+
There are no restrictions on the number of GraphQL profiles that can be added by the user.
234+
235+
GraphQL URL example:
236+
237+
```shell
238+
"urls": [
239+
{
240+
"$action": "delete",
241+
"method": "*",
242+
"name": "*",
243+
"protocol": "http",
244+
"type": "wildcard"
245+
},
246+
{
247+
"isAllowed": true,
248+
"name": "/graphql",
249+
"protocol": "http",
250+
"type": "explicit",
251+
"performStaging": false,
252+
"urlContentProfiles": [
253+
{
254+
"contentProfile": {
255+
"name": "Default"
256+
},
257+
"headerValue": "*",
258+
"headerName": "*",
259+
"headerOrder": "default",
260+
"type": "graphql"
261+
}
262+
]
263+
}
264+
]
265+
```
266+
267+
### Associating GraphQL Profiles with URL
268+
269+
The last step is to associate the GraphQL profiles with the URLs. As with JSON and XML profiles, in order for a GraphQL Profile to become effective, it has to be associated with a URL that represents the service. Add the GraphQL profile name which you defined previously under the GraphQL profiles in the name field. For example, here we have defined two GraphQL profiles with the "name": "Default" and "My Custom Profile" under the urlContentProfiles. Later we also associated these profiles in "graphql-profiles".
270+
271+
GraphQL configuration example:
272+
273+
In this example we define a custom GraphQL profile and use it on one URL, while assigning the default profile to another one.
274+
275+
```shell
276+
{
277+
"name": "graphql_policy",
278+
"template": {
279+
"name": "POLICY_TEMPLATE_NGINX_BASE"
280+
},
281+
"applicationLanguage": "utf-8",
282+
"caseInsensitive": false,
283+
"enforcementMode": "blocking",
284+
285+
"graphql-profiles": [
286+
{
287+
"attackSignaturesCheck": true,
288+
"defenseAttributes": {
289+
"allowIntrospectionQueries": true,
290+
"maximumBatchedQueries": "any",
291+
"maximumQueryCost": "any",
292+
"maximumStructureDepth": "any",
293+
"maximumTotalLength": "any",
294+
"maximumValueLength": "any",
295+
"tolerateParsingWarnings": true
296+
},
297+
"description": "Default GraphQL Profile",
298+
"metacharElementCheck": true,
299+
"name": "Default",
300+
"responseEnforcement": {
301+
"blockDisallowedPatterns": false
302+
}
303+
},
304+
{
305+
"attackSignaturesCheck": true,
306+
"defenseAttributes": {
307+
"allowIntrospectionQueries": true,
308+
"maximumBatchedQueries": "any",
309+
"maximumQueryCost": "any",
310+
"maximumStructureDepth": "any",
311+
"maximumTotalLength": "400",
312+
"maximumValueLength": "any",
313+
"tolerateParsingWarnings": false
314+
},
315+
"description": "my custom Profile",
316+
"metacharElementCheck": true,
317+
"name": "My Custom Profile",
318+
"responseEnforcement": {
319+
"blockDisallowedPatterns": true,
320+
"disallowedPatterns": ["pattern1", "pattern2"]
321+
}
322+
}
323+
],
324+
"urls": [
325+
{
326+
"$action": "delete",
327+
"method": "*",
328+
"name": "*",
329+
"protocol": "http",
330+
"type": "wildcard"
331+
},
332+
{
333+
"isAllowed": true,
334+
"name": "/graphql",
335+
"protocol": "http",
336+
"type": "explicit",
337+
"performStaging": false,
338+
"urlContentProfiles": [
339+
{
340+
"contentProfile": {
341+
"name": "Default"
342+
},
343+
"headerValue": "*",
344+
"headerName": "*",
345+
"headerOrder": "default",
346+
"type": "graphql"
347+
}
348+
]
349+
},
350+
{
351+
"isAllowed": true,
352+
"name": "/mygraphql",
353+
"protocol": "http",
354+
"type": "explicit",
355+
"performStaging": false,
356+
"urlContentProfiles": [
357+
{
358+
"contentProfile": {
359+
"name": "My Custom Profile"
360+
},
361+
"headerValue": "*",
362+
"headerName": "*",
363+
"headerOrder": "default",
364+
"type": "graphql"
365+
}
366+
]
367+
}
368+
]
369+
}
370+
```
371+
372+
### GraphQL Response Pages
373+
374+
A GraphQL error response page is returned when a request is blocked. This GraphQL response page, like other blocking response pages, can be customized, but the GraphQL JSON syntax must be preserved for them to be displayed correctly. The default page returns the GraphQL status code Blocking Response Page (BRP) and a short JSON error message which includes the support ID.
375+
376+
For example:
377+
378+
```shell
379+
"response-pages": [
380+
{
381+
"responsePageType": "graphql",
382+
"responseActionType": "default",
383+
"responseContent": "{\"errors\": [{\"message\": \"This is a custom GraphQL blocking response page. Code: BRP. Your support ID is: <%TS.request.ID()%>\"}]}"
384+
}
385+
]
386+
```

0 commit comments

Comments
 (0)