Внутреннее устройство
Базовые принципы, определившие архитектуру решения:
Приложение (тестируемый экземпляр) идентифицируется парой
(BaseURL, OAS)
.Таким образом, если в каком-либо Приложении изменился базовый URL или у спецификации API изменился хэш -- по умолчанию образуется новое Приложение.
Один (пользовательский) запрос на скан порождает "под капотом" множество задач нескольким инструментам, которые выбираются исходя из типа задачи.
При постобработке выходных данных мы стараемся обеспечить удобство последующей работы с обнаруженностями, приводим отчёты к единой форме, в случае неоднозначности приоритет отдаётся сохранению сути оригинальных данных.
Система разграничения доступа основана на двух принципах:
Доступ к данным тестирования Приложений задаётся в контексте Продукта.
По умолчанию никому нельзя. Закрытый перечень тех, кому можно.Ограничение возможности запуска скана (активных действий)
Создать запрос на скан могут все, но запустить его -- только субъекты из закрытого перечня.
Сущность Продукт -- по сути лишь группа Приложений (экземпляров тестируемых сервисов) для удобства организации.
Структура данных приложения
СУБД не используются: только файловая система и минимальный набор необходимых блокировок, реализованных на стороне приложения.
Внешние проявления упомянутых блокировок, намеренно оставленные для возможности отладки отдельных задач на скан:
.sr_lock
не позволяет создать новый запрос на скан в контексте данного Приложения при уже имеющемся запросе (или оставшемся с предыдущего неуспешного запуска);.scan_happened
предохраняет от повторного запуска той же задачи на скан (т.е. в контексте Скана) и соотв. перезаписи журналов и результатов.
Данные упорядочены в виде трёхуровевой структуры каталогов (не считая оставляемых под "scan_N" рабочих каталогов сканеров):
APPDATA_PATH/
productN/
product-info.json
appN/
.sr_lock
app-info.json
r-<tool>-<ts>.json
...
scanN/
.scan_happened
sr.json
...
Метаданные продукта:
title: str
description: str
avail_to: list[email] # email: str
Метаданные экземпляра приложения:
title: str
description: str
type_: str # "WEB_APP" | "REST_API"
// Формальная JSON-схема запроса на скан:
{
"type": "object",
"required": ["endpoints"],
"additionalProperties": false,
"properties": {
// Что сканировать
"endpoints": {"type": "array",
"items": {"type": "string"}},
// Доп. заголовки для авторизации запросов или иной специфики тестируемого сервиса
"headers": {"type": "array",
"items": {"type": "array", "minItems": 2, "maxItems": 2,
"prefixItems": [{"type": "string"},
{"type": "string"}]}},
// OpenAPI-спецификация (без неё предполагается DAST-тестирование web-сервиса
// с ней -- негативное тестирование API, Fuzzing)
"oas": {"type": "object", "properties": {
"file": {"type": "string"},
"url": {"type": "string"}
}, "oneOf": [{"required": ["file"]},
{"required": ["url"]}]}
}
}
Наличие OpenAPI-спецификации в запросе на скан определяет режим тестирования и набор соотв. инструментов.
Тип сущности (Продукт или Приложение) определяется наличием в каталоге файла product-info.json
или app-info.json
.
Все Приложения (и данные их тестирования), собранные под Продуктом, доступны пользователям в соответствии с avail_to
в метаданных Продукта.