server-monitor-manager/agents/hermes/notes/salvage-2026-08-18/hermes-desktop-attachments/desktop-attachments/smm-hermes-task-cert-lifecycle-2026-08-06.md
Ochenstarik 23eb3f5233 chore(agents): разбор рабочих папок с диска на 2026-08-18
Задания, отчёты и патчи, лежавшие в C:\Users\Ochenstarik\projects и в
домашней папке, перенесены в agents/. Разложено по агентам там, где имя
файла позволяло определить автора; остальное — в _salvage-2026-08-18/
и разбирается вручную.

Патчи в notes/salvage-2026-08-18/ — незакоммиченная работа из брошенных
рабочих копий: она существовала только на диске.

Тяжёлое (релизные архивы, инсталляторы, наборы данных) в репозиторий не
попало: оно лежит рядом, в Agent_projects/_archive и Agent_projects/_data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 14:19:54 +07:00

7.4 KiB
Raw Blame History

Жизненный цикл клиентских сертификатов

Репозиторий и ветка

Задание не пересекается по файлам с b3r-fact-reconciliation и выполняется параллельно в отдельном worktree. Затрагиваемые файлы (CertificateAuthority.cs, CertificateLifecycleService.cs, AgentClient.cs) веткой B-3R не изменяются.

Зачем

CertificateAuthority.cs, выдача клиентского сертификата:

var requestedNotAfter = DateTimeOffset.UtcNow.AddYears(1);

Срок — один год, автопродления нет ни у Agent, ни у Operator. Через год после развёртывания весь парк перестаёт проходить mTLS одновременно, и восстановление требует ручной перерегистрации каждого Node через одноразовый enrollment token. Процедуры ротации Control CA в проекте нет вообще.

Отзыв работает через таблицу identity в Control (ResolveIdentityAsync), CRL не используется — это осознанное решение и менять его не нужно.

Работы

1. Срок жизни

  • сократить срок клиентского сертификата до 3090 дней;
  • вынести значение в ControlOptions с валидацией в общей цепочке .Validate(...) в Program.cs, по образцу LinkReconciliationSeconds;
  • значение по умолчанию в appsettings.json и в control.env, который пишет bootstrap;
  • срок сертификата не может превышать остаточный срок Control CA — существующая логика ограничения сохраняется.

2. Автопродление Agent

  • Agent проверяет остаточный срок собственного сертификата при старте и далее периодически;
  • при остатке меньше трети срока формирует новый CSR и запрашивает выдачу по действующему mTLS-каналу, без enrollment token;
  • новый эндпоинт выдачи требует действующий сертификат того же node_id, idempotency key и запись в audit;
  • замена agent.pfx атомарная: запись во временный файл с правами 0600, затем rename; при любой ошибке остаётся действующий сертификат;
  • отозванный сертификат продлению не подлежит — запрос отклоняется, Node требует повторной регистрации.

3. Продление Operator-сертификата Desktop

  • Desktop проверяет остаточный срок при подключении к Control;
  • продление по тому же принципу, с явным уведомлением пользователя в интерфейсе;
  • защищённое хранение DPAPI сохраняется, приватный ключ не покидает устройство.

4. Уведомление об истечении

  • событие certificate.expiring в поток событий Control при остатке меньше трети срока;
  • поле остаточного срока в ответе /api/v1/control/agents;
  • отображение в Desktop на странице Servers.

5. Ротация Control CA

Документ docs/certificate-rotation.md:

  • когда ротация требуется: компрометация, истечение, смена алгоритма;
  • порядок: выпуск нового CA, период двойного доверия, перевыпуск клиентских сертификатов, вывод старого CA;
  • что делает оператор руками и что делает bootstrap;
  • как проверить, что ни один Node не остался на старом CA;
  • почему ротация CA требует режима подтверждения two_person — см. docs/approval-policies.md.

Реализация автоматической ротации в эту задачу не входит — только процедура и то, что нужно для её ручного выполнения.

Тесты

  1. Сертификат с остатком меньше трети срока продлевается; agent.pfx заменён, старый сертификат больше не используется.
  2. Сертификат с достаточным остатком не продлевается — лишних запросов нет.
  3. Hub недоступен в момент продления: Agent продолжает работать на действующем сертификате, повторяет попытку позже, метрики не теряются.
  4. Отозванный сертификат продлить нельзя — запрос отклонён.
  5. Запрос продления сертификатом другого node_id отклонён.
  6. Замена agent.pfx прервана на середине: остаётся действующий сертификат, Agent поднимается.
  7. Срок вне диапазона в конфигурации: Control не стартует, ошибка валидации внятная.

Критерий приёмки

  • Node, проработавший дольше срока сертификата, продолжает работать без вмешательства оператора;
  • отзыв по-прежнему немедленно закрывает доступ;
  • существующие тесты CertificateAuthorityTests и сценарии перерегистрации зелёные без правок логики;
  • docs/certificate-rotation.md описывает выполнимую процедуру, а не намерение;
  • Control suite прогнан на Linux;
  • PR создан, CI зелёный;
  • независимый review получил полный текст этого задания.

Границы

  • не трогать LinkService.cs, LinkPolicyApplier.cs, LinkReconciliationBackgroundService.cs, ControlStore.cs в части Links, Provisioning.Helper/* и deploy/ochenstarik-smm-policy-apply — они заняты заданием B-3R;
  • CRL не вводить;
  • автоматическую ротацию CA не реализовывать;
  • приватный ключ Control CA остаётся на Hub и в enrollment-коды не попадает.

Отчётность

Раздельно перечислить: что запущено локально, что в CI, что не запускалось и почему. Статус после merge — merged / verified.