Ssl-context-builder#

Плагин позволяет получать сертификаты из HashiCorp Vault или из хранилищ на файловой системе и формировать SSL-контекст. Также поддерживается расширение Kafka-клиента для интеграции с HashiCorp Vault.

Предусловия#

Не требуются.

Последовательность выполнения#

Подключение#

  1. Добавить актуальную версию плагина в зависимости проекта.

  2. Использовать необходимые классы для построения SSLContext.

Построение контекста из хранилищ из файлов#

Используется класс ru.sbt.ss.ssl.context.builder.SSLContextBuilder:

SSLContext context = SSLContextBuilder.builder()
        .withProtocol("TLSv1.2")
        .withConscrypt()
        .withKeyPassword("123".toCharArray())
        .withKeyStorePassword("456".toCharArray())
        .withTrustStorePassword("456".toCharArray())
        .withStoreType("JKS")
        .withKeyStoreLocation(storeLocation)
        .withTrustStoreLocation(storeLocation)
        .withDnList("CN=test,OU=FPSS,O=SBT,ST=Moscow,C=RU")
        .withEndpointVerificationAlgorithm("dn")
        .build();

Параметры SSLContextBuilder#

Имя

Описание

Значение по умолчанию

ssl.key.password

Пароль от ключа

ssl.keystore.location

Расположение хранилища сертификатов

ssl.keystore.password

Пароль от хранилища сертификатов

ssl.keystore.type

Тип хранилища сертификатов

JKS

ssl.truststore.location

Расположение хранилища доверенных сертификатов

ssl.truststore.password

Пароль от хранилища доверенных сертификатов

ssl.truststore.type

Тип хранилища доверенных сертификатов

JKS

ssl.protocol

Версия протокола TLS

TLSv1.2

ssl.endpoint.identification.algorithm

Алгоритм проверки хоста подключения

HTTPs

ssl.conscrypt

Использование библиотеки Conscrypt

false

ssl.allowed.dn

Белый список доверенных DN

ssl.allowed.dn.file

Путь до файла с белым списком доверенных сертификатов

security.encoding.class

Класс для расшифровки паролей

ru.sbt.ss.password.BaseEncryptor

security.encoding.key

Ключ для расшифровки паролей конфигурации

ssl.keystore.certificate.chain.location

Расположение сертификата, полученного из Vault

ssl.keystore.key.location

Расположение приватного ключа сертификата, полученного из Vault

ssl.truststore.certificates.location

Расположение файла с доверенными сертификатами, полученными из Vault

ssl.truststore.empty

Позволяет использовать builder без параметров ssl.truststore.*

false

ssl.vault.pki.trust.only

Признак формирования SSLContext только с использованием хранилища доверенных сертификатов

false

Построение контекста из HashiCorp Vault#

Используется класс ru.sbt.ss.ssl.context.builder.VaultContextBuilder:

// SSLContext для подключения к Vault
SSLContextBuilder builder = SSLContextBuilder.builder()
        .withTrustStoreLocation("/Users/sbt-navalikhin-an/workspace/apps/vault/vaultclient.jks")
        .withTrustStorePassword("qwe123".toCharArray())
        .withProtocol("TLSv1.2");

        SSLContext context = VaultContextBuilder.builder()
        .withVaultSSLContextBuilder(builder)
        .withAuth(new PasswordAuth("test", "qwe123".toCharArray(), "userpass"))
        .withKeyStoreLocation("client.jks")
        .withKeyAlias("test-1")
        .withTrustStoreLocation("client.jks")
        .withVaultAddress("https://vault:8200/")
        .withCommonName("TestCert")
        .withAltNames(Collections.singletonList("localhost"))
        .withIpSans(Collections.singletonList("127.0.0.1"))
        .withSecretPath("kv1/certstore")
        .withKeySecret("key")
        .withKeyStoreSecret("keystore")
        .withTrustStoreSecret("truststore")
        .withIssueRoleName("test1")
        .withEngineVersion(1)
        .withProtocol("TLSv1.2").build();

Получение сертификатов из консоли#

  1. Скачать ssl-context-builder-*.jar.

  2. Создать файл vault.properties с параметрами подключения к HashiCorp Vault.

  3. Выполнить команду:

java -jar ssl-context-builder-*.jar vault.properties
  1. Сертификаты будут расположены в хранилищах из параметров ssl.keystore.location и ssl.truststore.location.

Параметры VaultContextBuilder#

Параметры подключения и авторизации в Hashicorp Vault#

Имя

Описание

Значение по умолчанию

ssl.vault.address

Адрес подключения к Vault, обязательный параметр

ssl.vault.auth.type

Тип алгоритма аутентификации в Vault: approle, token, password, certificate, kubernetes

approle

ssl.vault.auth.mount

Путь до API аутентификации в Vault

ssl.vault.auth.role.id

Идентификатор роли приложения при ssl.vault.auth.type=approle

ssl.vault.auth.secret.id

Секрет роли приложения при ssl.vault.auth.type=approle

ssl.vault.auth.token

Токен для подключения к Vault при ssl.vault.auth.type=token

ssl.vault.auth.username

Имя пользователя для подключения к Vault при ssl.vault.auth.type=password

ssl.vault.auth.password

Пароль пользователя для подключения к Vault при ssl.vault.auth.type=password

ssl.vault.auth.rolename

Роль для подключения к Vault при ssl.vault.auth.type=kubernetes

ssl.vault.auth.jwt

Service account jwt для подключения к Vault при ssl.vault.auth.type=kubernetes. Значение с префиксом «env:» будет браться из переменных среды, с префиксом «file:» будет браться из файла

ssl.vault.auth.provider

Провайдер для подключения к Vault при ssl.vault.auth.type=kubernetes

kubernetes

ssl.vault.tls.enable

Включение протокола TLS при подключении к Vault

true

ssl.vault.tls.<параметр SSLContextBuilder>

Параметры для создания SSLContext при подключении по HTTPS к Vault

ssl.vault.namespace

Пространство имен в Vault

ssl.vault.engine.version

Версия Key-Value хранилища секретов

2

ssl.vault.retries

Количество попыток подключения к Vault

5

ssl.vault.retry.interval

Интервал между попыток подключения к Vault в миллисекундах

500

ssl.vault.timeout

Тайм-аут запроса к Vault в секундах

3

Общие параметры, применимые при использовании любого типа хранилищ сертификатов и режима получения клиентского сертификата#

Имя

Описание

Значение по умолчанию

ssl.truststore.add.vault.ca

Добавление в доверенные сертификаты цепочки vault CA (pki/ca_chain)

true

ssl.truststore.force.update

Принудительное получение доверенных сертификатов и перезапись truststore при каждом запуске

false

ssl.protocol

Версия протокола TLS

TLSv1.2

ssl.endpoint.identification.algorithm

Алгоритм проверки хоста подключения

HTTPs

ssl.conscrypt

Использование библиотеки Conscrypt

false

ssl.allowed.dn

Белый список доверенных DN

ssl.allowed.dn.file

Путь до файла с белым списком доверенных сертификатов

security.encoding.class

Класс для расшифровки паролей

ru.sbt.ss.password.BaseEncryptor

security.encoding.key

Ключ для расшифровки паролей конфигурации

ssl.vault.secret.path

Путь до Key-Value секрета с пароля для хранилищ сертификатов ssl.keystore.location и ssl.truststore.location

ssl.vault.secret.key

Имя поля с паролем от ключа

ssl.vault.secret.keystore

Имя поля с паролем от хранилища сертификатов ssl.keystore.location

ssl.vault.secret.truststore

Имя поля с паролем от хранилища сертификатов ssl.truststore.location

ssl.vault.pki.mount

Путь до API движка выпуска сертификатов в Vault, также используется для получения цепочки доверенных сертификатов

pki

ssl.vault.ca.chain.path

Путь до API получения цепочки доверенных сертификатов в vault, по умолчанию <ssl.vault.pki.mount>/ca_chain

ssl.vault.pem.trust.path

Путь до Key-Value секрета c доверенными сертификатами в формате PEM

ssl.vault.pem.trust.fail.on.invalid

При значении false позволяет игнорировать невалидные ключи в kv секрете с доверенными сертификатами

true

ssl.vault.pem.trust.check.ca

Проверка атрибута BasicContraints: [CA: true] при добавлении доверенных сертификатов из kv секрета. Если атрибут false – сертификат считается невалидным, дальнейшее поведение настраивается параметром ssl.vault.pem.trust.fail.on.invalid

false

ssl.vault.pem.trust.aliases

Список ключей в секрете, содержимое которых необходимо загрузить в хранилище доверенных сертификатов, разделитель запятая. По умолчанию список пустой и используются все ключи из секрета

ssl.vault.before.expire

Промежуток времени до истечения сертификата для его перевыпуска в формате java.time.Duration, поведение параметра ssl.vault.before.expire различается для kv и pki

PT0S

ssl.vault.alias.ca

Префикс идентификатора сертификата CA Vault – при нескольких сертификатах идентификатор будет формироваться объединением префикса и номера сертификата в цепочке

ca

ssl.vault.alias.key

Идентификатор ключа и сертификата, выпущенных Vault

key

Параметры хранения сертификатов в JKS хранилищах#

Имя

Описание

Значение по умолчанию

ssl.keystore.type

Тип хранилища сертификатов, полученных из Vault: jks

JKS

ssl.keystore.location

Расположение хранилища сертификатов, полученных из Vault

ssl.keystore.mode

Права доступа к файлу хранилища сертификатов в POSIX формате, «644» или «w-r–r–»

600

ssl.truststore.type

Тип хранилища доверенных сертификатов, полученных из Vault: jks

JKS

ssl.truststore.location

Расположение хранилища доверенных сертификатов, полученных из Vault

ssl.truststore.mode

Права доступа к файлу хранилища доверенных сертификатов в POSIX формате, «644» или «w-r–r–»

600

Параметры хранения сертификатов в формате PEM#

Имя

Описание

Значение по умолчанию

ssl.keystore.type

Тип хранилища сертификатов, полученных из Vault: pem

JKS

ssl.keystore.key.location

Расположение приватного ключа сертификата, полученного из Vault

ssl.keystore.key.mode

Права доступа к файлу приватного ключа сертификата в POSIX формате, «644» или «w-r–r–»

600

ssl.keystore.certificate.chain.location

Расположение сертификата, полученного из Vault

ssl.keystore.certificate.chain.mode

Права доступа к файлу сертификата в POSIX формате, «644» или «w-r–r–»

600

ssl.truststore.type

Тип хранилища доверенных сертификатов, полученных из Vault: pem

JKS

ssl.truststore.certificates.location

Расположение файла с доверенными сертификатами, полученными из Vault

ssl.truststore.certificates.mode

Права доступа к файлу с доверенными сертификатами в POSIX формате, «644» или «w-r–r–»

600

Параметры выпуска сертификата через PKI Engine HashiCorp Vault#

Имя

Описание

Значение по умолчанию

ssl.vault.pki.mode

Режим выпуска сертификатов: pki

pki

ssl.vault.pki.method

Метод выпуска сертификатов, issue или fetch

issue

ssl.vault.pki.role.name

Имя роли в движке выпуска сертификатов в Vault, обязательный параметр

ssl.vault.pki.common.name

Значение поля CN в выпускаемом сертификате

ssl.vault.pki.email

Электронный адрес владельца сертификата, задается при использовании Secret Manager

ssl.vault.pki.alt.names

Список хостов через запятую для поля SAN сертификата

ssl.vault.pki.alt.ip

Список IP адресов через запятую для поля SAN сертификата

ssl.vault.pki.ttl

Параметр TTL для выпускаемого сертификата

ssl.vault.pki.csr

Запрос на сертификат в формате pem

ssl.vault.pki.csr.path

Путь до файла с запросом на выпуск нового сертификата

ssl.vault.pki.trust.only

Признак формирования SSLContext только с использованием хранилища доверенных сертификатов

ssl.vault.pki.max.wait.time

Максимальное время ожидания момента валидности полученного сертификата в миллисекундах

10000

ssl.vault.pki.crl.enable

Включение проверки попадания сертификата в список отозванных. Настройка устарела, в качестве замены использовать настройку ssl.vault.pki.revocation.check.enabled

true

ssl.vault.pki.uri.sans

Список альтернативных имен объектов URI через запятую для поля SAN сертификата

ssl.vault.pki.other.sans

Список или фрагмент строки JSON пользовательских OID/UTF8-строк для поля SAN сертификата

ssl.vault.pki.not.after

Поле «Не после» сертификата указанное значение даты, формат значения должен быть указан в формате YYYY-MM-ddTHH:MM:SSZ

ssl.vault.pki.exclude.cn

Если значение true, указанное common_name не будет включено в альтернативные имена DNS или темы электронной почты

false

ssl.vault.pki.revocation.check.enabled

Включение проверки отзыва сертификата

true

ssl.vault.pki.revocation.check.prefer.crl

Включение проверки попадания сертификата в список отозванных по CRL перед проверкой по OCSP. По-умолчанию проверка проводится с помощью CRL, затем, в случае неудачи, с помощью OCSP

true

ssl.vault.pki.revocation.check.fallback.enabled

Включение резервной проверки, если первая проверка завершилась ошибкой

true

ssl.vault.pki.revocation.check.soft.fail.enabled

При наличии сетевых проблем с проверкой по OCSP и CRL, проверка отзыва не выполняется

false

Параметры получения клиентского сертификата из секрета KV Engine HashiCorp Vault#

Имя

Описание

ssl.vault.pki.mode

Режим выпуска сертификатов: со значением kv

ssl.vault.pem.name

Ключ сертификата в секрете

ssl.vault.pem.key

Ключ приватного ключа в секрете

ssl.vault.pem.path

Путь до секрета

ssl.vault.disable.pem.certificate.generation

Игнорирование параметров pem (по умолчанию false)

Пример конфигурации с загрузкой параметров из файла#

Любые настройки можно загрузить из файла (в данном примере config/vault.properties):

# 1) Путь до файла с параметрами
ssl.vault.properties.file = config/vault.properties

# 2) ОПЦИОНАЛЬНО Переопределить любые настройки, загруженные из файла конфигурации
# Common name сертификата (CN)
ssl.vault.pki.common.name = OVERRIDE-TEST

# Пути до хранилищ сертификатов, сгенерированных vault
ssl.keystore.location = override-vault-keystore.jks
ssl.truststore.location = override-vault-truststore.jks

Настройка функций обратного вызова (callback) метода verify() класса ru.sbt.ss.ssl.conscrypt.DnConscryptHostnameVerifier проверки DN сертификатов#

Для настройки сallback’ов необходимо:

  1. Реализовать интерфейс ru.sbt.ss.ssl.conscrypt.VerifyCallback

  2. При помощи библиотеки "ssl-context-builder" (версии 1.9.4+) получения контекста передать реализацию как параметр метода withDnVerifyCallback() при создании SSLContext с помощью класса ru.sbt.ss.ssl.context.builder.SSLContextBuilder:

SSLContext context = SSLContextBuilder.builder().withProperties(properties.asJava).withDnVerifyCallback(new CustomVerifyCallback()).build()
public class CustomVerifyCallback implements VerifyCallback {
    @Override
    public void onSuccess(X509Certificate cert, String address) {
        System.out.println("Call \"onSuccess\" method");
    }

    @Override
    public void onError(X509Certificate cert, String address, Throwable cause) {
        System.out.println("Call \"onError\" method");
    }
}

По умолчанию используется дефолтная реализация интерфейса ru.sbt.ss.ssl.conscrypt.VerifyCallback с пустым телом методов onSuccess/onError:

VerifyCallback defaultCallback = new VerifyCallback() {
    @Override
    public void onSuccess(X509Certificate cert, String address) {
        // nothing by default
    }

    @Override
    public void onError(X509Certificate cert, String address, Throwable cause) {
        // nothing by default
    }
};

Загрузка ключей из Vault#

Для загрузки ключей из vault можно использовать VaultContextBuilder. Пример настроек, необходимых для загрузки ключей:

encryption.service.key.store.type = vault
ssl.vault.address = { IP_ADDRESS }
ssl.vault.auth.role.id = role_id
ssl.vault.auth.secret.id = secret_key
ssl.vault.secret.path = test/encryptions/keys
ssl.vault.tls.enable = true
ssl.vault.tls.truststore.location = /vault.jks
ssl.vault.tls.truststore.password = password

, где ssl.vault.secret.path – путь, откуда будет выполнена загрузка всех ключей.

Пример загрузки ключей:

Map<String, String> keys = VaultContextBuilder.builder().withProperties(proprties).buildSecretLoader();

Использование движка SberCA#

Движок SberCA аналогичен стандартному движку pki, но в дополнение к стандартному запросу issue предоставляет запрос fetch.

Разница между методами в том, что issue всегда выпускает новый сертификат, а fetch выпускает новый сертификат только если сертификат не существует или истек. Во всем остальном запросы и настройки идентичны.

Для использования метода fetch используется настройка ssl.vault.pki.method=fetch.

При использовании метода fetch:

  • при каждом запуске приложения сертификат запрашивается из vault запросом SberCA/fetch;

  • при наличии локального кеша полученный сертификат сравнивается сертификатом в локальном кеше, используя fingerprint – по умолчанию SHA-256 хеш от сертификата;

  • если fingerprint полученного сертификата отличается от сертификата в локальном кеше – сертификат перезаписывается.

Результат#

Выполнено подключение плагина Ssl-context-builder.