Когда клиент аутентифицируется методом tls_client_auth, edge действует от его имени, а auth узнаёт его по сертификату X.509, предъявленному при TLS-рукопожатии. На странице описаны три способа, как этот сертификат попадает в edge, как он обновляется и что может сломаться. Она нужна, если вы используете нативные приложения или веб-клиент за edge с аутентификацией по сертификату. Должны быть настроены central и auth с mutual-TLS-слушателем (Токены с привязкой к отправителю).
Три режима
Режим выбирается для каждого клиента при регистрации. Мастер в консоли выбирает его сам: Mobile or desktop app регистрируется с enrollEdgeClientCertificate, Web app — с issueEdgeClientCertificate.
| Issue | Enroll | cert-sync | |
|---|---|---|---|
| Поле клиента | issueEdgeClientCertificate: true | enrollEdgeClientCertificate: true | edgeClientCertificate, который вы передаёте сами |
| Кто генерирует ключ | 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 по шагам
- Вы регистрируете клиента с
enrollEdgeClientCertificate: true,authMethod: tls_client_auth,applicationType: nativeи, при желании,mtlsAuth. БезmtlsAuthклиент опознаётся по subjectCN=<client>,OU=<tenant>,O=Versola.centralхранит только факт, что клиент подключён к enrollment. edgeзагружает клиентов изcentralкаждыеconfiguration-cache-refresh-interval. Для такого клиента в записи есть subject, который должен быть в сертификате, а самого сертификата нет.- Реплика генерирует в памяти пару ключей EC P-256 и запрос PKCS#10 именно на этот subject.
- Она отправляет запрос на
POST {central.url}/configuration/clients/edge-certificate/sign, аутентифицируясь подписанным токеном, которыйedgeиспользует во всех синхронизирующих вызовах. Вызвать этот эндпоинт может только зарегистрированныйedge, и в административный API он не входит. centralпроверяет, что клиент подключён к enrollment, что этот edge обслуживает тенант клиента и что запрос называет в точности зарегистрированные subject и альтернативные имена. Затем он просит УЦ подписать (срок задаётclient-certificates.validity), проверяет, что в выданном сертификате есть то, чего ожидаетmtlsAuth, записывает серийный номер, время и edge в таблицуedge_certificate_enrollmentи возвращает цепочку.edgeзаписывает сертификат и ключ в файлы, потому что TLS-библиотека принимает пути к файлам, и предъявляет их при вызовахauth.
Ротация входит в тот же цикл. При каждой загрузке клиентов сертификат, у которого осталась треть срока или меньше, заменяется. Для 14 дней по умолчанию это примерно 4 суток 16 часов. Если УЦ в это окно недоступен, edge продолжает использовать текущий сертификат до истечения и пишет в лог edge_certificate_renewal_failed. После перезапуска enrollment выполняется заново, это одно подписание на клиента.
Сроки
| Параметр | Где | По умолчанию |
|---|---|---|
| Срок действия сертификата | central, client-certificates.validity | 14 days |
| Обновить выданный сертификат, когда осталось меньше | central, client-certificates.renew-before | 4 days |
Как часто central проверяет выданные сертификаты | central, client-certificates.check-interval | 1 hour |
| Обновление сертификата из enrollment | edge, зафиксировано | когда осталась треть срока |
Когда 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-manager | Kubernetes | CertificateRequest, созданный от имени 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 | Закреплённые сертификаты |
Что дальше
- Нативные приложения: поток, в котором используется этот сертификат.
- Конфигурация edge: блок
nativeи закреплённые сертификаты. - Как собрать поток нативного мобильного приложения: создайте клиента и пройдите вызовы.