Машинная identity: как сервис доказывает, что он — это он
Короткий ответ: токен в переменной окружения — это не identity, а пароль без владельца: его нельзя отозвать у одного сервиса, не узнаешь, кто им воспользовался, и скопировать его может любой, кто видит конфигурацию. Машинная identity — это отдельная сущность со своим способом входа, своим временем жизни токена и своим скоупом: проект, окружение и, если нужно, список ключей. В env-master у client secret есть отзыв, у access-токена — TTL в минуты, у enrollment-токена — минуты и ровно одно использование, а повторный обмен одноразового токена трактуется как утечка и поднимает тревогу.
Почему «токен в env» — это не identity
Общий токен на все сервисы (или на все окружения) решает задачу доступа ценой трёх потерь. Во-первых, отозвать его у одного потребителя нельзя — придётся менять у всех. Во-вторых, по журналу невозможно отличить, кто предъявил токен: биллинговый воркер или тот, кто снял его с скомпрометированного хоста. В-третьих, токен без срока жизни, найденный в годовалом бэкапе, работает. Identity вместо токена означает, что у каждого потребителя свои креденшелы, свой срок жизни и своя зона доступа — и всё это видно в аудите раздельно.
Из чего состоит identity в env-master
Сервис — сущность первого класса, а не побочный продукт токена. К нему привязываются identity, и у каждой свой контракт:
- способ входа — Universal Auth обменивает client id и secret на короткоживущий токен; enrollment-токен выдаётся для первичной регистрации и живёт минуты;
- время жизни — access-токен измеряется минутами и обновляется SDK сам; украденный access устаревает быстрее, чем его успевают применить;
- скоуп — проект, окружение и при необходимости список ключей: сервису
биллинга выдают
DB_*, а не весь прод; дополнительно — список разрешённых адресов.
Client secret показывается ровно один раз: в базе остаётся только его хэш, поэтому потерянный секрет не восстанавливают, а выпускают заново — восстановление было бы признаком того, что секрет где-то лежит открытым.
Повтор — это сигнал, а не ошибка
Enrollment-токен одноразовый по построению: захват атомарный (compare-and-set),
и вторая попытка обмена означает, что токен держат двое. Система не просто
отказывает: проигравшая попытка поднимает событие enrollment.reuse-detected
и вебхук администраторам. Тот же принцип у refresh-токенов: предъявление уже
ротированного токена гасит сессии, потому что единственное легитимное
объяснение — гонка, а все остальные — кража. Подробности — в
модели угроз.
Скоуп до набора ключей — главное отличие зрелой модели
Гранулярность доступа обычно заканчивается на окружении: токен от прода видит
весь прод. Это превращает каждый сервис в потенциальный источник полной утечки
окружения. Скоуп до списка ключей меняет арифметику риска: компрометация
воркера отчётов отдаёт атакующему ключи отчётов, а не пароль от основной базы
и токены платёжного провайдера. В сочетании с видимостью
restricted — значением, которое не показывается человеку
вообще, — получается секрет, которого нет ни у людей, ни у лишних машин.
Где проходит граница доверия
Машинный путь в env-master честно клиентский: SDK получает шифртекст и ключ окружения, обёрнутый x25519 под публичный ключ конкретной identity, и расшифровывает у себя — открытое значение сервер в этом сценарии не производит. При этом система не является zero-knowledge и не претендует: значения, показываемые человеку в дашборде, расшифровываются на сервере. Мы считаем, что точная формулировка границы полезнее красивого термина — поэтому она написана на странице безопасности прямым текстом.
Выдать первую identity — работа на минуты: проект, окружение, сервис, скоуп. Дальше сервис забирает свои секреты сам, без файлов и без людей в цепочке доставки — см. быстрый старт.