Как добавить хранилище доверенных сертификатов и хранилище ключей в приложение Springboot в PCF (Pivotal Cloud Foun dry) - PullRequest
0 голосов
/ 19 июня 2020

Есть ли способ добавить хранилище доверенных сертификатов и хранилище ключей в PCF:

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

Но как перенести хранилище ключей и трасторе в PCF.

Вариант 1, с которым я столкнулся, заключается в том, чтобы хранить хранилище ключей и доверенных сертификатов внутри / в ресурсе приложения spring -boot и указывать путь в manifest.yml: JAVA_OPTS arguments. Но что, если у нас есть 5 разных сред, имеющих 5 разных наборов хранилищ доверенных сертификатов и хранилищ ключей?

По этой причине нам необходимо экстернализовать. Подскажите, пожалуйста, есть ли способ сделать это в PCF.

Заранее спасибо!

1 Ответ

2 голосов
/ 22 июня 2020

Как вы упомянули, есть несколько способов сделать это, и это зависит от ваших конкретных c потребностей, какой из них будет работать лучше всего. Я постараюсь обрисовать как можно больше вариантов, а также плюсы и минусы каждого.

  1. Если вам нужно всего лишь распространить доверенные сертификаты, добавьте Bo sh Доверенные сертификаты и разрешение Bo sh распространять их на все виртуальные машины и контейнеры в CF - хороший способ go. В Ops Manager под плиткой Bo sh введите go в Security, и вы можете добавить любое количество доверенных сертификатов.

    Это хороший подход, когда несколько приложений должны доверять сертификатам, например, с корпоративный / частный центр сертификации. Он также хорошо работает с разными средами / основаниями, потому что у вас есть другой Ops Manager, который может поддерживать другой список доверенных сертификатов. Это может быть сложно управлять, если у вас есть много сертификатов, которым необходимо доверять, и / или если сертификаты используются только одним или небольшим количеством приложений. Для этого также требуются административные привилегии для CF и может потребоваться некоторое время для развертывания обновлений на всей основе.

  2. Это вариант, о котором вы упомянули в своем вопросе. Импортируйте сертификат в файл хранилища доверенных сертификатов 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, но он может варьироваться от версии к версии, поэтому вы должны поддерживать его в актуальном состоянии.

  3. Это небольшое изменение от # 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 также присутствует в этой опции.

  4. Следующая опция - это итерация # 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, с которым сложно работать, и о нем можно забыть.

  5. Вариант # 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 со всеми его автоматическими конфигурациями (не то чтобы это плохо, просто вы должны быть очень осторожны с порядком). Я считаю, что это проще сделать в скрипте профиля, который гарантированно запускается до запуска вашего приложения.

  6. Другой вариант - настроить ваш 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. Обратная сторона, вероятно, очевидна, нужно писать больше кода.

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

  1. Не будет работать.
  2. Будет работать, но имеет другой Аргумент JVM: javax.net.ssl.keyStore. 3 и 4. Может работать, но вместо добавления к хранилищу ключей по умолчанию вы должны создать новое в сценарии и также установить javax.net.ssl.keyStore. Это больше работы и не намного полезнее, чем # 2.
  3. Он будет работать с теми же оговорками, но имеет другой аргумент JVM: javax.net.ssl.keyStore.
  4. Он будет работать, вы просто необходимо его закодировать.

Вам также нужно быть осторожнее с ключами, потому что они представляют собой очень конфиденциальную информацию. ИМХО, стоило бы дополнительных усилий, чтобы убедиться, что они не хранятся в JAR / WAR и хранятся в безопасности, как в CredHub или Spring Cloud Config Server.

...