Files
MikrotikManager/deploy/TEST-ACME.md
T

46 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Реальная приёмка ACME — 2026-10-14
Принят блок 12.5.250: `mmt250-c22a9715.pngs.top`, CHR `104.165.244.7`, production Let's Encrypt DNS-01 / Cloudflare. Пользователь разрешил только собственные поддомены `mmt*` и подтвердил назначение сертификата сервисам с последующей очисткой. Звёздочка обозначает разрешённый префикс; в заявке использовалось точное обычное имя.
Временные credentials только в ignored private fixture; ключи/почта/account ID в Git не публикуются. Перед запуском проверить token/zone/account и отсутствие записей на точном FQDN и `_acme-challenge.FQDN`. Снять приватный native export, сертификаты/файлы и исходные `www-ssl`/`api-ssl`; сохранить исходную строку `acme_settings`, включая ключ ACME-аккаунта и дату. После окончания восстановить её полностью.
Текущий issuer создаёт TXT, выполняет ACME, синхронизирует A-запись с IPv4 сервера, импортирует leaf/key/chain и назначает сертификат **обоим** `www-ssl`/`api-ssl`, включая их. Переключатели trust-store не отключают назначение. Поэтому исходные параметры сервисов обязательны для отката. HTTP REST80 используется для управления во время проверки.
Ручной helper: `backend/scripts/acceptance/acme-live-issue.mjs`, private fixture через `MMAPP_ACME_FIXTURE` (по умолчанию ignored `tmp/acme250-private.json`). Требуется отдельно разрешённый тест, baseline, Portal fixture и SSH-туннель. Helper не заменяет native/DNS очистку; при уже сохранённом jobId новый выпуск блокируется. Неподтверждённый запрос сначала проверять по тому же ID, не отправлять новую задачу. Не запускать этот helper повторно без свежей подготовки: временные credentials после блока удалены.
Проверено: реальный Portal/UI, один POST issue, terminal done; trusted TLS/SNI/SAN, DNS A → `104.165.244.7`, REST HTTPS200 с обычной проверкой сертификата; RouterOS private key и назначение обоим сервисам. После теста сервисы восстановлены, собственные leaf/chain/files/job удалены, первоначальные коллекции/экспорт/settings совпали. Приложение удалило TXT; собственная A-запись удалена по проверенным имени/типу/content/ID. Даты PostgreSQL сравниваются после JSON-нормализации; неверное сравнение Date со строкой не должно повторять очистку.
Выданный публичный сертификат CA не объявляется отозванным: экземпляры и ключевые файлы на CHR удалены, DNS очищен; запись о выпуске сохраняется у CA. Это не тест автоматического renewal, CA revocation или нескольких backend.
Протоколы: [UI](../docs/ux-ui/acceptance/acme250-live-ui.json), [TLS](../docs/ux-ui/acceptance/acme250-tls.json), [DNS](../docs/ux-ui/acceptance/acme250-cloudflare.json), [native/cleanup](../docs/ux-ui/acceptance/acme250-native.json).
## Подготовка повторной выдачи / renewal — блок253 (2026-10-14)
Подготовлен конкретный домен `mmt253-8e62a941.pngs.top`, certName `mmt253-8e62a941`, CHR `104.165.244.7` (server2). Это обычное имя без wildcard. Этот раздел описывает следующий тест; выдача и продление253 ещё не запускались. Первичная выдача250 не доказывает замену сертификата при повторном импорте. HTTP ACK и terminal job сами по себе также не доказывают, какой leaf обслуживает TLS.
1. Перед изменениями снять свежий приватный baseline: native export, certificates/files/services; SQL ACME и renewal settings, список managed targets/jobs; scheduler state. Подтвердить отсутствие любых других managed targets/active jobs и DNS записей на обоих точных именах. Если они появились — остановиться до мутации. Не использовать удалённый baseline250.
2. Временно остановить автоматический certificates_renew через его настройки и дождаться отсутствия текущего запуска. Сохранить исходные настройки целиком. Не запускать несколько экземпляров collector. Настроить тестовый Cloudflare token и выполнить первый UI выпуск с новым requestId. Публично сохранить только terminal job/protocol и native metadata без секретов.
3. По аутентифицированному RouterOS чтению выбрать ровно один собственный leaf с exact name/CN, private-key=true и отпечатком; снять served TLS с SNI/обычной проверкой доверия. Если native fingerprint не SHA-256, сначала экспортировать только публичный сертификат и вычислить SHA-256 через X509Certificate; не интерпретировать другой алгоритм как SHA-256. Изолированная сводка для helper содержит только fqdn/certName/nativePrivateKey/nativeFingerprint256.
4. Read-only helper `node backend/scripts/acceptance/acme-renew-tls.mjs sample native-summary.json before.json` подключается только к104.165.244.7:443 с точным SNI, rejectUnauthorized=true и15s timeout. Требует совпадения native и TLS SHA-256, private key и hostname. Существующий output не перезаписывается. Этот helper ничего не выпускает и не меняет RouterOS/DNS.
5. Для реального collector renewal подтвердить канонический срок/статус leaf по state. Не менять даты на CHR и не обходить unknown guard252. Если RouterOS дата не распознаётся, записать препятствие и не запускать повторную выдачу. Для известного срока при выключенном renewal подготовить порог90 дней и интервал не менее3600s, подтвердить единственный собственный target. Затем один PUT enabled=true запускает certificates_renew через refreshScheduler немедленно: отдельный run-now НЕ отправлять. После terminal сразу выключить renewal до следующего интервала. Сохранить ID созданной scheduler-задачи; при неизвестном ACK проверять тот же ID, новый run не отправлять. Проверить source=scheduler, matching context, terminal done и snapshot renewed1/errors0.
6. Снять after.json тем же helper и сравнить `node backend/scripts/acceptance/acme-renew-tls.mjs compare samples.json comparison.json`, где samples.json содержит before/after. Новый SHA-256 должен отличаться от первого, native должен совпасть с served TLS. Не требовать увеличения expiry на целый день: обе выдачи могут быть в один день. Проверить оба назначения www-ssl/api-ssl и HTTPS REST с обычным доверием. Если job done, а TLS leaf прежний, это ошибка приёмки; не удалять первый leaf ради получения ложного успеха.
7. Независимо от результата остановить own renewal, вернуть исходные SSL сервисы, удалить только собственные exact cert IDs/fingerprints/PEM файлы/job IDs; вернуть ACME/renew settings целиком. Удалять только DNS записи с проверенными exact name/type/content/ID, не чужие записи. Подтвердить исходные коллекции, normalized export, settings и0 own DNS; удалить private baseline/token. Контрольный194.226.121.150 не менять, пароли не менять, перезагрузки не нужны.
Для этих двух выдач и повторного назначения SSL необходимо согласие на конкретный сценарий. Разрешение250 относилось к уже завершённому тесту. До согласия выполняются только подготовка/чтение. Полная регрессия и Docker build для изменения лишь ручного acceptance helper не нужны; comparator проверяется отдельно. CA revocation и multi-instance здесь не принимаются.
Нормативная справка для native полей/import: [MikroTik Certificates](https://help.mikrotik.com/docs/spaces/ROS/pages/2555969/Certificates). Документация не гарантирует успех повторного импорта в текущем приложении; именно это предстоит измерить.
## Ротация поколений — подготовка258 (2026-10-15)
Новый код проверяет неоднозначное исходное имя до CA order. Leaf/key импортируются под уникальным `<base>_new_<12hex>`. После проверки отпечатка/ключа оба SSL-сервиса переключаются на это поколение. Только после подтверждения назначений прежний объект переименовывается в `<base>_old_<12hex>`, новый получает исходное логическое имя, назначения и отпечаток проверяются повторно. Старый ключ не удаляется. API/DB requestId и certName остаются прежними; raw native IDs проверяются перед PATCH.
Подтверждается сохранение старого native ID/fingerprint, освобождение логического имени и неизменность нового поколения. Неизвестный ACK или внешнее изменение не дают success; автоматического повторного PATCH/слепого rollback нет. При поздней ошибке нужно сверить фактические назначения и оба поколения. Это ещё не обещание отсутствия краткого TLS reload и не приёмка нескольких одновременно работающих issuers.
Следующий реальный тест259: активировать подготовленный образ258, снять свежий baseline и выполнить согласованный first issue + scheduler renewal. Проверить ровно один leaf с логическим именем, один архив старого leaf с прежними ID/SHA-256/private-key и отсутствие незавершённых `_new_` объектов. Trusted TLS должен совпасть с новым leaf; canonical dates — с X509. Очистка должна учитывать собственные `_old_`/`_new_` имена с12hex, exact CN и записанные ID/fingerprints. Старый cleanup helper256, допускавший лишь exact logical/root имена, без адаптации не запускать. Удалять leaf поколения до собственных CA, затем проверить отсутствие и исходный export/files/services/settings. Чужие объекты не удалять.
Образ258 подготовлен и проверен локальными service сценариями; до этого реального теста активный backend остаётся257. Повторное согласование того же уже разрешённого сценария не требуется. Продление не объявляется принятым по fixtures.
## Реальная ротация принята — блок259 (2026-10-15)
First issue через настоящий Portal/UI и одно enable-triggered scheduler renewal того же exact домена завершены. Новый native ID/SHA-256, единственный logical name, один old archive с прежними ID/fingerprint/private-key и отсутствие unfinished new подтверждены. Оба trusted TLS samples совпали с соответствующими native leaf, отпечаток изменился; HTTPS REST200 после продления. Native/SSL/files/export/private SQL/DNS восстановлены, оба CHR доступны, private baseline/fixtures удалены. Активен backend258/frontend251. CA revocation не выполнялся. Протоколы находятся в docs/ux-ui/acceptance/acme259-*.json; следующий запуск требует свежего baseline, удалённый259 повторно не использовать.