Как мы встроили ACME в центр сертификации

С протоколом ACME администратору не нужно каждый раз вручную создавать запрос, проходить проверку домена, скачивать сертификат и устанавливать его на сервер. Все автоматизировано. И эта автоматизация особенно удобна сейчас, когда сроки действия TLS-сертификатов сокращаются.
В публичной Web PKI уже действует поэтапное уменьшение максимального срока: до 200 дней с марта 2026 года, до 100 дней с марта 2027 года и до 47 дней с марта 2029 года. Пусть эти требования не распространяются на наш центр сертификации автоматически — мы не входим в CA/Browser Forum, — но они показывают, куда движется отрасль: ручное управление сертификатами становится все менее практичным. Поэтому мы решили реализовать в нашем центре стандартный серверный ACME-интерфейс, совместимый с распространенными клиентами, и при этом не обходить политики выпуска и границы безопасности действующего ЦС.
Меня зовут Александр Венедюхин. В «Техническом центре Интернет» (ТЦИ) я и моя команда поддерживаем и развиваем Центр сертификации TLS – первый в России коммерческий центр сертификации TLS, часть структур «РТК-ЦОД». Поэтому задача вывести ACME в прод легла на нас. В статье расскажу, как устроен сервис, какие задачи мы решили при интеграции и какие ограничения есть у первой версии.
Что такое ACME
Открытый протокол ACME, описанный в RFC 8555, сейчас фактически стал стандартом для автоматического выпуска сертификатов и управления ими. Он задает взаимодействие клиента и центра сертификации — создание аккаунта и заказа, подтверждение управления доменным именем, передачу CSR, получение и отзыв сертификата — и позволяет автоматизировать весь регулярный цикл работы с TLS-сертификатами.
Перечисленные задачи берет на себя ACME-клиент: например, acme.sh, Certbot или lego. Для работы подходит стандартный клиент, если он учитывает текущие ограничения нашего центра сертификации. Также выпуск TLS-сертификатов можно включать в автоматизированные процессы: от настройки веб-сервера до CI/CD и управления большим количеством доменов.
Со стороны пользователя все выглядит привычно: клиент создает заказ, подтверждает управление доменом и получает сертификат. Но на стороне центра сертификации ACME нельзя было просто взять и добавить как еще один HTTP API. Нужно было встроить его в существующий процесс проверки доменов и выпуска сертификатов, провести запросы через границы изолированных контуров, связать состояния ACME-заказа с внутренними операциями ЦС и сохранить публикацию сертификатов в Certificate Transparency.
Почему это не просто HTTP API
На внешнем уровне ACME действительно выглядит как набор HTTP-запросов с JSON. Основная сложность начинается глубже: состояния протокола нужно согласовать с внутренним жизненным циклом сертификата и при этом не нарушить разделение зон безопасности.
CSR появляется не сразу
В ACME клиент передает CSR на этапе финализации заказа — после того, как подтвердил управление всеми заявленными именами. Существующий процесс нашего центра сертификации был устроен иначе: CSR поступал до подтверждения домена, поскольку часть внутренних проверок была привязана к открытому ключу из запроса.
В результате нам потребовался отдельный слой управления заказом. Он хранит состояние ACME-процесса, связывает подтвержденные идентификаторы с CSR, который поступает позднее, и только после этого передает данные во внутренний контур выпуска.
На финализации мы не копируем содержимое CSR в сертификат целиком. ЦС извлекает открытый ключ, проверяет его параметры, сравнивает имена с идентификаторами исходного заказа и применяет собственные фильтры политики выпуска. Для ACME сейчас поддерживается ECDSA P-256.
Публичный API и изолированный контур
Основная часть систем центра сертификации изолирована от внешних сетей. Публичный ACME API не должен был создавать прямой путь от интернета к подписывающему контуру.
Мы разделили внешний протокольный слой и внутренние операции ЦС. Публичная часть принимает и проверяет ACME-запросы, управляет аккаунтами и состояниями заказов. Дальнейшие операции проходят через контролируемые внутренние интерфейсы: подтверждение домена, проверку политики, формирование сертификата и передачу данных для подписания.
Такое разделение важно еще и потому, что ACME-процесс асинхронный. Проверка DNS, обращение к веб-серверу домена, выпуск сертификата или получение Signed Certificate Timestamp (SCT) могут занять время либо завершиться ошибкой. Внешнее состояние заказа должно корректно отражать результат каждой внутренней операции, не раскрывая устройство защищенного контура.
DCV пришлось адаптировать
До внедрения ACME у нас уже работали механизмы Domain Control Validation (DCV). Однако проверки через DNS и веб-сервер в существующем виде было недостаточно: ACME определяет конкретные форматы данных и порядок их обработки.
В DNS-01 клиент публикует TXT-запись с вычисленным значением по имени _acme-challenge.<домен>. ACME-сервер запрашивает ее через DNS и при совпадении значения подтверждает управление доменом.
В HTTP-01 клиент размещает файл по адресу:
http://<домен>/.well-known/acme-challenge/<token>
Сервер ЦС получает этот файл по HTTP и проверяет его содержимое. Для такого сценария веб-сервер должен быть доступен извне на порту 80 на время проверки.
Нам пришлось встроить оба типа challenge в действующий механизм DCV, добавить ACME-формат _acme-challenge, связать результат проверки с конкретной авторизацией и корректно обрабатывать повторные обращения клиента.
Certificate Transparency остается частью выпуска
После проверки домена и CSR сертификат еще нельзя сразу вернуть клиенту. Сертификаты промышленного ЦС ТЦИ выпускаются с SCT-метками российских CT-логов Яндекса и VK.
SCT подтверждает, что сертификат принят CT-логом для включения в публично проверяемый журнал. Наличие SCT не заменяет остальные проверки TLS: приложение по-прежнему проверяет цепочку доверия, срок действия сертификата и соответствие доменного имени.
Промышленные CT-логи нельзя использовать для отладки тестовой цепочки, поэтому на стейджинге работает внутренний имитатор CT-лога. Его SCT можно увидеть в тестовых сертификатах, но сами эти сертификаты не предназначены для использования за пределами staging-среды.
Почему API использует внешнюю цепочку доверия
TLS-соединение с ACME Directory должно устанавливаться еще до того, как клиент получит наш сертификат. Поэтому сертификат самого ACME API строится на цепочке, которая уже присутствует в распространенных хранилищах доверия, а не на корневом сертификате ЦС ТЦИ.
Иначе возникает проблема первоначального доверия: чтобы безопасно получить данные от сервиса, клиент уже должен располагать доверенным корнем для проверки его TLS-сертификата. Доверие к такой цепочке устанавливается независимо от ACME — например, при установке или обновлении операционной системы либо приложения.
Корневой сертификат ЦС ТЦИ при необходимости следует распространять независимо от ACME — например, через централизованные политики управления операционными системами и приложениями..
Что мы запустили
Промышленный ACME Directory доступен по адресу: https://acme.tlscc.ru/directory
Для проверки интеграций работает отдельная staging-среда: https://acme.stage.tlscc.ru/directory
Стейджинг использует собственную тестовую цепочку сертификации. Ее корневой сертификат не входит в доверенные хранилища браузеров и операционных систем, поэтому выпущенные там сертификаты нельзя использовать на публичных ресурсах. Среда предназначена для отладки ACME-клиентов, сценариев подтверждения домена и автоматической установки сертификатов.
В первой промышленной версии доступны:
HTTP-01 и DNS-01 для подтверждения управления доменом;
выпуск TLS-сертификатов в ветке ECDSA A1;
ключи ECDSA P-256 для оконечных сертификатов;
отзыв сертификатов через ACME;
работа через стандартные ACME-клиенты, способные сформировать запрос с учетом ограничений ЦС ТЦИ.
Выпуск сертификатов с криптосистемой ГОСТ через ACME пока не поддерживается, но их по-прежнему можно получать через другие интерфейсы ЦС ТЦИ.
Сертификаты промышленной ветки строятся до корневого сертификата TCI ECDSA ROOT A1. Если этот корневой сертификат отсутствует в доверенном хранилище конкретной операционной системы или приложения, его потребуется установить отдельно. Иными словами, доступность ACME автоматизирует выпуск и обновление сертификата, но сама по себе не добавляет корневой сертификат ЦС в хранилище доверия клиента.
Как проходит ACME-заказ
В упрощенном виде выпуск выглядит так:
Клиент обращается к Directory и получает адреса ресурсов ACME API.
Клиент создает ACME-аккаунт или использует существующий.
Клиент формирует заказ на сертификат для доменного имени.
Сервер предлагает доступные способы подтверждения управления доменом.
Клиент выполняет HTTP-01 или DNS-01, после чего ЦС проверяет результат.
Когда авторизация получена, клиент передает CSR через ресурс finalize.
ЦС сопоставляет имена в заказе и CSR, проверяет параметры открытого ключа и применяет внутреннюю политику выпуска.
Сертификат получает необходимые SCT и становится доступен клиенту вместе с цепочкой.
ACME использует собственную модель ресурсов и состояний. Аккаунт, заказ, авторизация и проверка — это отдельные объекты, а переход к следующему этапу возможен только после успешного завершения предыдущего. Запросы клиента подписываются с помощью JWS, а одноразовые значения nonce защищают их от повторного воспроизведения.
Закрытый ключ ACME-аккаунта и закрытый ключ оконечного сертификата выполняют разные задачи. Первый аутентифицирует запросы аккаунта к ACME API. Второй – закрытый ключ TLS-сервера клиента – остается у владельца сертификата, а соответствующий ему открытый ключ передается в CSR. Для отзыва сертификата ACME также позволяет авторизовать запрос с помощью ключа самого сертификата.
Ограничения первой версии
ACME-сервис уже работает в промышленной среде, но часть ограничений существующего ядра ЦС пока сохраняется.
Полноценный multi-SAN пока недоступен
Через ACME-клиент пока нельзя заказать сертификат с произвольным набором независимых DNS-имен. Клиент передает основное имя домена, а состав выпущенного сертификата определяется действующим профилем ЦС: для ряда сертификатов он может включать соответствующее имя с www. Это ограничение связано с внутренним сопоставлением имен при выпуске, а не с возможностями протокола ACME: RFC 8555 допускает несколько идентификаторов в заказе.
В CSR обязателен Subject/CN
Доменное имя должно присутствовать в поле Subject/CN запроса на сертификат. Для самого ACME это необязательно: стандарт допускает размещение имен в subjectAltName. Требование связано с текущей логикой ядра нашего ЦС. Поэтому для совместимости клиент должен поддерживать RFC 8555 и уметь формировать CSR с заполненным Subject/CN. Это особенно важно проверить перед переносом готовой конфигурации с другого ACME-сервера.
DNS-01 не следует делегировать через CNAME
При DNS-01 TXT-запись необходимо размещать непосредственно по имени _acme-challenge в проверяемой DNS-зоне либо делегировать acme-challenge на отдельные авторитативные серверы. Хотя модуль DNS-проверки ACME сейчас и поддерживает один переход по CNAME, мы не рекомендуем использовать такую конфигурацию.
Для отзыва нужно указать причину
В RFC 8555 причина отзыва является необязательным параметром, однако внутренний процесс формирования CRL в ЦС ТЦИ требует ее указать. Поддерживаются следующие причины из RFC 5280:
keyCompromise — код 1;
superseded — код 4;
cessationOfOperation — код 5.
Эти ограничения мы рассматриваем как свойства первой версии. В следующих обновлениях планируем расширить поддержку SAN и разрешить CSR без обязательного доменного имени в Subject/CN.
Как попробовать сервис
Начинать лучше со стейджинга: это позволяет проверить автоматизацию, не создавая промышленный сертификат.
Пример выпуска через acme.sh с HTTP-01:
./acme.sh --issue \
-d example.com \
--standalone \
--keylength ec-256 \
--server https://acme.stage.tlscc.ru/directoryВ режиме --standalone acme.sh временно запускает собственный HTTP-сервер. Перед выполнением команды нужно освободить порт 80 и убедиться, что он доступен извне по доменному имени из заказа.
После успешной проверки на стейджинге можно заменить адрес Directory на промышленный:
./acme.sh --issue \
-d example.com \
--standalone \
--keylength ec-256 \
--server https://acme.tlscc.ru/directoryПеред использованием в проде нужно учесть требования к Subject/CN, ключу ECDSA P-256 и составу доменных имен. Параметр --keylength ec-256 в примерах явно задает поддерживаемый тип ключа. Если вы самостоятельно формируете CSR без Subject/CN, запрос будет отклонен текущей версией ядра ЦС.
Основные настройки сведены ниже.
Параметр | Production | Staging |
ACME Directory | https://acme.tlscc.ru/directory | https://acme.stage.tlscc.ru/directory |
Challenge | HTTP-01, DNS-01 | HTTP-01, DNS-01 |
CAA-идентификатор | tlscc.ru | stage.tlscc.ru |
Сертификаты ЦС и CRL | http://ca.cstls.ru/list/ | http://ca.stage.tlscc.ru/list/ |
Цепочка доверия | Промышленная ECDSA A1 | Отдельная тестовая цепочка |
Назначение | Рабочие сертификаты | Проверка интеграций |
Конкретные адреса промежуточных сертификатов и CRL также указываются в расширениях каждого выпущенного сертификата.
Если в домене настроена CAA, она должна разрешать выпуск для соответствующей среды. CAA не подтверждает управление доменом и не заменяет HTTP-01 или DNS-01: эта запись только ограничивает перечень центров сертификации, которым владелец домена разрешает выпуск.
Что дальше
Для пользователя ACME — это несколько команд и автоматическое обновление сертификата. Для центра сертификации — отдельный слой управления состояниями и доверием, который должен охватывать весь жизненный цикл: от создания заказа и подтверждения домена до публикации в CT и отзыва.
В нашем случае основная работа была связана с согласованием ACME-модели с существующим ядром ЦС, DCV, изолированным подписывающим контуром и Certificate Transparency. Теперь этот процесс доступен через стандартный интерфейс — сначала для проверки на стейджинге, а затем для промышленного использования.
В ближайшее время мы планируем расширить возможности ядра и автоматизацию вокруг него:
полноценная поддержка нескольких имен в SAN;
прием CSR без обязательного Subject/CN;
расширение перечня способов валидации;
поддержка ACME Renewal Information — ARI, описанного в RFC 9773.
ARI позволяет центру сертификации рекомендовать клиенту окно для следующего продления. Так проще распределять нагрузку и, если потребуется, быстрее запустить массовую замену сертификатов. Решение о продлении при этом остается на стороне ACME-клиента.
Если вы уже реализовали ACME, поделитесь, с какими клиентами и сценариями работаете. Особенно интересны интеграции с панелями управления, CI/CD, Kubernetes и системами централизованного управления сертификатами. До связи!
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.