Как вы упомянули, есть несколько способов сделать это, и это зависит от ваших конкретных c потребностей, какой из них будет работать лучше всего. Я постараюсь обрисовать как можно больше вариантов, а также плюсы и минусы каждого.
Если вам нужно всего лишь распространить доверенные сертификаты, добавьте Bo sh Доверенные сертификаты и разрешение Bo sh распространять их на все виртуальные машины и контейнеры в CF - хороший способ go. В Ops Manager под плиткой Bo sh введите go в Security, и вы можете добавить любое количество доверенных сертификатов.
Это хороший подход, когда несколько приложений должны доверять сертификатам, например, с корпоративный / частный центр сертификации. Он также хорошо работает с разными средами / основаниями, потому что у вас есть другой Ops Manager, который может поддерживать другой список доверенных сертификатов. Это может быть сложно управлять, если у вас есть много сертификатов, которым необходимо доверять, и / или если сертификаты используются только одним или небольшим количеством приложений. Для этого также требуются административные привилегии для CF и может потребоваться некоторое время для развертывания обновлений на всей основе.
Это вариант, о котором вы упомянули в своем вопросе. Импортируйте сертификат в файл хранилища доверенных сертификатов Java, упакуйте файл в приложение Java и укажите путь к нему через переменную среды JAVA_OPTS
. Файл хранилища доверенных сертификатов может быть помещен в каталог resource
.
Пример: cf set-env <app> JAVA_OPTS '-Djavax.net.ssl.trustStore=/home/vcap/app/BOOT-INF/classes/jssecacerts'
Этот параметр полезен для сценария ios, не охватываемого опцией № 1 выше, например одиночного или небольшие приложения, где есть сертификаты, уникальные для этого приложения. Например, у вас есть сервер базы данных, которому вы должны доверять, и только одно приложение использует этот сервер базы данных.
У него есть недостаток, о котором вы упомянули, хранилище доверенных сертификатов должно быть встроено в приложение, поэтому для обработки нескольких сред вы должны d нужно сделать что-то вроде упаковки всех сертификатов среды в одно хранилище доверенных сертификатов и упаковать его в один JAR / WAR для всех сред или создать несколько файлов JAR / WAR, по одному для каждой среды.
Он также имеет К сожалению, вы полностью переопределяете хранилище доверенных сертификатов по умолчанию. Хранилище доверенных сертификатов по умолчанию заполнено множеством хорошо известных сертификатов ЦС, поэтому вы должны начать с копии хранилища доверенных сертификатов по умолчанию и добавить сертификаты, которые вы хотите добавить. В противном случае вы потеряете список доверенных центров сертификации по умолчанию, и проверка будет нарушена для таких сайтов, как Google или Yahoo. Сертификат CA по умолчанию поставляется с каждой JRE, но он может варьироваться от версии к версии, поэтому вы должны поддерживать его в актуальном состоянии.
Это небольшое изменение от # 2. Создайте файл сценария в каталоге приложения root с именем .profile
. В нем запустите keytool
и импортируйте все сертификаты, которые упакованы с вашим приложением.
Пример:
#!/bin/bash
$HOME/.java-buildpack/open_jdk_jre/bin/keytool \
-keystore $HOME/.java-buildpack/open_jdk_jre/lib/security/cacerts \
-storepass changeit \
-importcert \
-noprompt \
-alias MyCert \
-file $HOME/BOOT-INF/classes/ssl/MyCert.crt
# TODO: repeat this command for all the certs you need to import
Затем запустите jar uf target/your-app.jar .profile
, чтобы добавить скрипт в root вашего приложения JAR / WAR. Сценарий должен существовать в root вашего JAR / WAR-файла, чтобы Cloud Foun dry мог его подобрать и запустить. Вы можете запустить jar tf target/your-app.jar | grep profile
, чтобы подтвердить это. На выходе должно быть указано .profile
без ведущего пути. Если есть начальный путь, значит файл был добавлен не в том месте.
Преимущество этого подхода в том, что вам не нужно предоставлять хранилище полного доверия. Это большой недостаток №2, и в этом случае вы будете аккуратно использовать хранилище доверенных сертификатов по умолчанию, упакованное с JRE, предоставляемым пакетом сборки Java. Сценарий добавит дополнительные сертификаты перед запуском вашего приложения.
Обратной стороной этого подхода является то, что добавление сертификата беспорядочно и его можно легко пропустить / забыть, что приведет к поломке вашего приложения. Он также должен находиться в очень конкретном c месте, чтобы Cloud Foun dry нашел его и выполнил. Обратная сторона необходимости упаковывать ваши сертификаты в JAR / WAR также присутствует в этой опции.
Следующая опция - это итерация # 3. В этом случае вы включаете сценарий .profile
, но не упаковываете сертификаты в свой JAR / WAR. Вместо этого вы предоставляете сертификаты через переменную среды или связанную службу (это прекрасно работает с брокером служб CredHub).
Чтобы это работало, вам нужно настроить скрипт так, чтобы он извлекал сертификат. переменной среды, создает временный файл и импортирует его в хранилище доверенных сертификатов по умолчанию с keytool
. В следующем примере показано извлечение его из переменной среды, но вы можете использовать jq
и извлечь его из VCAP_SERVICES
для привязанной службы.
Пример:
#!/bin/bash
$HOME/.java-buildpack/open_jdk_jre/bin/keytool \
-keystore $HOME/.java-buildpack/open_jdk_jre/lib/security/cacerts \
-storepass changeit \
-importcert \
-noprompt \
-alias MyCert \
-file <(echo $CERT_1)
# TODO: repeat this command for all the certs you need to import
Преимущества этого подхода такие же, как и в случае №3, за исключением того, что вам больше не нужно связывать сертификаты с вашим приложением. Их можно кормить извне. Обратной стороной является тот же самый сценарий .profile
, с которым сложно работать, и о нем можно забыть.
Вариант # 2 - установить системные свойства в вашем коде. Вам просто нужно, чтобы это произошло на ранней стадии запуска приложения, прежде чем JVM инициализирует TLS. Если это произойдет позже, ничего не произойдет и ваши сертификаты не будут найдены.
В этой статье объясняются различные места, где вы можете разместить код инициализации в приложении Spring Boot. По сути, вы просто используете это для вызова System.setProperty("javax.net.ssl.trustStore", "path/to/custom/truststore")
, а если вы меняете пароль, System.setProperty("javax.net.ssl.trustStorePassword", "newpassword")
.
Я не фанат этого подхода, потому что все может неожиданно сломаться, если TLS инициализирован раньше ваш код работает. IMHO, это сложно контролировать, особенно в Spring Boot со всеми его автоматическими конфигурациями (не то чтобы это плохо, просто вы должны быть очень осторожны с порядком). Я считаю, что это проще сделать в скрипте профиля, который гарантированно запускается до запуска вашего приложения.
Другой вариант - настроить ваш WebClient вручную и не зависеть от хранилища доверенных сертификатов по умолчанию вообще. Вы можете создать свое собственное хранилище доверенных сертификатов, что даст вам максимальную гибкость.
Пример:
@Bean
public WebClient createWebClient() throws SSLException {
SslContext sslContext = SslContextBuilder
.forClient()
.trustManager( /* TODO */ )
.build();
ClientHttpConnector httpConnector = HttpClient.create().secure(t -> t.sslContext(sslContext) )
return WebClient.builder().clientConnector(httpConnector).build();
}
В приведенном выше коде есть маркер TODO, куда вам нужно добавить своего доверительного менеджера. В этом сообщении SO есть несколько хороших мыслей о том, как это сделать, но в целом то, что вы создаете и откуда загружаете сертификаты, довольно гибкое.
Результатом этого метода является то, что он полностью настраивается . Вы можете получить свои сертификаты откуда угодно, из переменных среды, VCAP_SERVICES
или даже из Spring Cloud Config. Они просто понадобятся вам при инициализации WebClient
. Обратная сторона, вероятно, очевидна, нужно писать больше кода.
Вероятно, есть и другие варианты, но, надеюсь, это заставит вас задуматься о том, что возможно. Вышеупомянутая информация также только затрагивает тему доверенных магазинов. Если вам нужно предоставить хранилище ключей с закрытыми ключами, некоторые из вышеперечисленных параметров будут работать с небольшими отличиями.
Вам также нужно быть осторожнее с ключами, потому что они представляют собой очень конфиденциальную информацию. ИМХО, стоило бы дополнительных усилий, чтобы убедиться, что они не хранятся в JAR / WAR и хранятся в безопасности, как в CredHub или Spring Cloud Config Server.