Двухуровневая схема защищает корневой CA: он подписывает только промежуточные CA и большую часть времени недоступен. Сертификаты для сервисов выпускает промежуточный CA в Stronghold.
Цель
Развернуть корневой CA, промежуточный CA в Stronghold, роль для выпуска серверных сертификатов, публикацию CRL и OCSP и подключить потребителей: cert-manager и ACME-клиентов.
Предварительные требования
Перед началом подготовьте:
- Токен Stronghold с правами на включение механизмов секретов и запись в
pki*/. - Утилиты
jqиopensslна рабочей станции. - Внешний адрес Stronghold, доступный клиентам, — в примерах
https://stronghold.example.com. - Домен для сертификатов — в примерах
example.com.
Шаг 1. Подготовьте корневой CA
Выберите один из вариантов.
Вариант A. Офлайн-корневой CA
Корневой CA хранится вне Stronghold (например, на изолированной машине или в HSM) и используется только для подписи промежуточных CA. В этом варианте в Stronghold нет mount pki_root, а шаг 3 выполняется с помощью средств офлайн-CA (openssl ca, openssl x509 -req или ПО вашего HSM). Сохраните сертификат корневого CA в файл root-ca.pem.
В этом варианте закрытый ключ корневого CA недоступен через API Stronghold: компрометация Stronghold или токена Stronghold не раскрывает его.
Вариант B. Корневой CA в отдельном mount
Если офлайн-CA не используется, держите корневой CA в отдельном mount, доступ к которому есть только у администраторов PKI.
Включите механизм секретов и задайте максимальный срок жизни:
d8 stronghold secrets enable -path=pki_root pki d8 stronghold secrets tune -max-lease-ttl=87600h pki_rootСгенерируйте корневой CA. Закрытый ключ (
internal) не покидает Stronghold:d8 stronghold write -field=certificate pki_root/root/generate/internal common_name="Example Root CA" issuer_name="root-2026" ttl=87600h > root-ca.pemОпубликуйте адреса выпускающего сертификата и CRL корневого CA:
d8 stronghold write pki_root/config/urls issuing_certificates="https://stronghold.example.com/v1/pki_root/ca" crl_distribution_points="https://stronghold.example.com/v1/pki_root/crl"
Для CA по ГОСТ укажите параметр key_type, например key_type=gost3410-256-paramset-a. Список допустимых значений приведён в справочнике API.
Шаг 2. Создайте промежуточный CA
Создайте mount для промежуточного CA и запрос на подпись сертификата.
Включите отдельный mount для промежуточного CA:
d8 stronghold secrets enable -path=pki_int pki d8 stronghold secrets tune -max-lease-ttl=43800h pki_intСгенерируйте ключ и запрос на подпись (CSR):
d8 stronghold write -format=json pki_int/intermediate/generate/internal common_name="Example Intermediate CA" | jq -r '.data.csr' > pki_int.csr
Шаг 3. Подпишите промежуточный CA корневым
Для варианта B выполните:
d8 stronghold write -format=json pki_root/root/sign-intermediate csr=@pki_int.csr format=pem_bundle ttl=43800h | jq -r '.data.certificate' > pki_int.pemДля варианта A подпишите pki_int.csr на офлайн-CA и сформируйте файл pki_int.pem, содержащий сертификат промежуточного CA и сертификат корневого CA.
Шаг 4. Импортируйте подписанный сертификат
Импортируйте подписанный сертификат промежуточного CA в mount pki_int:
d8 stronghold write pki_int/intermediate/set-signed certificate=@pki_int.pemЗадайте адреса CRL, OCSP и выпускающего сертификата, которые будут записаны в выпускаемые сертификаты:
d8 stronghold write pki_int/config/urls issuing_certificates="https://stronghold.example.com/v1/pki_int/ca" crl_distribution_points="https://stronghold.example.com/v1/pki_int/crl" ocsp_servers="https://stronghold.example.com/v1/pki_int/ocsp"Шаг 5. Создайте роль
Роль ограничивает домены и срок жизни сертификатов:
d8 stronghold write pki_int/roles/example-com allowed_domains="example.com" allow_subdomains=true max_ttl=720hДержите max_ttl коротким: чем короче срок жизни, тем реже нужен отзыв и тем меньше CRL.
Шаг 6. Выпустите сертификат
Выпустите сертификат для api.example.com по роли example-com:
d8 stronghold write pki_int/issue/example-com common_name="api.example.com" ttl=72hОтвет содержит certificate, issuing_ca, ca_chain, private_key и serial_number. Если закрытый ключ создаётся на стороне клиента, отправьте CSR на эндпоинт pki_int/sign/example-com.
Шаг 7. Настройте CRL и OCSP
Настройте пересборку CRL и очистку хранилища сертификатов.
Включите автоматическую пересборку CRL:
d8 stronghold write pki_int/config/crl auto_rebuild=true expiry=72hВключите автоматическую очистку просроченных и отозванных сертификатов:
d8 stronghold write pki_int/config/auto-tidy enabled=true tidy_cert_store=true tidy_revoked_certs=true safety_buffer=72hОтзыв сертификата выполняется по серийному номеру:
d8 stronghold write pki_int/revoke serial_number=<SERIAL_NUMBER><SERIAL_NUMBER>— значениеserial_numberиз ответа на выпуск сертификата.
Шаг 8. Подключите cert-manager
Для выпуска сертификатов для Ingress и подов Kubernetes используйте cert-manager с Issuer типа vault, указывающим на pki_int/sign/example-com. Настройка роли Stronghold и ресурсов cert-manager описана в разделе «Интеграция с cert-manager».
Шаг 9. Включите ACME (необязательно)
Механизм PKI поддерживает протокол ACME, поэтому сертификаты можно получать стандартными ACME-клиентами.
Задайте внешний адрес mount — он используется в ссылках ACME:
d8 stronghold write pki_int/config/cluster path="https://stronghold.example.com/v1/pki_int" aia_path="https://stronghold.example.com/v1/pki_int"Разрешите заголовки, необходимые протоколу ACME:
d8 stronghold secrets tune -passthrough-request-headers=If-Modified-Since -allowed-response-headers=Last-Modified -allowed-response-headers=Location -allowed-response-headers=Replay-Nonce -allowed-response-headers=Link pki_intВключите ACME и ограничьте роли:
d8 stronghold write pki_int/config/acme enabled=true allowed_roles="example-com" max_ttl=720hИспользуйте в ACME-клиенте каталог роли
https://stronghold.example.com/v1/pki_int/roles/example-com/acme/directory. По умолчанию для регистрации аккаунта требуется привязка к внешнему аккаунту (EAB, параметрeab_policy).
Проверка
Проверьте результат:
Проверьте цепочку выпущенного сертификата:
d8 stronghold write -format=json pki_int/issue/example-com common_name=test.example.com ttl=1h > test.json jq -r '.data.certificate' test.json > test.pem jq -r '.data.issuing_ca' test.json > int.pem openssl verify -CAfile root-ca.pem -untrusted int.pem test.pemПроверьте, что CRL доступен:
curl -s https://stronghold.example.com/v1/pki_int/crl/pem | openssl crl -noout -text | headПроверьте статус сертификата через OCSP:
openssl ocsp -issuer int.pem -VAfile int.pem -cert test.pem -url https://stronghold.example.com/v1/pki_int/ocsp -text
Очистка
Удалите объекты, созданные в этом руководстве.
- Отзовите тестовые сертификаты:
d8 stronghold write pki_int/revoke serial_number=<SERIAL_NUMBER>, где<SERIAL_NUMBER>— серийный номер сертификата. - Удалите локальные файлы
test.json,test.pem,int.pem. - Если стенд был тестовым, отключите mount:
d8 stronghold secrets disable pki_intиd8 stronghold secrets disable pki_root. Отключение mount удаляет ключи CA без возможности восстановления.