Клиентские сертификаты edge — Versola Docs
VersolaVersola/docs
До 1.00.7.1versola.kzGitHub

Клиентские сертификаты edge

Как edge получает клиентский сертификат для mutual-TLS-слушателя auth в трёх режимах (issue, enroll, cert-sync): сроки, расположение файлов, УЦ в central, что мониторить и как всё ломается.

Когда клиент аутентифицируется методом tls_client_auth, edge действует от его имени, а auth узнаёт его по сертификату X.509, предъявленному при TLS-рукопожатии. На странице описаны три способа, как этот сертификат попадает в edge, как он обновляется и что может сломаться. Она нужна, если вы используете нативные приложения или веб-клиент за edge с аутентификацией по сертификату. Должны быть настроены central и auth с mutual-TLS-слушателем (Токены с привязкой к отправителю).

Три режима

Режим выбирается для каждого клиента при регистрации. Мастер в консоли выбирает его сам: Mobile or desktop app регистрируется с enrollEdgeClientCertificate, Web app — с issueEdgeClientCertificate.

IssueEnrollcert-sync
Поле клиентаissueEdgeClientCertificate: trueenrollEdgeClientCertificate: trueedgeClientCertificate, который вы передаёте сами
Кто генерирует ключcentralкаждая реплика edge, в памятитот, кто выпускает сертификат
Где хранится ключВ central, в зашифрованном виде, и синхронизируется в edge, зашифрованный под его RSA-ключТолько в процессе реплики edgeВ central, как в предыдущем режиме
Сертификатов на репликиОдин общийПо одному на реплику, с одинаковым subjectОдин общий
Кто обновляетcentral, за renew-before до истеченияedge, когда остаётся треть срокаТот, кто выпускает, а cert-sync копирует новый
Типы клиентовВеб или нативныйТолько нативный (applicationType: native)Веб или нативный
СтатусОстаётся для существующих клиентовПредпочтителен для новых нативных клиентовДля УЦ, который вы ведёте сами

Первые два режима взаимно исключают друг друга и исключают переданный вами сертификат. Почему enroll только для нативных: токены веб-клиента привязаны к его сертификату (RFC 8705), поэтому все реплики должны предъявлять один и тот же, а реплики, получающие каждая свой, так не смогут. Токены нативного приложения привязаны к DPoP-ключу устройства, поэтому подойдёт сертификат любой реплики.

Во всех трёх режимах УЦ, выпустивший сертификат, должен быть доверенным для auth: он должен лежать в файле mutual-tls.trusted-certificates у auth.

Enrollment по шагам

  1. Вы регистрируете клиента с enrollEdgeClientCertificate: true, authMethod: tls_client_auth, applicationType: native и, при желании, mtlsAuth. Без mtlsAuth клиент опознаётся по subject CN=<client>,OU=<tenant>,O=Versola. central хранит только факт, что клиент подключён к enrollment.
  2. edge загружает клиентов из central каждые configuration-cache-refresh-interval. Для такого клиента в записи есть subject, который должен быть в сертификате, а самого сертификата нет.
  3. Реплика генерирует в памяти пару ключей EC P-256 и запрос PKCS#10 именно на этот subject.
  4. Она отправляет запрос на POST {central.url}/configuration/clients/edge-certificate/sign, аутентифицируясь подписанным токеном, который edge использует во всех синхронизирующих вызовах. Вызвать этот эндпоинт может только зарегистрированный edge, и в административный API он не входит.
  5. central проверяет, что клиент подключён к enrollment, что этот edge обслуживает тенант клиента и что запрос называет в точности зарегистрированные subject и альтернативные имена. Затем он просит УЦ подписать (срок задаёт client-certificates.validity), проверяет, что в выданном сертификате есть то, чего ожидает mtlsAuth, записывает серийный номер, время и edge в таблицу edge_certificate_enrollment и возвращает цепочку.
  6. edge записывает сертификат и ключ в файлы, потому что TLS-библиотека принимает пути к файлам, и предъявляет их при вызовах auth.

Ротация входит в тот же цикл. При каждой загрузке клиентов сертификат, у которого осталась треть срока или меньше, заменяется. Для 14 дней по умолчанию это примерно 4 суток 16 часов. Если УЦ в это окно недоступен, edge продолжает использовать текущий сертификат до истечения и пишет в лог edge_certificate_renewal_failed. После перезапуска enrollment выполняется заново, это одно подписание на клиента.

Сроки

ПараметрГдеПо умолчанию
Срок действия сертификатаcentral, client-certificates.validity14 days
Обновить выданный сертификат, когда осталось меньшеcentral, client-certificates.renew-before4 days
Как часто central проверяет выданные сертификатыcentral, client-certificates.check-interval1 hour
Обновление сертификата из enrollmentedge, зафиксированокогда осталась треть срока
Когда edge замечает изменениеedge, configuration-cache-refresh-intervalгенерируется 5 minutes

central обновляет только те сертификаты, которые сам выпустил. Если вы передадите сертификат через обновление клиента, central перестанет вести сертификат этого клиента. POST /configuration/clients/edge-certificate/renew?clientId=<id> немедленно обновляет один выданный сертификат.

Где лежат файлы

edge не хранит ни ключ, ни сертификат в базе. Чтобы предъявить их, он записывает файлы во временный каталог versola-client-certificates* в системном временном каталоге, созданный с правами 700. Каждый файл создаётся с правами 600 и называется по SHA-256 своего содержимого, так что обновлённый сертификат ложится рядом со старым. При штатной остановке каталог удаляется. После аварийного завершения он остаётся: не размещайте временный каталог на общих или постоянных томах и ограничьте доступ к файловой системе контейнера.

УЦ в central

central не хранит ключ УЦ. Подписание он делегирует бэкенду, указанному в блоке client-certificates его конфигурации. Задаётся ровно один из step-ca и cert-manager.

client-certificates {
  validity     = "14 days"
  renew-before = "4 days"
  step-ca {
    url              = "https://step-ca.example.com:9000"
    root-certificate = "/app/ca/root_ca.crt"
    provisioner      = "central"
    provisioner-key  = "/app/ca/provisioner.json"
  }
}
БэкендГде используетсяКак подписывает
step-caЦели на Compose (локальный Docker, vps)Одноразовый токен от JWK-провижионера central с максимумом 14 дней и шаблоном, который сохраняет subject запроса и ограничивает сертификат клиентской аутентификацией. Ключ провижионера — единственный секрет, который хранит central
cert-managerKubernetesCertificateRequest, созданный от имени service account пода, которому разрешено только создавать, читать и удалять такие объекты в своём namespace. Ключи: issuer-name, а также issuer-kind (по умолчанию ClusterIssuer), issuer-group (по умолчанию cert-manager.io) и namespace (по умолчанию namespace пода)
client-certificate-authorityТолько локальная разработкаcentral хранит сертификат УЦ и его ключ и подписывает сам. Используется, если ни один блок client-certificates не называет УЦ. В других окружениях лучше не применять

step-ca, созданный до появления шаблона с сохранением subject, переписывает subject в голый CN. Тогда central отклоняет более длинную регистрацию subject_dn и объясняет причину. Без УЦ central отклоняет регистрацию, которая просит выпущенный сертификат.

cert-sync

Для УЦ, который вы ведёте сами, или cert-manager, выпускающего сертификаты через pki.clients чарта, команда cert-sync из образа versola-tools копирует сертификаты в central. Она читает $CERT_SYNC_DIR/<client-id>/tls.crt и tls.key (незашифрованный PKCS#8) и отправляет PUT /configuration/clients только с edgeClientCertificate, когда содержимое меняется.

ПеременнаяЗначение
CENTRAL_URLБазовый URL Central API
CENTRAL_SECRET, CENTRAL_SECRET_FILE, CENTRAL_RESOURCE_SECRETСекрет ресурса central для Basic-аутентификации
CERT_SYNC_INTERVAL_SECONDSСекунды между проходами. 0 — один проход и выход

По умолчанию выключено.

Что мониторить

  • Логи edge. В строке лога запроса есть ключ error. edge_certificate_unavailable означает, что клиент исключён, потому что сертификат получить не удалось. edge_certificate_renewal_failed означает, что обновление не удалось и используется старый сертификат, срок его действия указан в описании.
  • Логи central. Каждое подписание пишет signed certificate <serial> for client '<id>' at edge '<edge>', valid until <time>. Каждый выпуск тоже пишет серийный номер и срок. Настройте оповещение для клиента, у которого последнее подписание старше двух третей срока действия.
  • Таблицы. edge_certificate_enrollment (клиенты в enrollment, последнее подписание) и client_certificate_issuance (выпущенные сертификаты: серийный номер и срок, без ключей) служат журналом аудита.
  • Признаки. Если /native/* отвечает 404 для существующего клиента или auth возвращает 401 invalid_client, чаще всего у edge нет действующего сертификата для этого клиента.

Режимы отказа

ПризнакПричинаЧто делать
/native/* возвращает 404 для клиентаУ edge нет сертификата для него: enrollment не удался, клиент не относится к тенантам этого edge или нет блока nativeПосмотрите в логе edge edge_certificate_unavailable и ответ central
central отказывает в запросе на подписаниеКлиент не подключён к enrollment, не обслуживается этим edge или запрос не называет зарегистрированный subjectПроверьте регистрацию. Повтор не поможет
central отклоняет подписанный результатВ сертификате УЦ нет типа и значения subject из mtlsAuth (например, шаблон УЦ переписывает subject)Исправьте шаблон УЦ или значение mtlsAuth
Регистрация отклонена: нет УЦissueEdgeClientCertificate без блока client-certificates или client-certificate-authorityНастройте бэкенд
auth возвращает invalid_clientВыпустивший УЦ не входит в mutual-tls.trusted-certificates у authДобавьте УЦ в этот файл и перезапустите auth. На время смены УЦ держите в файле оба
Вызовы падают после истечения УЦЗакончился срок самого сертификата УЦ, и выпуск сообщает об этомЗамените УЦ
edge не может подключиться к слушателю authНе совпало закрепление: native.trusted-certificates не соответствует конечному сертификату, который предъявляет authЗакреплённые сертификаты

Что дальше