Hetzner Cloud Audit Skills

Cloud & Container Security v0.8.2 · 23.09.2026 активный

Агентные навыки для аудита безопасности и затрат инфраструктуры Hetzner с подтверждением путей атак.

v0.8.2
23.09.2026 current

Установка
npx skills add https://github.com/jpolec/hetzner-cloud-audit-skills/tree/v0.8.2 --skill hetzner-security-audit
uvx hetzner-audit doctor --report-dir ./_output
uvx hetzner-audit audit --format markdown --output _output/audit.md
uvx hetzner-audit map --format svg --output _output/architecture.svg
git clone https://github.com/jpolec/hetzner-cloud-audit-skills
cd hetzner-cloud-audit-skills
uv run hetzner-audit audit --format markdown --output _output/audit.md
git clone https://github.com/jpolec/hetzner-cloud-audit-skills && cd hetzner-cloud-audit-skills
uv run hetzner-audit audit --input benchmarks/scenarios/v0.1-insecure.json --format markdown --output demo.md
unset HCLOUD_TOKEN
показать оригинал переведено ИИ

Аудит навыков для Hetzner Cloud

Знаете ли вы свой Hetzner Cloud: что выставлено наружу, что тратится впустую и что исправить следующим.

License: Apache-2.0 PyPI Python 3.11+ Free and open source Read-only

Бесплатно и с открытым исходным кодом (Apache-2.0). Никаких аккаунтов, SaaS или телеметрии. hetzner-audit запускается на вашей машине и не отправляет ничего никуда, кроме read-only GET запросов к API Hetzner.


Действительно ли вы знаете свою инфраструктуру Hetzner?

  • Доступна ли какая-либо база данных из интернета? Или только через одно неосторожное правило файрвола?
  • Может ли скомпрометированный preview-бокс достичь вашей продакшн-базы? Файрволы Hetzner Cloud не фильтруют приватные сети, поэтому, скорее всего, может.
  • Платите ли вы за то, чем никто не пользуется? Неподключённые тома, остановленные серверы, за которые всё равно списываются деньги, устаревшие типы серверов.
  • Какие три сервера составляют половину вашего счёта? Какие из них можно сделать меньше или запустить на ARM?
  • Что изменилось с прошлой недели? Новый публичный порт или файлвол, который молча исчез?

Один read-only токен и одна команда отвечают на провайдерскую часть всего этого; детали хостов (UFW, Docker, базы данных) поступают из опционального read-only бандла, который вы запускаете сами. Вы получаете карту архитектуры, представление о радиусе поражения, разбивку затрат на каждую VM и ранжированный список того, что делать дальше. Каждый вывод подкреплён доказательствами.

Architecture diagram of an example Hetzner project: summary tiles, trust sources, private network, location columns, role tiers, recommended actions, and legend

Пример проекта, сгенерированного hetzner-audit map из read-only токена. Публичные IP-адреса никогда не отображаются.

Независимый open-source проект. Не связан с Hetzner, Cloudflare или любым другим провайдером, которого он распознаёт, и не одобрен ими. v0.8 — альфа: проверяйте каждый результат с высоким влиянием перед тем, как действовать на его основе.


1. Что вы получаете

Безопасность Публичная экспозиция, обход Cloudflare, радиус поражения в общих приватных сетях и пути через границы доверия
Затраты Стоимость каталога на VM, концентрация расходов, идентифицируемые потери и кандидаты на правкий размер или ARM
Архитектура AWS-стиль диаграммы: сетевая зона, приватная сеть, локации, уровни ролей и источники доверия
За пределами API Файрвол хоста, слушатели и Docker из бандла, запускаемого владельцем; дрифт Terraform; выделенные серверы Robot; Object Storage; Kubernetes; несколько проектов
Действия Ранжированный список дел: экономия, уровень доказательств, риск действий и конкретный следующий шаг
Отслеживание изменений Снапшоты с таймстемпами, diff с учётом покрытия, GitHub Action и SARIF
Готовность к агентам Поставляется как навык SKILL.md для Claude Code, OpenAI Codex и совместимых агентов
Полный список того, что оно распознаёт (Cloudflare и другие CDN, Tailscale и другие mesh VPN, туннели, хостовые файрволы, Docker, базы данных, Robot, Object Storage, Kubernetes) с честным статусом live/fixture на каждую позицию: What hetzner-audit sees.

Чем это отличается от дашборда затрат или сканера портов: оно разделяет то, что доказано, от того, что лишь подозревается.

Результат Значение
confirmed / reachable Каждое звено в цепочке подтверждено доказательствами: сеть, файрвол, хостовое правило, слушатель, конфиг сервиса
reachable_after_pivot Каждый слой пропускает трафик, но только после компрометации другого хоста, чего доказательства не подтверждают
needs_validation / cloud_path_present Топология Hetzner позволяет это, но доказательств на уровне хоста или рантайма нет
unknown Путь не обнаружен, но покрытие слишком неполное, чтобы заявлять об изоляции

Отсутствующий коллектор сообщается как пробел. Он никогда не сообщается как «безопасно». Подтверждённые экономии остаются нулевыми, пока нет доказательств. Инструмент никогда не завышает цифры.


Два способа начать

AI agent skill: быстрее, рекомендуется Командная строка
Установка npx skills add https://github.com/jpolec/hetzner-cloud-audit-skills/tree/v0.8.2 --skill hetzner-security-audit uvx hetzner-audit …, или git clone и uv run
Запуск Спросите у агента: «аудит моей инфраструктуры Hetzner» hetzner-audit audit, hetzner-audit map
Что происходит Агент запускает preflight, снапшот, аудит и диаграммы. Затем объясняет находки простым языком и ведёт через исправления. Markdown, JSON, SARIF и SVG файлы попадают в папку вывода
Подходит для Первого взгляда, вопросов вроде «может ли staging достучаться до prod?» и توجيهного remediation CI, cron, скриптов и повторяющихся отчётов

Оба используют один и тот же read-only движок и одни и те же правила доказательств. Работает с Claude Code, OpenAI Codex и другими SKILL.md-совместимыми агентами.


2. Быстрый старт

Шаги 1 и 2 одинаковы для обоих способов. Затем выбирайте A (агент) или B (командная строка).

Шаг 1: создайте read-only токен

В Hetzner Console: ваш проект → Security → API tokens → Generate API token → Read.

Никогда не выбирайте Read & Write; инструмент делает только GET запросы. Иллюстрированное руководство по токену охватывает каждый шаг, включая отзыв.

Token setup: Project → Security → API tokens → Read

Шаг 2: загрузите его в терминал без утечек

printf 'Hetzner read-only token: '
IFS= read -rs HCLOUD_TOKEN; printf '\n'
export HCLOUD_TOKEN

Это держит токен вне истории шелла. Никогда не вставляйте его в промпт агента, аргумент команды, .env, скриншот или отчёт.

Вариант A: AI agent skill (около 30 секунд)

npx skills add https://github.com/jpolec/hetzner-cloud-audit-skills/tree/v0.8.2 --skill hetzner-security-audit

Часть /tree/v0.8.2 привязывает skill к тегированному релизу, что вы и хотите для инструмента безопасности. Уберите, чтобы следовать за main (разработка).

Запустите ваш агент (например claude или codex) из того же терминала, чтобы он унаследовал HCLOUD_TOKEN не видя его значения. Затем просто спросите:

audit my Hetzner infrastructure

Или перейдите сразу к тому, что вас интересует:

draw the architecture of my Hetzner project
can anything reach my production database?
where am I overpaying on Hetzner?
what changed since the last audit?

Агент проверяет настройку через doctor, подтверждает с вами область проекта и собирает read-only снапшот. Затем загружает сетевые, Linux, Docker, PostgreSQL, Redis, бэкап или cost-наставления только когда доказательства делают это релевантным. Для работы cost-first есть отдельный skill: --skill hetzner-cost-audit.

Вариант B: инструмент командной строки

uvx hetzner-audit doctor --report-dir ./_output              # preflight: token, API, project scope
uvx hetzner-audit audit --format markdown --output _output/audit.md
uvx hetzner-audit map --format svg --output _output/architecture.svg

uvx запускает PyPI пакет без установки. Можно также работать из исходников:

git clone https://github.com/jpolec/hetzner-cloud-audit-skills
cd hetzner-cloud-audit-skills
uv run hetzner-audit audit --format markdown --output _output/audit.md

Чтобы закрепить релиз, используйте uvx --from 'git+https://github.com/jpolec/hetzner-cloud-audit-skills@v0.8.2' hetzner-audit --help. Для CI см. GitHub Action.

doctor подтверждает, что токен работает, не печатая его. Показывает область проекта (количество серверов, файрволов, сетей и томов), чтобы вы могли проверить, выбрали ли правильный проект. Также предупреждает, если отчёты попадут в Git-отслеживаемую директорию.

Токена ещё нет? Попробуйте демо

git clone https://github.com/jpolec/hetzner-cloud-audit-skills && cd hetzner-cloud-audit-skills
uv run hetzner-audit audit --input benchmarks/scenarios/v0.1-insecure.json --format markdown --output demo.md

Это запускается против синтетического, намеренно небезопасного фикстуры. Вы также можете просто прочитать пример отчёта по безопасности и пример отчёта по затратам.

Когда вы закончите

unset HCLOUD_TOKEN   # then revoke the token in Hetzner Console

Относитесь к отчётам как к конфиденциальным. Они содержат имена, частные адреса и топологию. Не коммитьте реальные отчёты или снимки в публичный репозиторий.


3. Отчёт: что исправить, в каком порядке

Audit summary of an example project: no database open to the Internet, one indirect pivot path, six confirmed findings including Storage Box exposure

Каждый аудит начинается с трёх пунктов:

  1. На первый взгляд. Область, подтверждённые находки, гипотезы, которые всё ещё требуют хостового или рантайм-доказательств, и пробелы в сборе данных. Затраты разбиты на немедленно выявляемые потери (телеметрия не нужна), кандидаты на оптимизацию и экономию в трёх уровнях (теоретическая, ожидаемая, измеренная), а также концентрация расходов (например, «топ-3 ВМ = 56% расходов»). Изменения провайдера за последние 30 дней также учитываются.
  2. Что знает этот аудит. Покрытие по затратам, CPU, RAM и дисковой телеметрии, владельцам, бэкапам и хостовым доказательствам; каждый использованный источник доказательств (API, хостовые бандлы, Terraform, Robot, Object Storage, kubectl, чек-лист владельца); и для каждого сервера с хостовым бандлом — что признаёт каждый слой и что достижимо end-to-end.
  3. Рекомендуемые действия, ранжированные. У каждого есть экономия, уровень доказательств (HIGH, MEDIUM или LOW, с причиной), риск действия и конкретный следующий шаг. Например:
    • «Перенести jobs-1 с устаревшего cx22. Преемник того же семейства сейчас недоступен в этом локации. Доступная замена: cpx22, +15.00/мес. ARM-альтернатива: cax11, +1.50/мес, требует multi-arch образы и бенчмарк».

Где исправление — это простая команда hcloud (защита от удаления, метки, удаление правила всех портов), действие включает предлагаемую команду для человеческого ревью. Такие команды требуют токен Read & Write, поэтому hetzner-audit никогда не запускает их, а имена провайдеров санитизированы, чтобы сфальсифицированное имя не могло инжектить шелл-синтаксис.

Затем следуют детальные находки, каждая с цепочкой доказательств, влиянием и способом устранения. Косвенные пути держатся отдельно от прямого воздействия: база данных, доступная только через пивот через другой хост, не сообщается как интернет-экспонированная.


4. Безопасность: экспозиция и радиус поражения

Из коробки API-only слой проверяет:

  • Публичную экспозицию около 30 чувствительных TCP и UDP сервисов и диапазонов: SSH, базы данных, Docker, Kubernetes API и kubelet, etcd, Vault, Consul, Kafka, AMQP, Elasticsearch, RDP, SMB, SNMP, memcached UDP, и диапазон NodePort.
  • Качество файрвола:
    • правила, открывающие все порты в интернет;
    • файрволы, которые ничего не защищают;
    • дрифт IPv4/IPv6;
    • дублирующие правила;
    • публичные серверы без файрвола.
  • Edge: веб-ориджины, открытые для любого адреса, пока пир-серверы принимают только edge-прокси. Cloudflare, Fastly, Bunny CDN, AWS CloudFront, Gcore и Imperva распознаются по их опубликованным диапазонам (каждый список датирован и проверяется через scripts/update_provider_ranges.py --check).
  • Mesh VPN и туннели: админ-доступ Tailscale, Headscale, NetBird, WireGuard и ZeroTier распознаётся, и их UDP-порты не считаются экспозицией. Серверы, не принимающие ничего из интернета, считаются хорошим паттерном, с указанием любого туннельного агента (Cloudflare Tunnel, ngrok, frp) при наличии хостового бандла.
  • Латеральное перемещение: пути от несвязанных ворклоудов к базам данных, идентичности и хостам секретов в общих приватных сетях.
  • Load balancer'ы: интернет → load balancer → целевые эджи в графе атак, и бэкенды, также достижимые напрямую. Плюс:
    • чистый HTTP;
    • HTTP без редиректа на HTTPS;
    • нездоровые таргеты;
    • единственный таргет;
    • вообще никаких таргетов.
  • Сертификаты: просроченные, скоро истекающие, не продлевающиеся или неиспользуемые.
  • DNS: записи, указывающие на IP, не принадлежащие проекту (риск захвата) или на приватные адреса.
  • Storage Boxes: доступные извне Hetzner или без плана снапшотов.
  • SSH-ключи: слабые алгоритмы (DSA, RSA ниже 3072 бит) и ключи старше двух лет. Сила ключа читается до того, как материал ключа замаскируется.
  • Жизненный цикл и устойчивость:
    • операционные системы после конца поддержки;
    • устаревшие типы серверов;
    • отключённая защита от удаления;
    • отсутствующие бэкапы;
    • реплики вне spread placement group.
  • Гovernance:
  • серверы, которые политика не может оценить, потому что отсутствуют метки environment или role;
  • отсутствующие метки владельца (owner);
  • нарушения политики окружения (environment-policy).

Помечайте базы данных и хосты секретов меткой sensitivity=high, чтобы обнаружение не зависело от имён серверов.

  • Исходящий трафик (Egress): Hetzner Cloud Firewalls разрешают весь исходящий трафик до тех пор, пока у файрвола нет хотя бы одного исходящего правила. Отчёт подсчитывает серверы, которые могут подключиться куда угодно, выделяя хосты с данными и идентичностью, а ваша политика может запретить это для роли ([roles.db] internet_egress = false или ["tcp/443"]), что вызывает HETZ-EGR-001.
  • Цели балансировщика нагрузки по серверу, селектору меток или IP-адресу. IP-цель разрешается в Cloud-сервер или выделенный сервер Robot, где это возможно, и иначе остаётся видимой как эндпоинт, поэтому гибридный путь через LB никогда не теряется.

Каждое замечание также указывает, выполнялось ли его правило против живого проекта Hetzner или только против фикстур.

Вы контролируете шум. Добавьте audit.ignore=true или audit.ignore.HETZ-BCP-001=true для одного правила к ресурсу, который намеренно отличается, например к временному билд-боксу. Замечание перемещается в раздел Suppressed by owner labels отчёта вместо того чтобы исчезнуть молча.

Hetzner Cloud Firewalls не фильтруют трафик частной сети (Hetzner FAQ). Каждый участник частной сети имеет маршрут к любому другому участнику, и правила файрвола с диапазонами частных источников не влияют на этот трафик. Достижимость порта определяется слушателем, его bind-адресом, хостовым файрволом и управлением приложением. hetzner-audit моделирует это так: частный путь — cloud_path_present, пока доказательства хоста не подтвердят или не опровергнут его.

Per-VM connectivity of an example project: entry points, private network, high-value hosts, and blast radius

Задавайте прямые вопросы:

hetzner-audit ask "Can the Internet reach any database?" --input snapshot.json
hetzner-audit path --from staging-worker --to prod-db --protocol tcp --port 5432 --input snapshot.json
hetzner-audit explain HETZ-XLY-002-0123456789abcdef --input snapshot.json

explain выводит сохранённую цепочку доказательств, путь атаки, вызов верификатора, неразрешённые предварительные условия и способ устранения. Он не просит модель придумать новое объяснение.

Attack path from staging-worker to prod-db with cited evidence

API Hetzner не видит слушателей хоста, публикацию портов Docker, PostgreSQL HBA, Redis ACL или память гостя. Без доказательств хоста такие замечания остаются needs_validation и показывают, чего не хватает. Следующий раздел закрывает этот пробел.


5. Доказательства хоста: то, что не видит API

hetzner-audit host-bundle > host-bundle.sh          # review it: a fixed list of read-only commands
ssh web-1 'sudo HETZNER_AUDIT_SERVER=web-1 sh -s' < host-bundle.sh > _output/web-1.bundle
hetzner-audit audit --host-bundle _output/web-1.bundle --output _output/audit.md
hetzner-audit map --format svg --view host --host-bundle _output/web-1.bundle --output _output/host.svg

hetzner-audit никогда не подключается к вашим серверам. Вы запускаете скрипт сами; он выводит правила UFW, nftables и iptables, слушателей (ss), эффективные настройки sshd, настройки изоляции Docker и опубликованные порты, pg_hba.conf и состояние bind/ACL Redis. Он не выводит переменные окружения, пароли (Redis показывает только <set>) и хеши ACL.

С бандлом публичная доступность определяется пересечением потоков: Cloud Firewall ∩ хостовый файрвол ∩ слушатель. Замечание становится confirmed, когда каждый слой допускает порт, и rejected, когда доказательства хоста его опровергают. Если слой не удалось прочитать (например, UFW без root, цепочка прыжков firewalld или нет ss), замечание остаётся needs_validation. Неизвестное никогда не считается безопасным.

Что оно находит, чего не может найти один API:

  • Опубликованные порты Docker, обходящие хостовый файрвол. Docker пробрасывает опубликованные порты до того, как сработают входные правила UFW или nftables. Порт, «закрытый» в UFW, может быть открыт, с только Cloud Firewall на пути.
  • sshd, принимающий пароли, вход root по паролю или пустые пароли.
  • Отсутствие хостового файрвола вообще, поэтому Cloud Firewall — единственный слой.
  • Базы данных, слушающие на всех интерфейсах, и неаутентифицированный Redis или PostgreSQL, доступные через частную сеть, которую Cloud Firewall не фильтрует.
  • pg_hba.conf в порядке первого совпадения. Ранний reject скрывает поздний trust только когда он действительно его покрывает (тип соединения, семейство адресов, диапазон).
  • Контейнеры, которые привилегированные, монтируют Docker-сокет или хостовые пути, или имеют опасные capabilities.

Per-VM host layers of an example project: cloud firewall, host firewall, listeners, Docker bypass, and what is reachable


6. За рамками одного Cloud-проекта

Каждый источник опционален, доступен только для чтения и имеет свои учётные данные или сохранённый файл:

Источник Как Что проверяет
Terraform --terraform plan.json (terraform show -json, state или сохранённый план) Ресурсы вне Terraform, ресурсы, удалённые вне него, дрифт защиты/бэкапов/файрволов/меток, источники файрвола, отличающиеся от кода, безопасные изменения в плане
История изменений провайдера автоматически (последние 30 дней /actions) Режим восстановления, консольные сессии, сброс паролей, пересборки, удаление файрвола, отключение защиты
Несколько проектов snapshot --project prod --token-env HCLOUD_TOKEN_PROD, затем merge Один отчёт; файрвол в одном проекте доверяет публичному адресу другого проекта; продакшн смешан с другими окружениями
Hetzner Robot --robot (GET с пользователем веб-сервиса) или сохранённый файл Выделенные серверы без активного файрвола Robot, чувствительные порты, которые он пропускает (первое совпадение, только SYN), нефильтрованный IPv6, связь vSwitch с Cloud-сетями, слабые ключи
Object Storage --object-storage (S3 GET, SigV4) или сохранённый файл Публичные ACL, политики бакетов с масками (чтение или запись), отключённое версионирование; с --verify-public-buckets публичный доступ подтверждается одним анонимным листингом
Kubernetes --k8s cluster.json (kubectl get nodes,pods,services -A -o json) NodePorts, которые Cloud Firewall открывает в интернет на нодах, нагрузки с доступом на уровне ноды, обнаружение CCM/CSI
Телеметрия гостей hetzner-audit metrics --prometheus URL > metrics.json, затем --node-metrics RAM p95, пик RAM и пик корневой ФС; подбор размера предлагает только типы, им соответствующие
Чек-лист консоли hetzner-audit checklist, ответы через --attestations 2FA у каждого участника, роли участников, токены Read & Write, вход в Robot, ключи S3, под-аккаунты Storage Box, контакты для восстановления
Представление архитектуры добавляет всё это под сеткой серверов: балансировщики нагрузки, кластер Kubernetes, серверы Robot и vSwitch, а также бакеты.

7. Стоимость: сначала потери, потом оптимизация

hetzner-audit cost --metrics-days 30 --format markdown --output cost.md
hetzner-audit map --format svg --view cost --output cost.svg
  • Идентифицируемые потери: неприкреплённые тома, неназначенные IP, остановленные, но оплачиваемые серверы и устаревшие снимки. Им не нужна телеметрия.
  • Кандидаты на оптимизацию: изменение размера и переход x86 → ARM на основе CPU p95 за 30 дней. Только один кандидат на сервер учитывается в сумме, поэтому экономия никогда не считается дважды.
  • Трафик: исходящий трафик против включенной квоты каждого сервера, уже возникший перерасход за период и действие, когда сервер превышает 80%.
  • Структурные сигналы: концентрация затрат, серверы с высокой долей хранилища (томы выше половины стоимости вычислений) и устаревшие типы с заменой и дельтой стоимости.
  • Три цифры экономики, никогда не смешанные:
    • теоретическая: каждый кандидат, лучший на сервер;
    • ожидаемая: неиспользуемые ресурсы, плюс изменение размера, где телеметрия CPU, RAM и диска покрывает весь окно, а использование RAM не растёт;
    • измеренная: после изменения hetzner-audit diff before.json after.json оценивает оба снимка по более раннему каталогу, поэтому экономия от вашего изменения отделена от изменений цен провайдера. Это дельта каталога, а не сверка со счётом, и пробелы в сборе блокируют её.
  • RAM и диск определяют кандидата. С --node-metrics меньший тип предлагается только если RAM p95 остаётся ниже 70%, пик RAM ниже 90%, а использование диска ниже 80% от кандидата.

Per-VM cost view of an example project: status per VM, component bars, spend concentration, and cost actions

Аудит стоимости намеренно консервативен. Остановленный сервер всё ещё оплачивается. Экономия на ARM требует валидации образа, зависимостей и производительности. Инструмент не имеет действий по изменению размера, остановке, удалению, откреплению или покупке.

Cost recommendation with evidence and safeguards


8. Карты и представления архитектуры

hetzner-audit map --format svg --view architecture --output architecture.svg   # --theme dark available
hetzner-audit map --format svg --view connectivity --output connectivity.svg
hetzner-audit map --format svg --view cost --output cost.svg
hetzner-audit map --format svg --view host --output host.svg                   # needs --host-bundle
hetzner-audit map --format svg --view posture --output posture.svg
hetzner-audit map --format markdown --output network-map.md                    # Mermaid; renders on GitHub

Представление архитектуры расположено как диаграмма AWS или OCI:

  • сводные плитки по верхнему краю;
  • источники доверия слева (Интернет, пограничные прокси вроде Cloudflare или Fastly, mesh-VPN вроде Tailscale, списки разрешений);
  • сетевая зона и приватная сеть (аналог VPC у Hetzner);
  • один столбец на локацию, пересечённый уровнями ролей;
  • полоса для серверов вне приватной сети и для Storage Boxes;
  • при наличии: балансировщики нагрузки, Kubernetes, серверы Robot и vSwitch, бакеты, а также флаги хостов на серверах (обход Docker, отсутствие хостового фаервола, роль Kubernetes);
  • рекомендуемые действия и легенда вдоль нижнего края.

Галерея примеров: другие стеки, тот же аудит. Четыре синтетических проекта (каждое имя и адрес вымышлены), отрисованные через hetzner-audit map:

WireGuard admin, Fastly in front, one forgotten SSH/FTP server
WireGuard + Fastly. Веб-уровень принимает HTTP/HTTPS только от Fastly; UDP-порт WireGuard не считается раскрытием; легаси-хост с открытыми для всего мира SSH и FTP помечен.
Zero public ingress with Cloudflare Tunnel and Tailscale
Нулевой публичный вход. Приложения опубликованы через Cloudflare Tunnel (видно в хостовом бандле), админка работает через Tailscale, и ничего не принимает трафик из Интернета: целевой паттерн.
k3s on Cloud with a dedicated database via vSwitch, ZeroTier, Bunny CDN
Гибрид. k3s в Cloud за Bunny CDN, выделенные серверы Robot, объединённые vSwitch, админка через ZeroTier. NodePort, открытый в мир, привилегированная нагрузка и сервер Robot без фаервола помечены.
Load balancer behind CloudFront, NetBird, Object Storage
Балансировщик + CloudFront. Три веб-сервера за Hetzner LB и CloudFront, админка NetBird и Object Storage. Публичный бакет и порт Elasticsearch, открытый в мир, помечены.

Представление posture — это матрица доменов (сеть, хост, данные, идентичность, отказоустойчивость, управление) по серьёзности. Показывает подтверждённые находки рядом с теми, что ещё нужно валидировать, с полосами покрытия и источниками доказательств.

Security posture of an example project: domains by severity, confirmed vs to validate, coverage, and evidence sources

--max-actions управляет количеством отрисованных действий.

Раскрытие Значение
critical Чувствительный порт или все порты открыты для любого адреса, или у сервера нет облачного фаервола
public Другие порты открыты для любого адреса
proxied Доступен только из диапазонов пограничного прокси (таблетка называет его, например VIA CF или VIA FASTLY)
private Нет публичного входа, кроме UDP-порта mesh-VPN (Tailscale, WireGuard/NetBird, ZeroTier)
Карты показывают намерения файрволов, а не управление хостами или приложениями. Они никогда не печатают публичные IP-адреса, но раскрывают вашу топологию, поэтому храните их в приватности. См. пример карты.

9. Отслеживание изменений в CI

hetzner-audit snapshot --output before.json --read-only --no-ssh
# ... later ...
hetzner-audit snapshot --output after.json --read-only --no-ssh
hetzner-audit diff before.json after.json --fail-on-regression                       # broad: new world/wide exposure
hetzner-audit diff before.json after.json --fail-on-regression --regression-policy strict   # any growth

Diff сравнивает точные пространства разрешённых потоков, а не рёбра графа: для каждого сервера и балансировщика нагрузки, по семейству адресов и протоколу, множество пар (адрес источника, порт назначения), которые файрволы допускают на вход, и то же самое для выхода. after − before вычисляется точно и затем классифицируется (world, wide, edge provider, allow-list):

  • расширение 80-443 до 80-8443, или открытие порта только на IPv6 — это новый риск (broad и strict);
  • расширение 203.0.113.4/32 до 203.0.113.0/24, замена одного доверенного адреса на другой, или новый исходящий доступ в Интернет — изменение, на котором проваливается strict;
  • новый публичный IP за deny-all файрволом, или правило world-open на сервере без публичного интерфейса — вовсе не риск.

Закрытый риск также перечисляется. Также сообщается об изменениях активов и фактов, а также регрессиях покрытия коллектора. Ресурс, который не удалось собрать, не сообщается как удалённый. Каждый факт записывает свой источник, время наблюдения, версию коллектора и ID запуска.

- uses: jpolec/hetzner-cloud-audit-skills@v0.8.2
  env:
    HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }}
  with:
    mode: audit
    policy: policies/infrastructure.toml
    fail-on: confirmed-high   # hypotheses never fail the job
    format: sarif
    output: hetzner-audit.sarif

Установите fail-on: confirmed или confirmed-high, чтобы проваливать задачу только на подтверждённых выводах. Гипотезы needs_validation никогда не проваливают задачу, и они появляются в SARIF на уровне none. Зелёная задача означает, что на этом пороге ничего не было подтверждено; это не означает, что инфраструктура безопасна.

Запускайте живую сборку только из защищённых задач schedule или workflow_dispatch, и никогда не выставляйте токен в код форков. См. полное руководство по GitHub Action. SARIF работает лучше всего, когда вывод маппится на IaC. Выводы только о runtime-топологии остаются в Markdown и JSON.

Скажите ему, что такое «правильно». Общие лучшие практики слабее, чем ваш собственный архитектурный контракт:

[environments.production]
may_receive_from = ["production"]

[services.postgres]
public = false

[ssh]
public = false
hetzner-audit audit --policy policies/example-policy.toml --format markdown --output audit.md

Наблюдаемые факты, политика владельца, декларации IaC и выведенные гипотезы хранятся как отдельные записи.


10. Модель безопасности

  • Только чтение. Код не содержит вызовов Hetzner POST, PUT или DELETE. Используйте токен Read всё равно.
  • Нет SSH, нет сканирования портов. Инструмент никогда не подключается к вашим серверам. Доказательства хоста приходят из скрипта, который вы сами проверяете и запускаете. Единственный неаутентифицированный запрос, который он может сделать — это одно анонимное листинг вашего бакета, и только с --verify-public-buckets, чтобы подтвердить, что бакет, который уже выглядит публичным, действительно таковым является.
  • Отдельные, опциональные учётные данные. HROBOT_USER/HROBOT_PASSWORD (пользователь Robot webservice), HETZNER_S3_ACCESS_KEY/HETZNER_S3_SECRET_KEY, и PROMETHEUS_TOKEN читаются из окружения и никогда не печатаются. doctor предупредит, если любой из них лежит в .env файле.
  • Нет авто-ремедиации. Каждое действие — это план с шагами валидации и отката для ручной проверки.
  • Секреты и персональные данные замаскированы. В снапшотах удалены:
    • токены, пароли, приватные ключи и user_data;
    • email-адреса и reverse-DNS имена;
    • имена пользователей и хосты Storage Box;
    • материал SSH публичных ключей и комментарии;
    • загруженные PEM-сертификаты, списки пользователей sshd, пароли Redis, и переменные окружения контейнеров (никогда не собираются);
    • значения DNS-записей, кроме A, AAAA и CNAME (TXT часто содержит токены верификации), хранятся только как счётчик.
  • Нет проектного бэкенда, нет телеметрии. Аудит-данные никогда не отправляются ничему, чем управляет этот проект. Запросы идут только к провайдерам и эндпоинтам, которые вы настраиваете (Hetzner Cloud, Robot, Object Storage, ваш Prometheus).
  • Поддельные имена не могут захватить отчёты. Текст провайдера экранируется в Markdown и Mermaid, поэтому имя сервера не может внедрить ссылки, HTML или инструкции в отчёт, который читает агент.
  • Ограниченные и вежливые. API-вызовы ретраят 429 и 5xx ответы с бэкоффом и уважают Retry-After. Пагинация и поиск по пути ограничены.

См. модель угроз и разрешения.


11. Как это работает

flowchart LR
  H[Hetzner GET-only API] --> F[Temporal facts]
  I[IaC and owner policy] --> F
  R[Host bundles, Robot, S3, kubectl, telemetry] --> F
  F --> G[Typed evidence graph]
  G --> P[Attack paths]
  G --> D[Temporal diff]
  G --> S[Security findings]
  G --> C[Cost and architecture candidates]
  P --> V[Deterministic verification]
  D --> V
  S --> V
  C --> V
  V --> A[Ranked recommended actions]
  A --> O[Markdown / SVG / JSON / SARIF]

Конвейер: collect → reason → verify → recommend. Детерминированный верификатор — отдельный компонент, а не независимый человек или агент-ревьюер. Кандидаты, сгенерированные агентом, без независимого верификатора остаются в статусе needs_validation.

Подробнее: архитектура, архитектура FinOps, эталонный анализ Cloudflare, ландшафт.


12. Статус, лимиты и дорожная карта

Возможность Статус v0.8
Инвентаризация с покрытием по эндпойнтам, doctor префлайт, повторные попытки/бэкофф Бета, протестировано на живом проекте
Публичная экспозиция (~30 сервисов), качество фаервола, обход Cloudflare Бета, протестировано на живом проекте
Радиус поражения приватной сети Бета (хост/рантайм остаются needs_validation)
Экспозиция Storage Box и план снимков; управление лейблами Бета, протестировано на живом проекте
Балансировщики нагрузки (вкл. рёбра графов атак и обход), сертификаты, DNS, жизненный цикл ОС, размещение Бета, только фикстуры (позитивный кейс и чистый твин)
Сила и возраст SSH-ключей Бета: поля проверены на живом проекте (слабых ключей не было, поэтому позитивный кейс протестирован фикстурами и бенчмарками)
Квота трафика и перерасход Бета, протестировано на живом проекте
Семантический diff экспозиции (наборы потоков, не ID рёбер) Бета, property-тестирование против брутфорса
Рекомендуемые действия с уровнями доказательств; пять представлений (архитектура, связность, стоимость, хост, позиция) Бета
История изменений провайдера (/actions) Бета, протестировано на живом проекте
Пакет доказательств хоста и пересечение потоков Бета, только фикстуры (модель реального UFW + Docker хост, плюс adversarial-кейсы парсера); ещё не запускалось на живом
Дрифт Terraform, Robot, Object Storage, Kubernetes, чек-лист консоли Бета, только фикстуры. Подписание Object Storage верифицировано против тестовых векторов AWS SigV4
Слияние мульти-проектов Бета, слияние протестировано на одном живом проекте; кросс-проектные правила — только фикстуры
Телеметрия RAM/диска гостя и тиры экономии Экспериментально, только фикстуры
Точный diff пространства потоков (вход и выход), широкие/строгие политики Бета, property-тестирование против брутфорса
Модель исходящего трафика и политика egress по ролям Бета, протестировано на живом проекте
IP-таргеты балансировщиков (Cloud и Robot) Бета, только фикстуры
anonymize и скорер валидационного корпуса Бета; анонимизированный вывод тестировался на живом для получения идентичных находок; корпус пока пуст
Снимки и diff; GitHub Action с fail-on; SARIF Бета
Стоимость: отходы, концентрация, райзизинг и ARM-кандидаты Экспериментально

Чего это (пока) не является

  • Доказательства хоста настолько полны, насколько полон бандл. Фаерволы, построенные из цепочек, которые парсер не моделирует (зоны firewalld, CSF, кастомные цепочки iptables), остаются «unknown», поэтому связанные находки остаются needs_validation. Скрипт только читает; вы всё ещё решаете, где его запускать.
  • Robot, Object Storage, Kubernetes и Terraform не запускались мейнтейнером против живого аккаунта. Они тестируются на документированных форматах ответов. Пожалуйста, сообщайте о случаях, когда инструмент ошибается.
  • Не маппинг комплаенса. Нет матриц CIS, NIST или C5.
  • Не биллинг-инструмент. Стоимости используют нетто-цены каталога без НДС. Трафик покрывает только уже понесенный перерасход за этот период, и ничего не сверяется с инвойсами.

Используйте для топологии, публичной экспозиции, радиуса поражения приватной сети, дрифта фаервола и ранжированного списка фиксов. Не рассматривайте как единственный аудит безопасности или FinOps.

См. дорожную карту.

Помогите измерить реальную точность. hetzner-audit anonymize snapshot.json --output anon.json заменяет имена, значения лейблов, адреса, ID, нестандартные порты и свободный текст последовательно, так что находки остаются теми же. Разметьте находки анонимизированного проекта и scripts/corpus_eval.py покажет ложно-подтверждённый рейт — это то число, что важно для аудитора (руководство по корпусу).

Включено два бенчмарка:

  • Fixture benchmark: высаживает 33 проблемы безопасности. 23 соответствуют детерминированному контракту доказательств, а 10 намеренно остаются needs_validation.
  • Generated benchmark: 150 случайных проектов, каждый смешивает высаженные проблемы с чистыми двойниками. Он оценивает 18 правил (cloud, host, Robot, Object Storage, Kubernetes) по истинным срабатываниям, ложным срабатываниям и ложным пропускам. Все набирают 1.00 precision и recall; один сценарий обнаружил настоящий баг в правиле «no host firewall» до релиза.

Оба измеряют правила против их спецификации, а не точность обнаружения в реальном мире (методология).


13. Вклад

Приветствуются issues, идеи правил и pull requests, особенно реальные случаи, где инструмент ошибается. См. CONTRIBUTING.md и AGENTS.md.

uv sync --extra dev
uv run ruff check . && uv run mypy src && uv run pytest
./scripts/demo.sh                              # regenerate examples/reports
uv run python scripts/validate_artifacts.py

Код времени выполнения использует только стандартную библиотеку Python. Лицензирован под Apache-2.0 за его явное предоставление патента.

Сопровождающий

Создан и поддерживается Jakub Połeć.

Сообщайте о проблемах безопасности через GitHub private vulnerability reporting, а не через публичный issue.

Если hetzner-audit сэкономил вам деньги или поймал что-то страшное, ⭐ на GitHub поможет другим найти его.

Войдите, чтобы оставить комментарий