AWS AppSync: Rate and Max Depth Limiting 🔏

Robert Bulmer
5 min readNov 27, 2021
It is important not to leave your applications open to security threats

AWS AppSync

AppSync is a fully managed GraphQL service offered by Amazon Web Services and can be used to build scalable enterprise APIs. A typical AppSync solution consists of small resolvers that can be combined to access various data sources such as databases, HTTP APIs or AWS Lambda.

AppSync

What is Rate Limiting?

Rate limiting helps you to prevent an attack on your API from a single source. We can limit the number of requests that can come from any one source over a fixed time period.

The rate limit is the maximum number of requests from a single IP address that are allowed in a five-minute period. This value is continually evaluated, and requests will be blocked once this limit is reached. The IP address is automatically unblocked after it falls below the limit.

What is Depth Limiting?

In graphQL you can request data from multiple sources by asking for ‘child-like’ fields that are associated to the parent object. For example

query myMultipleDepthQuery{
person(id:1){
firstName,
surname,
address:{
postCode // new depth in our query
}
}
}

Let’s take a look at how attackers can abuse an API if Rate Limiting and Depth Limiting is not protected against.

Malicious Actor

Malicious Queries

With any public API you may experience a malicious user trying to perform a potentially destructive query.

Denial of Service (DoS) attacks occur when a user repetitively calls your API trying to bring down the service with a high volume of requests.

In Serverless architectures a Denial of Service (Dos) attack might also cause a Denial-of-Wallet (DoW) attack. Where malicious users fail to bring down the service because the cloud architecture can scale to manage the malicious volume, and instead rapidly rack up costs in your account.

You can protect against both of these using AppSync Rate Limiting.

Another malicious query possible with GraphQL is requesting very deeply nested queries where data can be cyclical. For example:

query maliciousQuery {
album(id: 1) {
songs {
album {
songs {
album {
...etc..
}

Continuously looping through deeply nested field resolvers in GraphQL can result in many calls to the downstream data sources, be it a Database, Lambda or another internal or external service with HTTP resolvers. The results can be extremely costly.

Genuine reasons for depth limiting include:

  • enforcing good practice for consumers to only request a certain number of cyclic properties.
  • keep requests small and reduce execution times.

Let’s now see how to implement these techniques in the AWS console.

Rate Limiting AWS AppSync

With AppSync you can enable Rate Limiting with AWS WAF:

In your AppSync Settings you can enable your Web Application Firewall (WAF) per AppSync API:

Enabling AWS WAF in AppSync API settings

Now, let’s create a WAF Web ACL:

Important: Ensure that the Web ACL is deployed in the same Region as your AppSync API

Create a new Web ACL in the Region matching your AppSync API

In the AWS resources section, select AWS AppSync and choose your API, in this case my AppSync API is robsAPI .

Add your AppSync API to the Web ACL

In the Add rules section, choose ‘Add my own rules and rule groups’. Specify a Rule name and choose the Rate-based rule option.

Create your own custom rate limit rule

Choose your rate limit amount, in this example I will set 100 requests per IP within a 5 minute interval window.

Apply a sensible rate limit rule to block requests from an IP address

Review your new Rate limit policy and click on Create Web ACL.

Review your web ACL configuration

Now refresh your AppSync Settings and confirm your Web ACL with Rate Limit is now configured and protecting your API 🎉.

Confirmation within AppSync API settings

Depth Limiting in AWS AppSync

As mentioned above, deeply nested queries can impact performance of your API for genuine requests, or it could be an attempt of a Denial of Wallet attack (DoW) for Serverless applications.

Unfortunately, at the time of writing there is currently no way in AppSync to configure a query Depth Limit out-the-box.

However, we can implement this depth limit using Velocity Template Language VTL in our Resolvers.

Below is an example of using the Matches regex to determine the length of selectionSetList. This example enforces a depth limit of 3 and can be placed inside of a AppSync resolver function.

#set($selectionSetList = $ctx.info.selectionSetList)

#foreach ($item in $selectionSetList)
#if($item.matches(".*/.*/./."))
$util.error("Error: Queries with more than 3 levels found. At level - $item")
#end
#end
#return($ctx.prev.result)

Summary

Rate limiting and depth limiting your AppSync endpoints is extremely important in order to help protect your API implementation server from getting overwhelmed with requests. By implementing these two techniques you can help to protect your Serverless AWS applications from Denial of Service (DoS) and Denial of Wallet (DoW) attacks.

Another very important consideration is implementing Depth Limiting and Rate Limiting can also help limit downstream micro-services or legacy non-serverless application that are not as scalable as your top-level API might be.

Additional Resources:

AWS AppSync : https://aws.amazon.com/appsync/product-details/

GraphQL: https://graphql.org/learn/

AWS WAF: https://aws.amazon.com/waf/features/

Getting in touch!

Happy building! 🚀 Thank you for reading.

Writing technical articles helps myself to revisit challenges and complications I have faced before. By sharing my experiences hopefully it can also help others in the community too.

Reach me on linkedIn here: https://www.linkedin.com/in/robertbulmer/

--

--

Architech Insights | Serverless Engineer/Architect UK — Certified SA and DevOps Pro | AWS Community Builder! 🚀