Как убрать секреты с сервера и не сломать существующие процессы


В предыдущей статье мы рассказывали, как пришли к идее Единого Хранилища Секретов — ЕХС. Задача на первый взгляд была понятной: перестать разбрасывать ключи, пароли и другие чувствительные данные по серверам и рабочим станциям, собрать их в одном месте и централизованно управлять доступом и жизненным циклом.
Но довольно быстро выяснилось, что безопасно хранить секрет — только половина задачи.
Администратору всё равно нужен SSH-ключ. Пользователю — закрытый ключ сертификата. Скрипту автоматизации — credentials для подключения к системе. А старому корпоративному приложению совершенно всё равно, насколько красивую архитектуру мы построили: оно по-прежнему ожидает пароль в конфигурационном файле.
Получается интересная ситуация: секрет мы с сервера убрали, но существующие процессы от этого никуда не исчезли.
Значит, следующий вопрос звучит уже не «где хранить секреты?», а «как пользоваться секретами из централизованного хранилища так, чтобы не вернуть их обратно в файлы, скрипты и переменные окружения?»
Именно здесь в архитектуре ЕХС появляется ещё один компонент — Wallet.
Но обо всём по порядку.
Где на самом деле лежит закрытый ключ
Возьмём обычный Linux-сервер, которому нужен закрытый ключ для подключения по SSH или выполнения другой криптографической операции.
Самый очевидный вариант — сохранить ключ в файле, ограничить права доступа и продолжить работу. Именно так устроено огромное количество существующих систем.
Пока всё работает штатно, проблем может быть не видно. Но если злоумышленник получает доступ к файловой системе, вместе с ней он потенциально получает и ключевой материал.
Можно зашифровать диск или отдельно защитить файл, но тогда появляются следующие задачи: где хранить данные для расшифрования и как встроить новый механизм в уже работающие процессы.
В Windows ситуация несколько отличается. Например, Data Protection API позволяет связать возможность локального хранения данных в зашифрованном виде с пользовательским или машинным контекстом. Поэтому просто скопировать защищённый файл на другой компьютер уже недостаточно.
Это заметно лучше хранения ключа в открытом виде, но фундаментальная проблема остаётся: секрет всё равно находится на конечном устройстве, а его безопасность зависит от безопасности этого устройства и учётной записи пользователя.
Есть и ещё один, менее очевидный риск — потеря самого устройства.

Если закрытый ключ существует в единственном экземпляре на рабочей станции, то вместе с вышедшим из строя диском можно потерять и возможность расшифровать данные. В отдельных PKI-сценариях здесь помогает Key Recovery Agent, но только если механизм восстановления был предусмотрен заранее.
Поэтому идея, к которой мы пришли в предыдущей статье, выглядит вполне естественно: убрать секреты из множества локальных хранилищ и перенести их в ЕХС, где можно централизованно управлять доступом, аудитом и жизненным циклом.
Казалось бы, вопрос закрыт, но на практике всё только начинается.
Секреты – хранить нельзя использовать
Допустим, ключи, пароли и другие чувствительные данные уже находятся в ЕХС.
С точки зрения управления стало гораздо лучше. Мы знаем, где находится секрет, можем контролировать доступ к нему, менять политики, вести аудит и избавляться от множества неизвестных копий.
А теперь администратору нужно подключиться к серверу по SSH. Что делать?
Самый простой вариант — открыть веб-интерфейс ЕХС, найти нужный секрет, получить его значение, скопировать и вставить в нужную команду.
Формально задача решена, но довольно быстро секрет начинает жить собственной жизнью.
Сегодня пользователь скопировал его в буфер обмена. Завтра положил во временный файл, потому что так удобнее. Через неделю кто-то вставил его в конфигурацию. Ещё позже этот же ключ оказался в скрипте или CI/CD.
В результате мы потратили усилия на централизацию, а секрет постепенно снова расползся по инфраструктуре.
Стало понятно, что одного ЕХС недостаточно. Нужен клиентский компонент, который позволит работать с секретами непосредственно на конечном устройстве, но при этом сохранит их связь с централизованными политиками.
Так появился локальный кошелек секретов, наш Wallet.
Wallet — локальный кошелёк секретов
Wallet — это полноценное кроссплатформенное приложение для Windows, Linux и macOS, которое работает совместно с ЕХС и предоставляет пользователю локальный доступ к разрешённым ему секретам на конечном устройстве.
Если ЕХС отвечает за централизованное хранение, политики, права доступа и жизненный цикл, то задача Wallet другая — сделать эти секреты доступными там, где они действительно нужны пользователю или локальному процессу.
При этом Wallet — не отдельное хранилище со своей независимой базой секретов.
Пользователь аутентифицируется в Wallet, а он обращается к ЕХС, получает информацию о доступных ему секретах и предоставляет возможность работать с ними через графический интерфейс или CLI.
Таким образом получается разделение ролей:
ЕХС — место постоянного хранения секретов и управления ими.
Wallet — приложение для контролируемой работы с секретами на конечном устройстве.

На бумаге модель выглядит довольно просто, но как только мы начали применять её к реальным сценариям, почти сразу возник вопрос: а что произойдёт, если ЕХС окажется недоступен?
А если сам ЕХС недоступен?
Представим администратора, который ежедневно использует сертификат или закрытый ключ.
Пока есть соединение с ЕХС, всё хорошо: Wallet обращается к серверу и получает необходимые данные. Но сеть может пропасть. Пользователь может оказаться в изолированном сегменте. Сам ЕХС может стать временно недоступен.
Если Wallet при каждой операции обязан связываться с сервером, то вместе с ЕХС остановятся и зависящие от него процессы.
Это уже довольно неприятный компромисс: мы повысили безопасность хранения, но одновременно сделали работающие процессы зависимыми от доступности ещё одной системы.
Поэтому в Wallet появился offline-режим. Он позволяет заранее получить разрешённые секреты из ЕХС и сохранить их локально на ограниченный срок.
И здесь мы приходим к небольшому парадоксу. Мы только что несколько абзацев убеждали себя в том, что хранить секреты локально плохо. А теперь сами возвращаем их на устройство.
Разница — в контроле.
Локально кэшированные секреты хранятся в зашифрованном виде, а сам пользователь не решает произвольно, что и как долго можно сохранить. Эти правила задаются централизованно в ЕХС. Администратор может определить, разрешён ли конкретному Wallet offline-режим, какие секреты можно кэшировать и на какой срок.
Например, инженеру можно разрешить заранее получить ключевые пары на 12 часов перед работами в изолированном сегменте. Для другой группы устройств кэширование можно полностью запретить. А для третьей разрешить offline-доступ только к определённым секретам.
В итоге offline-режим становится не просто функцией удобства, а частью политики безопасности.
И это хороший пример того, что в реальной инфраструктуре безопасность и доступность приходится балансировать, а не максимизировать независимо друг от друга.
Кто запрашивает секрет — и откуда
Следующий вопрос возник уже вокруг самого доступа.
Допустим, злоумышленник каким-то образом получил логин и пароль пользователя.
Достаточно ли этого, чтобы открыть Wallet и получить закрытый ключ? Хотелось бы, чтобы нет.
Поэтому Wallet поддерживает двухфакторную аутентификацию, где в качестве второго фактора используется TOTP. Причем второй фактор администратор ЕХС может назначить как на аутентификацию в Wallet, так и на прочтение значения отдельных критичных секретов. Таким образом, украсть учетную запись недостаточно. Нужен второй фактор, который генерируется на мобильном устройстве пользователя.
Но два фактора всё ещё отвечают в основном на вопрос: кто перед нами?
Они ничего не говорят о том, с какого устройства выполняется запрос.
Представим, что пользователь настоящий, пароль корректный, второй фактор тоже. Но Wallet запущен на неизвестной машине или устройстве, которое не соответствует корпоративным требованиям. Стоит ли в таком случае отдавать ему закрытый ключ?
Для этого в Wallet появился ещё один механизм — проверка окружения.
Перед доступом к секрету приложение может проверить характеристики устройства: например, состоит ли оно в нужном домене, соответствует ли hostname заданному значению, установлен ли требуемый антивирус и выполняются ли другие условия. Причем правила можно комбинировать и выстраивать уникальные наборы проверок.
В результате решение о доступе начинает выглядеть уже не как обычная проверка логина и пароля:

Для чувствительных данных такая модель гораздо ближе к тому, что нам было нужно изначально.
Секрет в истории bash — это уже инцидент
Представим, что есть в компании DevOps-инженер, который устал делать одну и ту же рутину на каждом сервере и в итоге написал скрипты для автоматизации. Это может быть простой bash-скрипт или ansible playbook, который по очереди подключается к 100 серверам по SSH и выполняет однотипные операции.
Для подключения по SSH инженеру нужен закрытый ключ, который он захардкодит в скрипты или передаст в качестве переменной окружения, которая останется в истории. Оба варианта ведут к легкой компрометации закрытого ключа и ещё 100 серверов.
Но предложение «теперь перепишите всю автоматизацию под новую систему хранения» тоже вряд ли обрадует инженера.
Поэтому Wallet изначально задумывался не только как графическое приложение для пользователя. У него есть CLI, через который локальные процессы могут получать доступ к разрешённым секретам.

Если инженер уже работает через bash, PowerShell или Ansible, он может продолжать использовать знакомые инструменты.
Был скрипт — остаётся скрипт.
Был Ansible — остаётся Ansible.
Меняется только способ, которым процесс получает чувствительные данные: вместо ключа, который годами лежит рядом со скриптом, секрет запрашивается через Wallet только тогда, когда он действительно нужен.
В итоге ЕХС продолжает оставаться централизованным источником секретов, а Wallet становится локальной точкой взаимодействия между ним и существующей автоматизацией.
А что делать с браузером?
Похожая проблема возникает с веб-приложениями.
Представим старую систему, которая не знает ничего ни про ЕХС, ни про внешние хранилища секретов и ожидает обычный пароль в HTML-форме. Интегрировать её напрямую с ЕХС долго или вообще невозможно.
Можно заставить пользователя каждый раз открывать Wallet, копировать его и вставлять в браузер. Но тогда в нашу цепочку действий снова возвращается буфер обмена, а вместе с ним — возможность случайно вставить значение не туда, сохранить его или просто оставить в истории работы.
Поэтому следующий логичный шаг для Wallet — браузерное расширение, которое сможет получать разрешённый секрет через локальное приложение и подставлять его непосредственно в нужную форму.
Пользователь продолжает работать с привычным веб-приложением, а сам секрет не приходится вручную переносить между окнами.
Конечно, такой сценарий создаёт уже свои требования: необходимо контролировать, для каких ресурсов разрешена подстановка, кто инициировал операцию и соответствует ли устройство установленной политике.
Но общий принцип остаётся прежним: существующее приложение не обязательно должно знать о ЕХС, чтобы секрет из ЕХС использовался в нём контролируемо.
Где хранится ≠ где используется
В итоге архитектура, к которой мы пришли, состоит уже не из одного хранилища.
ЕХС отвечает за постоянное хранение секретов, политики, доступ и жизненный цикл.
Wallet работает непосредственно на пользовательском устройстве или сервере и становится клиентским приложением ЕХС: через него пользователь и локальные процессы могут безопасно работать с разрешёнными секретами.
А между ними находится набор правил, который определяет: кто запрашивает секрет, с какого устройства, разрешён ли offline-доступ, как долго может существовать локальная копия.
Именно поэтому после внедрения централизованного хранилища работа с секретами не заканчивается.
Скорее наоборот — появляется следующий уровень задачи.
Можно построить хорошо защищённый ЕХС, но, если пользователи после этого продолжают копировать пароли через буфер обмена в bash, а инженеры один раз выгружают закрытые ключи и складывают их рядом со скриптами, часть эффекта от централизации довольно быстро исчезнет.
Поэтому мы постепенно пришли к другому вопросу.
Не: «как сделать так, чтобы секрет никогда не появлялся на конечном устройстве?»,
а: «как сделать так, чтобы секрет появлялся там только тогда, когда действительно нужен, на контролируемых условиях и без необходимости человеку работать с его значением напрямую?»
На этом не заканчиваем
В этих двух статьях мы показали путь от зарождения централизованного хранения секретов в ЕХС до их контролируемого использования через Wallet.
Но на практике этим всё не заканчивается. Каждое внедрение приносит новые ограничения и нестандартные сценарии: особенности существующей инфраструктуры, требования к отказоустойчивости, автоматизации, локальной работе и интеграции с системами, которые изначально не рассчитывали на централизованное управление секретами.
Именно такими кейсами мы и хотим делиться дальше — не просто рассказывать о новых функциях, а показывать, какие задачи за ними стояли, с какими ограничениями мы столкнулись и к каким решениям пришли.

Спасибо всем, кто прочитал обе статьи и проявил интерес к теме. Будем держать вас в курсе развития ЕХС и Wallet и продолжать делиться практическим опытом внедрения.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.