
Вендор-нейтральный формат графа атак NDJSON с таксономией узлов и рёбер, маппингами AWS/GCP/Azure, правилами вывода и базой данных экспозиций для инструментов наступательной безопасности.
Граф атак, который действительно можно передать кому-то другому.
Каждый продукт безопасности на основе графов хранит ваш граф атак внутри проприетарного хранилища. Вы не можете его экспортировать, сравнить два сканирования, поместить его в систему контроля версий или запросить его чем-либо, кроме собственного UI вендора. Когда проект заканчивается, граф уходит вместе с ним.
RAGE — это вендор-нейтральный формат файлов для графов наступательной безопасности, плюс открытый корпус, который придаёт ему смысл: таксономия узлов и рёбер, маппинги AWS/GCP/Azure и рецепты сбора, а также правила вывода рёбер. Один файл. Любой язык. Взял и пошёл.
Статус: ранний черновик (spec_version: 0.1). Пока не стабилен; отзывы и pull request'ы приветствуются.
Граф RAGE — это один файл NDJSON (один JSON-объект на строку). Строка 1 — это манифест;
каждая другая строка — это запись с тегом kind.
{"kind":"manifest","spec_version":"0.1"}
{"kind":"node","node_id":"gcp|proj-a|gcp:iam:service-account|sa-deploy","node_type":"ServiceAccount"}
{"kind":"node","node_id":"gcp|proj-a|gcp:iam:service-account|sa-admin","node_type":"ServiceAccount"}
{"kind":"node","node_id":"gcp|proj-a|gcp:storage:bucket|bucket-crown","node_type":"ObjectStorage"}
{"kind":"edge","type":"CanImpersonate","source":"gcp|proj-a|…|sa-deploy","target":"gcp|proj-a|…|sa-admin"}
{"kind":"edge","type":"CanReadData","source":"gcp|proj-a|…|sa-admin","target":"gcp|proj-a|…|bucket-crown"}
{"kind":"finding","resource_id":"gcp|proj-a|…|bucket-crown","severity":"critical"}
Цепочка из двух переходов, соблюдающая таксономию: sa-deploy может имперсонировать sa-admin (ребро идентичность-к-идентичности), который может читать бакет с главными ценностями (идентичность-к-хранилищу).
Прочитайте это в три строки на любом языке:
for line in open("graph.rage.ndjson"): rec = json.loads(line) # switch on rec["kind"]
jq 'select(.kind=="edge" and .type=="CanImpersonate")' graph.rage.ndjson
| kind | обязательные поля | назначение |
|---|---|---|
manifest | spec_version | строка 1: версия + опциональные счётчики/область/производитель |
node | node_id, node_type | ресурс или идентичность |
edge | source, target, type | возможность или связь |
fact | fact_id | нормализованное наблюдение, на основе которого построен граф |
evidence | evidence_id, content_hash | защищённая от подделки квитанция (операция API/сбора) |
finding | resource_id, severity | экспозиция |
surface / path | - | опциональные виды расширений |
Цепочка происхождения — это evidence (API), затем fact, затем edge/finding, связанные идентификаторами.
node_type и type рёбер берутся из открытых реестров в vocab/. Всё
остальное — опциональное обогащение. См. spec/format.md.
Формат — это лишь половина RAGE. Другая половина — это общий корпус, который придаёт типам
смысл, чтобы два независимых инструмента соглашались в том, что такое CanImpersonate и где может утечь учётные данные:
vocab/): 105 типов узлов в 10 классах, 80 типов рёбер в 9 категориях.providers/): 219 нативных типов ресурсов в AWS, GCP и Azure, каждый сопоставлен с обобщённым типом узла вместе с вызовами, которые его перечисляют.rules/): контракт в rules/derivation.json плюс 2 400+ исполняемых правил match/where/emit для того, как выводятся рёбра.exposure-db/): 1 049 сопоставленных мест утечки учётных данных, каждое привязано к ребру RAGE, которое оно порождает, и к рецепту, который его читает.Весь корпус, в удобочитаемом виде, находится в TAXONOMY.md.
RAGE спроектирован так, чтобы любой мог его создавать или потреблять. Формат — это контракт; инструменты взаимозаменяемы, а список открыт.
RAGE — это формат, Thunderstorm его создаёт, Blaze его исследует.
| реализация | роль | где |
|---|---|---|
| Thunderstorm | производитель: облачный коллектор только для чтения + движок вывода | github.com/ustayready/thunderstorm |
| ваш инструмент здесь | производитель или потребитель | создавайте или читайте .rage.ndjson — и он будет взаимодействовать |
Всё, что читает или записывает формат, говорит на RAGE. Соответствующие производители и движки
соответствуют реестрам в этом репозитории; RAGE не зависит ни от одного из них. См.
COMPATIBILITY.md о том, как реализации привязываются к spec_version.
spec/format.md - проводной формат (записи, грамматика node_id, .rage.zip, область).spec/edges.md - семантика рёбер: направление/обход, state, weight/walkable, канонизация.spec/rules.md - семантика вычисления правил: неподвижная точка, слияние состояний, каталог функций.schemas/ - JSON Schema для всех 8 видов записей.vocab/ - node-types.json + edge-types.json + conditions.json.rules/derivation.json - контракт вывода рёбер (для каждого ребра: условия + разрешения/триггеры для каждого облака).rules/{derived,explicit}/** - исполняемый корпус из 2 400+ правил match/where/emit.providers/{aws,gcp,azure}.json - маппинги нативных типов в обобщённые + рецепты узлов + рецепты фактов.exposure-db/{aws,gcp,azure}.json + vocabulary.json - База экспозиций (1 049 мест утечки).TAXONOMY.md - весь корпус, в удобочитаемом виде (сгенерирован из реестров выше).tools/rage_engine.py - эталонный движок правил: прогоняет корпус выведенных правил по графу до неподвижной точки.validate/ - валидаторы записей (полная JSON Schema), реестров, строк разрешений и корпуса правил.examples/ - минимальный валидный граф, задействующий все 8 видов записей.python3 -m venv .venv && ./.venv/bin/pip install -r requirements.txt
./.venv/bin/python validate/rage_validate.py examples/minimal.rage.ndjson # full JSON Schema + refs
./.venv/bin/python validate/check_registries.py # registry integrity
./.venv/bin/python validate/check_rules.py # rule corpus vs vocab
CI запускает всё вышеперечисленное плюс гейт отсутствия дрейфа gen_taxonomy.
Apache-2.0 (см. LICENSE).