Jenkins usando JNLP atrás do proxy reverso nginx SSL

0

Eu gostaria de usar o JNLP para conectar os escravos Jenkins ao mestre Jenkins. O mestre está executando um proxy SSL nginx configurado de acordo com a documentação oficial . Além desta documentação, encontro problemas relacionados a certificados.

Atualmente, posso fazer com que o escravo sem cabeça JNLP domine a conexão para funcionar apenas com conexão HTTP não segura, mas não com HTTPS (embora meu painel de controle jenkins funcione em geral). Uso um certificado autoassinado assinado por meu próprio certificado CA personalizado (x509 com base em openssl).

Então, como digo ao binário java do meu escravo que confie no meu certificado CA SSL? Eu tentei isso.

# 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

Na verdade, o JAVA parece não procurar o certificado no keystore fornecido. Qual é o meu erro aqui?

EDITAR

Problema semelhante / mesmo ocorre ao usar o jenkins cli. De acordo com isso , agora suponho que não tenha nada a ver com a confiança no meu certificado, pois não consigo ver umjavax.net.ssl.SSLHandshakeException

Acabei de receber uma redefinição de conexão

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)

.. então eu assumo um problema de configuração com o meu proxy. Peguei a configuração da configuração do proxy reverso e adicionei a seguinte configuração para forçar o 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
      [....]
  }
  [....]
}

Novamente, ao mudar para HTTP não seguro, o JNLP e o jenkins-cli funcionam conforme o esperado. Então qual é o erro?
Talvez eu precise passar informações adicionais do cabeçalho? Talvez eu precise de uma configuração SSL adicional nas minhas configurações de proxy?

ITL
fonte
Você precisa do seu CAcert no SSL truststore do processo do cliente, e não o armazenamento de chaves SSL. Nem todas as SSLHandshakeException são causadas por problemas de certificação, mas você não está obtendo a que está, portanto provavelmente está falhando antes do ponto de validação da certificação. (1) Qual versão do java (6/7/8, Oracle / OpenJDK / IBM /?) ​​Você está usando para o cliente? (2) Você pode (2A) obter uma captura de rede com o Wireshark tcpdump ou similar, filtrada o mais próximo possível e mostrar ou vincular a isso; ou (2B) execute com sysprop javax.net.debug=ssl, capture a saída (grande!) e adicione isso?
David_thompson_085
@ dave_thompson_085 o javax.net.debug=sslfez o truque. Eu pude descobrir que o binário java (oracle jdk 7) tentou fazer o handshake TLSv1 com cifras 'fracas' ... Depois de instalar o Java Cryptography Extension (JCE), tive um suporte cifrado mais forte e consegui dizer ao java binário para fazer TLSv1.2. usando -Dhttps.protocols=TLSv1.2. No entanto, após a atualização para o Oracle JDK 8, ele funciona imediatamente. Então, obrigado pelo seu apoio e me direcionando para a direção certa ... Talvez você formule isso como resposta e eu vou excluí-lo e votá-lo.
ITL

Respostas:

2

(Expandido com base no feedback dos comentários)

Esse servidor está configurado para exigir a versão do protocolo TLSv1.2 (somente) e ciphersuites usando pelo menos um AES-GCM ou AES de 256 bits, com troca de chave DHE ou ECDHE (para a qual o OpenSSL e o nginx usam grafias variantes EDH e EECDH em alguns casos, incluindo este).

O cliente JSSE no Oracle ou OpenJDK JDK7 não oferece TLSv1.2 ou 1.1 por padrão (não conhecido pela IBM, que possui seus próprios provedores de criptografia), mas eles são implementados e podem ser ativados ; para (Https)URLConnectionisso pode ser feito com a propriedade do sistema https.protocols. (Ou sobrepondo sua fábrica de soquetes, mas a propriedade do sistema geralmente é mais fácil.) Mas o JDK7 não implementa o GCM, e as versões do Oracle (mas NÃO as do OpenJDK) proíbem a criptografia simétrica de 256 bits, a menos que você instale os " Arquivos de política de jurisdição JCE Unlimited Strength Jurisdiction "do site da Oracle; consulte https://stackoverflow.com/a/33712287/2868801 e possivelmentehttps://stackoverflow.com/questions/30350120/sslhandshakeexception- while-connecting-to-a-https-site

Por outro lado, o JDK8 (Oracle e OpenJDK) oferece TLSv1.2 e 1.1 por padrão e implementa o GCM, para que ele possa se conectar sem a política Força Ilimitada.

Tanto o 7 quanto o 8 oferecem suporte à troca de chaves DHE e ECDHE. Mas para qualquer outra pessoa em uma situação semelhante ao JDK6: ECDHE não funciona, a menos que você adicione um provedor de terceiros para primitivas de ECC, como bcprovem http://www.BouncyCastle.org

dave_thompson_085
fonte