Я хотел бы использовать JNLP для соединения рабов Дженкинса с мастером Дженкинса. Мастер работает за прокси SSL nginx, настроенным в соответствии с официальной документацией. Помимо этой документации, я сталкиваюсь с проблемами, связанными с сертификатами.

В настоящее время я могу заставить безглавое соединение JNLP-master-master работать только с небезопасным HTTP-соединением, но не с HTTPS (хотя моя панель управления jenkins работает вообще). Я использую самоподписанный сертификат, подписанный моим собственным сертификатом CA (на основе openssl x509).

Итак, как мне указать двоичному файлу Java моего ведомого доверять моему сертификату SSL CA? Я попробовал это.

# add CA certificate to key store
$ keytool -import -file /usr/local/share/ca-certificates/my_ca.crt -alias my_ca -storepass mypassword

# try to reference keystore to JNLP headless call
$ java -Djavax.net.ssl.keyStorePassword=mypassword -Djavax.net.ssl.keyStore=/home/myuser/.keystore -jar slave.jar -jnlpUrl https://proxied-jenkins.example.com/computer/testslave/slave-agent.jnlp

На самом деле JAVA, похоже, не ищет сертификат в предоставленном хранилище ключей. В чем моя ошибка здесь?

РЕДАКТИРОВАТЬ

Подобная / та же проблема возникает при использовании Jenkins Cli. В соответствии с этим, теперь я предполагаю, что это не имеет никакого отношения к доверию моего сертификата, так как я не вижу javax.net.ssl.SSLHandshakeException

Я просто получаю сброс соединения

Failing to obtain https://proxied-jenkins.example.com/computer/testslave/slave-agent.jnlp
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:196)
    at java.net.SocketInputStream.read(SocketInputStream.java:122)
    at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
    at sun.security.ssl.InputRecord.read(InputRecord.java:480)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
    at hudson.remoting.Launcher.parseJnlpArguments(Launcher.java:269)
    at hudson.remoting.Launcher.run(Launcher.java:219)
    at hudson.remoting.Launcher.main(Launcher.java:192)

.. поэтому я предполагаю проблему с настройкой моего прокси. Я взял конфигурацию из конфигурации обратного прокси и добавил следующую конфигурацию для принудительного использования SSL:

upstream jenkins-upstream {
  server unproxied-jenkins.example.com:8080 fail_timeout=0;
}

server {
  listen 80;
  server_name proxied-jenkins.example.com;
  return 301 https://$host$request_uri;
}
server {
  listen 443;
  server_name proxied-jenkins.example.com;

  #this is the jenkins web root directory (mentioned in the /etc/default/jenkins file)
  root            /var/run/jenkins/war/;

  ssl on;
  ssl_certificate /etc/nginx/conf.d/proxied-jenkins.example.com.crt;
  ssl_certificate_key /etc/nginx/conf.d/proxied-jenkins.example.com.key;
  ssl_protocols TLSv1.2;
  ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;

  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  [...] # continuing according to jenkins documentation
  location @jenkins {
      proxy_pass                  http://jenkins-upstream
      [....]
  }
  [....]
}

Опять же, при переходе на небезопасный HTTP, JNLP и jenkins-cli работают как положено. Так в чем же ошибка?
Может быть, мне нужно передать дополнительную информацию заголовка? Может быть мне нужна дополнительная конфигурация SSL в настройках моего прокси?

2 ответа2

2

(Расширен на основе отзывов на комментарии)

Этот сервер настроен так, чтобы требовать версию протокола TLSv1.2 (только) и наборы шифров, использующие по крайней мере один из AES-GCM или 256-битный AES, с обменом ключами либо DHE, либо ECDHE (для которых OpenSSL и, следовательно, nginx используют варианты написания EDH и EECDH в некоторых случаях, включая этот).

JSSE-клиент в Oracle или OpenJDK JDK7 не предлагает TLSv1.2 или 1.1 по умолчанию (не знаю для IBM, у которой есть свои собственные поставщики шифрования), но они реализованы и могут быть включены ; для (Https)URLConnection это можно сделать с помощью системного свойства https.protocols . (Или путем наложения его фабрики сокетов, но системное свойство обычно проще.) Но JDK7 не реализует GCM, и версии Oracle (но НЕ OpenJDK) запрещают 256-битное симметричное шифрование, если вы не установили «Файлы политики неограниченной юрисдикции JCE» с веб-сайта Oracle; см. https://stackoverflow.com/a/33712287/2868801 и, возможно, https://stackoverflow.com/questions/30350120/sslhandshakeexception- while- connecting- to- a- https-site

Напротив, JDK8 (Oracle и OpenJDK) по умолчанию предлагает TLSv1.2 и 1.1 и реализует GCM, поэтому он может подключаться без политики Unlimited Strength.

И 7, и 8 поддерживают обмен ключами DHE и ECDHE. Но для всех, кто находится в аналогичной ситуации с JDK6: ECDHE не будет работать, если вы не добавите стороннего провайдера для примитивов ECC, такого как bcprov с http://www.BouncyCastle.org

1

Для пользователей Google, которые переходят на эту страницу на основе названия, а не содержания этого вопроса, и хотят, чтобы подчиненные JNLP подключались к обратному прокси-серверу Jenkins, работающему на отдельном сервере, а не на обратном прокси-сервере, см. Мой ответ to Jenkins: Как настроить Jenkins для обратного прокси-сервера Nginx для подключения подчиненных JNLP.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .