Allow only specific queries
Prevent malicious requests to your GraphQL servers by specifying allowed queries.
For example, you might know that clients send only a limited set of GraphQL queries to your servers. To prevent your GraphQL servers from resolving potentially malicious requests, you specify that list of expected queries so that the servers immediately return an error for queries that are not in that list.
Before you begin
This guide assumes that you use the same names for components like clusters, workspaces, and namespaces as in the getting started. If you have different names, make sure to update the sample configuration files in this guide.
- Set up Gloo Mesh Gateway in a single cluster.
- Deploy sample apps.
- Configure an HTTP listener on your gateway. The
RouteTable
in this guide is not required, because you create a GraphQL-specific route table instead. - Follow the Gloo GraphQL get started guide to define example GraphQL schema and resolvers and configure routing.
Configure policies to allow specific GraphQL queries
You can apply a GraphQLAllowedQueryPolicy
policy at the route level. For more information, see Applying policies.
Review the following sample configuration files.
apiVersion: security.policy.gloo.solo.io/v2
kind: GraphQLAllowedQueryPolicy
metadata:
name: bookinfo-allowed-queries
namespace: bookinfo
spec:
applyToRoutes:
- route:
labels:
route: graphql-bookinfo
config:
allowedQueryHashes:
- <query_hash>
Review the following table to understand this configuration. For more information, see the API docs.
Setting | Description |
---|---|
spec.applyToRoutes | Use labels to configure which GraphQL routes to apply the policy to. This example label matches the app and route from the example route table that you previously applied in the GraphQL getting started guide. If omitted or empty, the policy applies to no routes in the workspace. If more than one GraphQLAllowedQueryPolicy applies to a GraphQL route, the oldest policy is applied. |
allowedQueryHashes | A list of SHA-256 hashed GraphQL queries that you allow the GraphQL server to resolve. Queries that are not sent as hashes are hashed and compared against the list. If a query hash is not in this list, the server returns an error. If omitted or empty, all queries are allowed. |
Verify a GraphQLAllowedQueryPolicy
Save a simple GraphQL query string in an environment variable. For example, let’s say you want to allow only queries that return the title, reviews, and ratings from the Bookinfo app.
export QUERY="query MyProductsForHome { productsForHome { title reviews { reviewer, text }, ratings { reviewer, numStars } } }"
Compute the SHA-256 hash for this query by using the
shasum
command, and save the hash in an environment variable.shasum
prints both the hash and the name of the input file, but because the SHA-256 hash is always 64 characters long, thehead
command takes only the first 64 characters of the output.export QUERY_SHA256=$(echo -n $QUERY | shasum -a 256 | head -c 64) echo $QUERY_SHA256
Example hash:
01f818a19df3fbe19940b7af2e0fa5adcf1884686bb4d3e289623d5fa1875231
Apply the following example policy in your cluster. This policy creates an allowlist that includes only the hash for the specified query, and applies to the
graphql-bookinfo
route that you created in the Get started guide.kubectl apply -f - << EOF apiVersion: security.policy.gloo.solo.io/v2 kind: GraphQLAllowedQueryPolicy metadata: name: bookinfo-allowed-queries namespace: bookinfo spec: applyToRoutes: - route: labels: route: graphql-bookinfo config: allowedQueryHashes: - ${QUERY_SHA256} EOF
To send a cURL request with the allowed query to the GraphQL services, encode the query in JSON format. Note that GraphQL clients typically convert the request automatically.
export QUERY_JSON={\"query\":\"$QUERY\"}
Send the allowed GraphQL query to the route through the ingress gateway, and format the output with
You receive the expected response, because the query was allowed:jq
.{ "data": { "productsForHome": [ { "title": "The Comedy of Errors", "reviews": [ { "reviewer": "Reviewer1", "text": "An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!" }, { "reviewer": "Reviewer2", "text": "Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare." } ], "ratings": [ { "reviewer": "Reviewer1", "numStars": 5 }, { "reviewer": "Reviewer2", "numStars": 4 } ] } ] } }
Now, save a different GraphQL query that is not listed in the policy in an environment variable.
export BAD_QUERY="query MyProductsForHome { productsForHome { title } }" export BAD_QUERY_JSON={\"query\":\"$BAD_QUERY\"}
Send the query to the same route.
This time, you receive an error from the GraphQL server because the query is not in the route’s allowlist:{ "errors": [ { "message": "hash ba7faf706579b441e281376ba5a87d5047e79eb52dcf6ac0eb34eb85ed53b053 not found in allowlist for query: 'query MyProductsForHome { productsForHome { title } }'" } ] }
Cleanup
You can optionally remove the resources that you set up as part of this guide.
kubectl -n bookinfo delete GraphQLAllowedQueryPolicy bookinfo-allowed-queries