Синхронизация CMS и эксплуатация сертификатов
1. Обзор
DAT CMS (Certificate Management Service) — это сервер, который создаёт и распространяет сертификаты, общие для всего кластера.
Каждое приложение периодически получает список сертификатов через клиент CMS (DatCmsManager), и именно эта синхронизация автоматизирует ротацию ключей. Даже если оператор не меняет ключи вручную, сертификаты создаются заново по заданному циклу, а устаревшие истекают сами.
Сертификаты, которыми можно выдавать, получает только сервер входа; серверы контента получают сертификаты лишь для проверки. Серверу контента достаточно знать только CMS, знать сервер входа ему не нужно.
2. Протокол синхронизации
2.1. Запрос и ответ
| Эндпоинт | Назначение |
|---|---|
GET /v1/certs?version=N | полные сертификаты (с закрытым ключом подписи) |
GET /v1/certs/verify-only?version=N | сертификаты только для проверки |
GET /v1/certs.json, /v1/certs/verify-only.json | то же содержимое в формате JSON |
POST /v1/cert/{sig-alg}/{crypto-alg}/{delay}/{duration}/{ttl} | ручное создание сертификата (нужен токен Master) |
GET /health | проверка состояния |
Тело ответа — обычный текст, первая строка которого содержит текущую version сервера, а начиная со следующей строки идут сертификаты, по одному в строке.
1712345678
1a.1712345000.3600.1800.ECDSA-P256.IV-AES256-GCM.<sig-key>.<crypto-key>
2b.1712348600.3600.1800.ECDSA-P256.IV-AES256-GCM.<sig-key>.<crypto-key>2.2. Курсор версии
Клиент запоминает последнюю успешную version и отправляет её в следующем запросе. Сервер отбирает и возвращает только сертификаты новее этого значения.
- Если version клиента старее серверной → возвращаются только сертификаты, появившиеся после неё.
- Если version клиента новее серверной (замена сервера, сброс БД и т. п.) → курсор откатывается к
0и возвращается полный набор. - Клиент продвигает version только при успешном импорте. Это защищает от ситуации, когда курсор сдвигается по неудачному ответу и сертификаты теряются навсегда.
Запрос инкрементальный, но ответ заменяет список целиком
?version=N — это запрос «дай изменения после N», однако клиент не объединяет полученный список с прежним, а заменяет его (clear = true). Так сделано потому, что сервер всегда сам определяет и отдаёт полный набор действительных сертификатов; благодаря этому отозванные (revoke) в CMS сертификаты не остаются у клиента.
2.3. Токены доступа
CMS разграничивает доступ тремя видами токенов.
| Токен | Права |
|---|---|
Токен Master | Генерация сертификата DAT, просмотр версии сервера |
Токен Full Cert | GET сертификата Full (Pair Key, Hash Key) |
Токен Verify Cert | GET сертификата Verify (Verify Key Only) |
Серверам, которые только проверяют токены, по правилу следует выдавать лишь токен Verify Cert. Однако ключ шифрования включается и в ответ verify-only, поэтому обязательно ознакомьтесь с предупреждениями в документе Сертификат.
3. Задержка выдачи сертификата (delay)
Если использовать для выдачи только что созданный сертификат, другие узлы, ещё не выполнившие синхронизацию, не смогут проверить подписанные им токены. Задержка выдачи — это значение, устраняющее такой интервал.
Например, предположим, что CMS создаёт сертификат A, а серверы 1 и 2 синхронизируются с периодом 60 секунд. Если сервер 1 получил его первым и выдал DAT по сертификату A, а сервер 2 ещё не получил сертификат, то сервер 2 не сможет проверить этот DAT.
Если задать задержку в 180 секунд, то в течение 180 секунд после создания сертификат останется недоступным для выдачи, и за это время все серверы безопасно завершат синхронизацию. С учётом возможных временных сетевых сбоев рекомендуется задавать значение как минимум в 3–4 раза больше периода синхронизации каждого сервера.
4. Намеренное поведение
Всё перечисленное ниже предусмотрено проектом и не является дефектом. Указываем это явно, поскольку при эксплуатации такое поведение может показаться неожиданным.
4.1. Подпись продолжается кэшированным сертификатом даже после закрытия окна выдачи
Приложение продолжает использовать сертификат для выдачи, выбранный в момент синхронизации, и не проверяет issuable() заново при каждой выдаче.
Причина: если окно выдачи закроется при разорванной связи с CMS, то при подходе с повторной проверкой в этот момент вход в систему остановится по всему сервису. В DAT выбран вариант «даже если новый сертификат не получен, выдачу пока продолжаем».
Цена: при затяжном сетевом сбое токены могут продолжать выдаваться сертификатом, окно выдачи которого уже прошло. Однако такие токены до окончательного истечения сертификата нормально проверяются на других узлах, поэтому это сочтено компромиссом, лучшим, чем падение сервиса во время аварии.
4.2. Сертификат, обновлённый с тем же CID, отбрасывается
Если приходит сертификат с тем же CID, что уже имеется, новый поступивший игнорируется.
Причина: CID — неизменяемый идентификатор сертификата. Если один и тот же CID начнёт указывать на разные ключи, станет непонятно, каким ключом проверять уже выданные и находящиеся в обращении токены.
Замена ключа — обязательно с новым CID
Если распространить сертификат, сохранив тот же CID и заменив только ключ, изменения никогда не попадут к клиентам, и при этом не возникнет никакой ошибки. При замене ключа выпускайте сертификат с новым CID.
4.3. Если новых сертификатов нет, прежний список сохраняется
Если в ответе нет ни одного сертификата, клиент оставляет имеющийся список без изменений. Список не очищается.
Причина: если очистить имеющиеся сертификаты в самый неудачный момент — когда сервер сертификатов упал или ответ некорректен, — то немедленно начнут проваливаться все проверки токенов. Если ничего нового не получено, безопаснее продержаться на том, что уже есть.
4.4. Режим SINGLE_NODE создаёт сертификат при каждом запуске
Если запустить CMS в режиме одного узла, он создаёт один сертификат при каждом старте, независимо от наличия сертификатов, доступных для выдачи.
Причина: режим одного узла предназначен для автономного запуска CMS без отдельной инфраструктуры. Сразу после старта должен существовать сертификат, доступный для выдачи.
Внимание: при частых перезапусках сертификаты будут накапливаться. Впрочем, каждый сертификат исключается из списка по прошествии собственного времени истечения, поэтому бесконечно их число не растёт.
4.5. Если нет сертификатов, доступных для выдачи, выдача начинается сразу, без задержки
Если на момент создания сертификата нет ни одного, доступного для выдачи, CMS пропускает фазу задержки и прибавляет время задержки к периоду выдачи.
Причина: соблюдение задержки означало бы, что всё это время кластер не сможет выдать ни одного токена. При первом запуске или восстановлении после полной аварии выдача должна быть возможна немедленно. В этом случае в журнале сервера остаётся предупреждение.
5. Отзыв и истечение сертификатов
- Сертификат остаётся в списке распространения до момента окончательного истечения (
start + duration + ttl). Он не исчезает сразу после закрытия окна выдачи. - DAT, выданный незадолго до окончания окна выдачи, живёт ещё столько, сколько составляет его TTL, поэтому сервер проверки, впервые запущенный уже после этого момента, тоже получит сертификат и сможет проверить такой токен.
- Сертификат, у которого прошло окончательное истечение, исключается из списка, а при последующей очистке удаляется и из хранилища.
6. Развёртывание
Параметры запуска сервера CMS, способы развёртывания через Docker · Kubernetes · бинарный файл и переменные окружения рассматриваются в отдельном документе.