env-master
ENСоздать аккаунт

Аудит доступа к секретам: что должно попадать в журнал

Короткий ответ: журнал доступа к секретам — это не строка в общей ленте активности, а отдельный поток событий, где каждое чтение значения — человеком или машиной — записано с указанием ключа, субъекта и момента, но без самого значения. Чтобы журналу можно было верить, записи связываются цепочкой под ключом, который живёт вне базы, — переписать историю задним числом без этого ключа нельзя. В env-master журнал состоит из двух потоков (изменения и доступы), проверяется командой audit:verify, а раз в час сервер пишет подписанный якорь головы цепочки в лог, который уезжает с хоста.

Лента активности — не аудит

«Пользователь X изменил настройку» и «сервис Y прочитал DB_PASSWORD» — события разной природы. Первое интересно менеджеру, второе — следователю. Когда они смешаны в одной ленте, чтения тонут в конфигурационном шуме, а выгрузить «кто обращался к секретам за квартал» превращается в ручную фильтрацию. Поэтому в env-master потока два: изменения и доступы, связанные одной цепочкой на уровне организации. Каждое чтение секрета — человеком в дашборде или сервисом при старте — это событие, а не побочный эффект.

В журнале нет значений — и это требование, а не ограничение

В записи попадают имя ключа и HMAC значения. Этого достаточно, чтобы увидеть «значение изменилось» и «это чтение отдало то же значение, что и вчера», и недостаточно, чтобы узнать само значение. Журнал аудита по определению читают многие и хранят долго — если бы в нём лежали значения, он сам стал бы хранилищем секретов с худшими свойствами, чем основное.

Почему цепочка под ключом, а не из обычных хешей

Цепочка из простых хешей проверяется кем угодно — значит, кем угодно и пересчитывается. Тот, кто получил доступ на запись в базу, удалил бы события, пересобрал цепочку от разрыва и переписал голову, лежащую там же. Поэтому звено считается под ключом, выведенным из ключа аудита, а тот живёт в окружении сервиса, а не в базе: пересчитать цепочку, не имея ключа, нельзя. Голова цепочки тоже подписана — усечь журнал, удалив последние события, без ключа не получится.

Якоря против отката из резервной копии

Остаётся один случай, который изнутри базы не отличить: откат к состоянию, которое когда-то было подлинным, из старой копии. Против него сервер раз в час пишет якорь — подписанный снимок головы — в свой лог, а он уезжает с хоста. Передайте накопленные якоря проверке (audit:verify --anchors <файл>), и она убедится, что каждое зафиксированное звено осталось на месте — и что журнал не стёрт целиком. Границы названы честно: откат к состоянию новее последнего якоря не виден по построению (окно — час), а якоря, накопленные до появления у них собственной подписи, помечаются как неподписанные — принимать старую форму значило бы оставить открытой ровно ту дверь, ради которой подпись вводилась.

Свойство, которое нельзя проверить, свойством не является

Всё вышесказанное — не обещание, а проверяемая процедура: audit:verify идёт от первого события по звеньям и сверяет каждое, попутно замечая то, чего сверка хешей по отдельности не увидит, — развилку, обрыв хвоста и события, до которых от начала цепочки не добраться. Полное описание конструкции — в модели угроз, сжатая версия — на странице безопасности.

Хранение журнала ограничено тарифом только по глубине (от 7 дней на Free до года на Business — см. тарифы); сам факт записи каждого чтения и проверяемость цепочки одинаковы во всех планах. Аудит, который включается за деньги, — это аудит, который выключается, когда он больше всего нужен.

← Все статьи