Перейти к содержимому

Журнал аудита

NORA записывает операции реестра в структурированный журнал аудита. Каждая запись представляет собой JSON-объект, записанный в одну строку (формат JSONL).

ПеременнаяПо умолчаниюОписание
NORA_AUDIT_LOGfileРежим вывода: file, stdout, both или off
config.toml
[audit]
mode = "file" # "file", "stdout", "both", "off"

Режимы:

РежимПоведение
fileЗапись в {storage_path}/audit.jsonl
stdoutЗапись в stderr (совместимо с 12-factor, работает с агрегаторами логов)
bothЗапись и в файл, и в stderr
offОтключить журналирование аудита

Каждая строка представляет собой JSON-объект со следующими полями:

ПолеТипОписание
tsstringВременная метка в формате ISO 8601 (UTC)
actionstringЧто произошло — см. Типы действий
actorstringКто вызвал операцию — см. Значения actor
artifactstringПакет, путь или ссылка на образ; пусто для pull, cache_hit и proxy_fetch
registrystringТип реестра: docker, npm, pypi, maven, raw и т. д.; admin для выпуска токенов, область переиндексации для reindex, * для политик хранения
detailstringДополнительный контекст: blob/manifest для Docker, правило и причина для curation_block, роль и срок для admin_token_mint, счётчики для retention-apply
{"ts":"2026-10-13T07:46:45.283Z","action":"push","actor":"ci","artifact":"team/a.txt","registry":"raw","detail":""}
{"ts":"2026-10-13T07:46:47.990Z","action":"pull","actor":"proxy","artifact":"","registry":"raw","detail":""}
{"ts":"2026-10-13T07:46:52.149Z","action":"push","actor":"api","artifact":"team/tiny:1.0","registry":"docker","detail":"manifest"}
{"ts":"2026-10-13T07:46:53.645Z","action":"delete","actor":"ci","artifact":"team/b.txt","registry":"raw","detail":""}
{"ts":"2026-10-13T07:47:03.543Z","action":"push","actor":"anonymous","artifact":"team/c.txt","registry":"raw","detail":""}
{"ts":"2026-10-13T08:00:00.000Z","action":"retention-apply","actor":"scheduler","artifact":"12 versions","registry":"*","detail":"keys=36 bytes_freed=104857600 duration=1.2s"}
ДействиеОписание
pushКлиент загрузил артефакт
pullСкачивание Cargo, pub или Raw из локального хранилища
deleteКлиент удалил артефакт
overwriteСуществующий артефакт Raw заменён
mountМонтирование блоба Docker из другого репозитория
cache_hitЗапрос обслужен из кэша прокси без обращения к вышестоящему реестру
proxy_fetchАртефакт получен из вышестоящего реестра
curation_blockСкачивание отклонено курацией
reindexПерестроение индекса через POST /api/v1/admin/reindex или переиндексация репозитория RPM/Debian
admin_token_mintАдминистратор выпустил API-токен для пользователя через POST /api/v1/admin/tokens (artifact — пользователь; сам токен не пишется)
retention-applyПрогон политик хранения удалил версии (одна сводная запись на прогон)
ActorКогда
имя пользователяАутентифицированный пользователь для push, delete, overwrite и reindex RPM/Debian в Cargo, Maven, npm, PyPI, Raw, RPM и Debian; также для curation_block, административного reindex и admin_token_mint. API-токен записывается именем его владельца
anonymousТе же операции, когда у запроса нет идентичности (аутентификация выключена или анонимный доступ)
apipush, delete и mount в Docker — записи Docker не содержат имени пользователя
proxypull, cache_hit и proxy_fetch
schedulerretention-apply от встроенного планировщика политик хранения
cliretention-apply из nora retention-apply

При использовании режима file или both журнал аудита записывается в:

{NORA_STORAGE_PATH}/audit.jsonl

По умолчанию: data/audit.jsonl (относительно рабочей директории).

Файл создаётся автоматически. Родительские директории создаются, если они не существуют.

services:
nora:
image: ghcr.io/getnora-io/nora:latest
environment:
NORA_AUDIT_LOG: both
NORA_STORAGE_PATH: /data
volumes:
- nora-data:/data

Затем следите за журналом:

Окно терминала
docker exec nora tail -f /data/audit.jsonl | jq .

В режиме stdout записи аудита отправляются в stderr вместе с обычными логами. Используйте драйвер логов вашего оркестратора контейнеров для их пересылки:

Окно терминала
# Filter audit entries from container logs
docker logs nora 2>&1 | grep '"action":' | jq .

Для выделенной пересылки на основе файлов (Filebeat, Promtail, Vector):

filebeat.yml
filebeat.inputs:
- type: log
paths:
- /data/audit.jsonl
json.keys_under_root: true
json.add_error_key: true
Окно терминала
# All pushes today
grep '"action":"push"' /data/audit.jsonl | jq .
# Everything user "ci" pushed, overwrote or deleted
# (Docker writes are recorded with actor "api", not the username)
jq -c 'select(.actor == "ci")' /data/audit.jsonl
# Downloads refused by curation
jq -c 'select(.action == "curation_block")' /data/audit.jsonl
# Count operations per registry
jq -r '.registry' /data/audit.jsonl | sort | uniq -c | sort -rn