INTEGRITY Документация

Настройка защиты от вредоносных запросов GraphQL через API

Используйте Cloudflare GraphQL API чтобы собрать данные о текущем использовании вашего GraphQL API и настроить защиту GraphQL от вредоносных запросов Cloudflare для их логирования или блокировки.

Введение

Размер запроса определяется как количество терминальных полей (листьев) в запросе, а глубина запроса означает самый глубокий уровень, на котором присутствует лист. Например, размер этого запроса будет указан как 4 (terminalField[1-4] all contribute to this counter), а глубина будет указана как 3 (terminalField3 and terminalField4 are at depth level 3).

GraphQL-запрос
{
	terminalField1
	nonTerminalField1(filter: 123) {
		terminalField2
		nonTerminalField2 {
			terminalField3
			terminalField4
		}
	}
}

Сбор статистики GraphQL

Используя новый apiGatewayGraphqlQueryAnalyticsGroups узел в GraphQL API Cloudflare, вы можете получить apiGatewayGraphqlQuerySize и apiGatewayGraphqlQueryDepth измерений.

GraphQL-запрос
query ApiGatewayGraphqlQueryAnalytics(
	$zoneTag: string
	$start: Time
	$end: Time
) {
	viewer {
		zones(filter: { zoneTag: $zoneTag }) {
			apiGatewayGraphqlQueryAnalyticsGroups(
				limit: 100
				orderBy: [
					apiGatewayGraphqlQuerySize_DESC
					apiGatewayGraphqlQueryDepth_DESC
				]
				filter: { datetime_geq: $start, datetime_leq: $end }
			) {
				count
				dimensions {
					apiGatewayGraphqlQuerySize
					apiGatewayGraphqlQueryDepth
				}
			}
		}
	}
}

При выполнении запроса выше вы получите следующий ответ:

Ответ
{
	"data": {
		"viewer": {
			"zones": [
				{
					"apiGatewayGraphqlQueryAnalyticsGroups": [
						{
							"count": 10,
							"dimensions": {
								"apiGatewayGraphqlQueryDepth": 1,
								"apiGatewayGraphqlQuerySize": 11
							}
						},
						{
							"count": 10,
							"dimensions": {
								"apiGatewayGraphqlQueryDepth": 1,
								"apiGatewayGraphqlQuerySize": 2
							}
						}
					]
				}
			]
		}
	},
	"errors": null
}

В примере ответа Cloudflare зафиксировал 10 запросов с глубиной 1 и размером 11, а также 10 запросов с глубиной 1 и размером 2 за выбранный период времени.

Анализ статистики GraphQL

Вы можете использовать ответ для расчета процентилей по атрибутам и задать порог допустимых значений. Например, можно применить простую эвристику вроде 1.5 * p99 для размера или глубины запроса.

Ниже приведён простой скрипт Python, который выводит размер запроса и уровни глубины p-level на основе приведённого выше вывода ответа API GraphQL (в виде JSON-файла):

Python-скрипт
#!/usr/bin/env python3

import json
import numpy as np
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--response", help="Path to the API JSON response file with the apiGatewayGraphqlQueryAnalyticsGroups node", required=True)
args = parser.parse_args()
with open(args.response) as f:
    query_sizes = np.array([], dtype=np.uint16)
    query_depths = np.array([], dtype=np.uint8)
    data = json.load(f)['data']['viewer']['zones'][0]['apiGatewayGraphqlQueryAnalyticsGroups']
    for datapoint in data:
        query_sizes = np.append(query_sizes, [datapoint['dimensions']['apiGatewayGraphqlQuerySize']] * datapoint['count'])
        query_depths = np.append(query_depths, [datapoint['dimensions']['apiGatewayGraphqlQueryDepth']] * datapoint['count'])

    quantiles = [0.99, 0.95, 0.75, 0.5]
    print('\n'.join([f"Query size {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_sizes, quantiles))]))
    print('\n'.join([f"Query depth {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_depths, quantiles))]))

При выполнении запроса выше вы получите следующий вывод:

Пример вывода
./calculator.py --response=response.json
Query size 99th percentile is 11.0
Query size 95th percentile is 11.0
Query size 75th percentile is 11.0
Query size 50th percentile is 6.5
Query depth 99th percentile is 1.0
Query depth 95th percentile is 1.0
Query depth 75th percentile is 1.0
Query depth 50th percentile is 1.0

Ограничение входящих запросов GraphQL

Теперь клиентам API Shield доступны три новых поля в пользовательских правилах:

Например, с помощью API или панели управления можно развернуть следующее правило, которое блокирует запросы с глубокой вложенностью и обращением более чем к 30 полям.

(cf.api_gateway.graphql.query_size > 30 and cf.api_gateway.graphql.query_depth > 7 and cf.api_gateway.graphql.parsed_successfully)