Jenkins używa JNLP za zwrotnym proxy nginx SSL

0

Chciałbym użyć JNLP do połączenia niewolników Jenkins z mistrzem Jenkins. Master działa za proxy nginx SSL skonfigurowanym zgodnie z oficjalną dokumentacją . Poza tą dokumentacją napotykam problemy związane z certyfikatami.

Obecnie mogę sprawić, by bezgłowe połączenie JNLP master do master działało tylko z niezabezpieczonym połączeniem HTTP, ale nie z HTTPS (chociaż ogólnie mój pulpit jenkins działa). Używam samopodpisanego certyfikatu podpisanego przez mój własny niestandardowy certyfikat CA (x509 oparty na openssl).

Jak więc powiedzieć binarnemu java mojego slave'a, aby zaufał mojemu certyfikatowi SSL CA? Próbowałem tego.

# 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

W rzeczywistości JAVA wydaje się nie szukać certyfikatu w dostarczonym magazynie kluczy. Jaki jest mój błąd tutaj?

EDYTOWAĆ

Podobny / ten sam problem występuje przy korzystaniu z jenkins cli. Zgodnie z tym , teraz zakładam, że nie ma to nic wspólnego z zaufaniem do mojego certyfikatu, ponieważ nie widzęjavax.net.ssl.SSLHandshakeException

Właśnie otrzymałem reset połączenia

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)

.. więc zakładam problem z konfiguracją mojego serwera proxy. Wziąłem konfigurację z konfiguracji odwrotnego proxy i dodałem następującą konfigurację, aby wymusić 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
      [....]
  }
  [....]
}

Ponownie przy przejściu na niezabezpieczony HTTP, JNLP i jenkins-cli działają zgodnie z oczekiwaniami. Więc jaki jest błąd?
Może muszę przekazać dodatkowe informacje w nagłówku? Może potrzebuję dodatkowej konfiguracji SSL w ustawieniach proxy?

ITL
źródło
Potrzebujesz swojego CAcert w magazynie zaufanych certyfikatów SSL procesu klienta, a nie w magazynie kluczy SSL. Nie wszystkie wyjątki SSLHandshakeException są spowodowane problemami z certyfikatem, ale nie otrzymujesz takiego, więc prawdopodobnie nie zdajesz egzaminu przed zatwierdzeniem certyfikatu. (1) Jakiej wersji java (6/7/8, Oracle / OpenJDK / IBM /?) ​​Używasz dla klienta? (2) Czy możesz (2A) uzyskać przechwytywanie sieci za pomocą programu Wireshark tcpdump lub podobnego, przefiltrować tak dokładnie, jak to możliwe i pokazać lub połączyć z tym; lub (2B) uruchom z sysprop javax.net.debug=ssl, przechwyć wyjście (duże!) i dodaj to?
dave_thompson_085,
@ dave_thompson_085 załatwił sprawę javax.net.debug=ssl. Byłem w stanie dowiedzieć się, że binarny java (oracle jdk 7) próbował wykonać uścisk dłoni TLSv1 z „słabymi” szyframi ... Po zainstalowaniu Java Cryptography Extension (JCE) miałem silniejszą obsługę szyfrów i mogłem powiedzieć java binarny do zrobienia TLSv1.2. za pomocą -Dhttps.protocols=TLSv1.2. Jednak po aktualizacji do Oracle JDK 8 działa on od razu po rozpakowaniu. Więc dziękuję za wsparcie i wskazanie mi właściwego kierunku ... Może sformułujesz to jako odpowiedź, a ja z wyjątkiem i poprę go.
ITL,

Odpowiedzi:

2

(Rozszerzony na podstawie opinii na temat komentarzy)

Serwer ten jest skonfigurowany tak, aby wymagał protokołu w wersji TLSv1.2 (tylko), i szyfruje przy użyciu co najmniej jednego z AES-GCM lub 256-bitowego AES, z wymianą kluczy DHE lub ECDHE (dla których OpenSSL, a zatem nginx używa wariantów pisowni EDH i EECDH w niektórych przypadkach, w tym ten).

Klient JSSE w Oracle lub OpenJDK JDK7 domyślnie nie oferuje TLSv1.2 lub 1.1 (nie wiem dla IBM, który ma własnych dostawców kryptografii), ale są one zaimplementowane i można je włączyć ; do (Https)URLConnectiontego można to zrobić za pomocą właściwości systemowej https.protocols. (Lub poprzez nałożenie fabryki gniazd, ale właściwość systemowa jest zwykle łatwiejsza.) Ale JDK7 nie implementuje GCM, a wersje Oracle (ale NIE te OpenJDK) zabraniają 256-bitowego szyfrowania symetrycznego, chyba że zainstalujesz „ Pliki zasad JCE Unlimited Strength Jurysdykcji „ze strony internetowej Oracle; patrz https://stackoverflow.com/a/33712287/2868801 i ewentualniehttps://stackoverflow.com/questions/30350120/sslhandshakeexception-while-connecting-to-a-https-site

W przeciwieństwie do JDK8 (Oracle i OpenJDK) domyślnie oferuje TLSv1.2 i 1.1 oraz implementuje GCM, dzięki czemu może łączyć się bez polityki nieograniczonej siły.

Zarówno 7, jak i 8 obsługują wymianę kluczy DHE i ECDHE. Ale dla każdego innego w podobnej sytuacji z JDK6: ECDHE nie działa, chyba że dodasz zewnętrznego dostawcę prymitywów ECC, np. bcprovZ http://www.BouncyCastle.org

dave_thompson_085
źródło