Developers are increasingly embracing GraphQL as a preferred method to build APIs. GraphQL simplifies retrieving data from multiple sources, streamlining data access and aggregation. By querying multiple data sources with one POST request from a single endpoint, developers using GraphQL can precisely request the data they need from various sources. This approach helps solve limitations encountered in REST API architectures, where problems like under-querying (requests lacking all the necessary data) or over-querying (requests going to multiple endpoints and gathering excessive data) can occur.
GraphQL is the optimal choice for microservices architectures, as it grants clients the ability to retrieve only the essential data from each service or data source. This fosters heightened flexibility and agility, which are critical components to thrive in a modern business environment.
With a greater degree of access and flexibility, GraphQL APIs also present a more extensive attack surface that’s enticing to bad actors. Despite being relatively new, GraphQL is still prone to many of the same vulnerabilities found in other API architectures. Fortunately, you can protect GraphQL APIs from these common threats by leveraging some of your existing infrastructure and tools.
This tutorial helps build an understanding of how to deliver and secure GraphQL APIs. We illustrate how to deploy an Apollo GraphQL server on F5 NGINX Unit with F5 NGINX Plus as the API gateway. In addition, we show how to deploy F5 NGINX App Protect WAF at the API gateway for advanced security and use F5 NGINX Management Suite to configure your WAF and monitor for potential threats. This setup also allows you to use NGINX App Protect WAF to detect attacks like SQL injection.
Follow the steps in these sections to complete the tutorial:
Before you begin this tutorial, you need the following:
NGINX Management Suite integrates several advanced features into a unified platform to simplify the process of configuring, monitoring, and troubleshooting NGINX instances. It also facilitates the management and governance of APIs, optimizes application load balancing, and enhances overall security for organizations.
Follow these steps to install and configure NGINX Management Suite:
NGINX Unit is an efficient and streamlined runtime application with a lightweight design, making it an ideal choice for organizations seeking high performance without compromising speed or agility. It’s an open-source server that can handle TLS, request routing, and run application code. You can learn more about NGINX Unit on its Key Features page.
In this tutorial, we use Express as a Node.js web application framework on NGINX Unit that offers extensive capabilities for constructing an Apollo GraphQL server. At the time of this writing, the current version is Apollo Server 4.
Follow these steps to deploy NGINX Unit and install the Apollo GraphQL server:
Select a suitable environment to deploy an NGINX Plus instance. In this tutorial, we use an AWS Ubuntu instance and set up an API gateway reverse proxy using NGINX Plus. We then deploy NGINX App Protect WAF in front of our API gateway for added security.
Follow these instructions to install NGINX Plus and NGINX App Protect WAF:
load_modules
in the nginx.conf directory. load_module modules/ngx_http_js_module.so;load_module modules/ngx_stream_js_module.so;
load_module modules/ngx_http_app_protect_module.so;
app_protect_enable on;
Create a GraphQL policy configuration in the directory /etc/app_protect/conf. For further information on how to create an NGINX App Protect WAF policy, please refer to the relevant guidelines.
Here is an example GraphQL policy configuration:
{ "name": "graphql_policy",
"template": {
"name": "POLICY_TEMPLATE_NGINX_BASE"
},
"applicationLanguage": "utf-8",
"caseInsensitive": false,
"enforcementMode": "blocking",
"blocking-settings": {
"violations": [
{
"name": "VIOL_GRAPHQL_FORMAT",
"alarm": true,
"block": false
},
{
"name": "VIOL_GRAPHQL_MALFORMED",
"alarm": true,
"block": false
},
{
"name": "VIOL_GRAPHQL_INTROSPECTION_QUERY",
"alarm": true,
"block": false
},
{
"name": "VIOL_GRAPHQL_ERROR_RESPONSE",
"alarm": true,
"block": false
}
]
}
To enforce GraphQL settings, update the app_protect_policy_file
field with the GraphQL policy name in the nginx.conf file. Once you have updated the file, perform an NGINX reload to enforce the GraphQL settings.
Here is an example of the nginx.conf file that includes an NGINX App Protect policy:
user nginx; worker_processes 4;
load_module modules/ngx_http_js_module.so;
load_module modules/ngx_stream_js_module.so;
load_module modules/ngx_http_app_protect_module.so;
error_log /var/log/nginx/error.log debug;
events {
worker_connections 65536;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen <port>;
server_name <name>;
app_protect_enable on;
app_protect_security_log_enable on; # This section enables the logging capability
app_protect_security_log "/etc/app_protect/conf/log_sm.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
app_protect_security_log "/etc/app_protect/conf/log_default.json" /var/log/app_protect/security.log;
proxy_http_version 1.1;
location / {
client_max_body_size 0;
default_type text/html;
proxy_pass http://<ip addr>:<port>$request_uri;#<ip addr> of Nginx unit
}
location /graphql {
client_max_body_size 0;
default_type text/html;
app_protect_policy_file "/etc/app_protect/conf/graphql_policy.json";
proxy_pass http://<ip addr>:<port>$$request_uri; #<ip addr> of Nginx unit
}
}
}
$ nginx -s reload
Now you can test your configuration by following these steps:
$ curl -X PUT --data-binary @demo.json --unix-socket /var/run/control.unit.sock http://localhost/config
{ "success": "Reconfiguration done."
}
$ curl -X POST http://3.X.X.X:4003/graphql/ -H "Content-Type:application/json" -d '{"query": "query {hello OR 1=1;} "}'
<html><head><title>Request Rejected</title></head><body>The requested URL was rejected. Please consult with your administrator.<br><br>Your support ID is: 7313092578494613509<br><br><ahref='javascript:history.back();'>[GoBack]</a></body><html>
attack_type="Non-browser Client,Abuse of Functionality,SQL-Injection,Other Application Activity,HTTP Parser Attack",blocking_exception_reason="N/A",date_time="2023-07-05 21:22:38",dest_port="4003",ip_client="99.187.244.63",is_truncated="false",method="POST",policy_name="graphql_policy",protocol="HTTP",request_status="blocked",response_code="0",severity="Critical",sig_cves="N/A,N/A",sig_ids="200002147,200002476",sig_names="SQL-INJ expressions like ""or 1=1"" (3),SQL-INJ expressions like ""or 1=1"" (6) (Parameter)",sig_set_names="{SQL Injection Signatures},{SQL Injection Signatures}",src_port="64257",sub_violations="HTTP protocol compliance failed:Host header contains IP address",support_id="7313092578494613509",
In this tutorial, you learned how to set up an Apollo GraphQL Server on NGINX Unit, deploy NGINX Plus as an API gateway, and secure your GraphQL APIs with NGINX App Protect WAF in front of your API gateway.
You can also use NGINX Management Suite Security Monitoring to identify and block common advanced threats before they compromise your GraphQL APIs. This simple architecture defends GraphQL APIs from some of the most common API vulnerabilities, including missing authentication and authorization, injection attacks, unrestricted resource consumption, and more.
Test drive NGINX today with a 30-day free trial of the API Connectivity Stack, which includes NGINX Plus, NGINX App Protect, and NGINX Management Suite.
"This blog post may reference products that are no longer available and/or no longer supported. For the most current information about available F5 NGINX products and solutions, explore our NGINX product family. NGINX is now part of F5. All previous NGINX.com links will redirect to similar NGINX content on F5.com."