Importar certificado na JVM

Quando um certificado é self-sign, ou seja, foi assinado por uma CA próprio, a jvm não irá “confiar” nesse certificado. Com isso ocorre o erro abaixo:

Caused by: feign.RetryableException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed executing GET https://<dominio>/

Para solucionar esse problema, uma das opções é importar o certificado na keystore da jvm.

Importando o certificado

Via ansible

Se possuir o ansible instalado, com apenas a execução abaixo é possível importar o certificado:

$ ansible <host> -mjava_cert -a"executable=/usr/lib/jvm/jdk8/bin/keytool cert_url=<dominio> keystore_path=/usr/lib/jvm/jdk8/jre/lib/security/cacerts keystore_pass=changeit" --become

Manual

  1. Extraia o certificado com o comando abaixo.
$ echo | openssl s_client -connect <dominio>:443
  1. Copie e cole todo o conteúdo entre —–BEGIN CERTIFICATE—– e —–END CERTIFICATE—– inclusive, em um arquivo.
  2. Importe o certificado com o comando abaixo.
$ keytool -import -alias person.services.intranet -keystore /usr/java/jre6/lib/security/cacerts -file <arquivo> -storepass changeit

Testando a importação do certificado

A forma mais fácil de testar se um certificado foi importado com sucesso é atráves dessa aplicação java:

  1. Copie e cole o código abaixo em um arquivo SSLPoke.java:
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;

/** Establish a SSL connection to a host and port, writes a byte and
 * prints the response. See
 * http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services
 */
public class SSLPoke {
    public static void main(String[] args) {
        if (args.length != 2) {
            System.out.println("Usage: "+SSLPoke.class.getName()+" <host> <port>");
            System.exit(1);
        }
        try {
            SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
            SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1]));

            InputStream in = sslsocket.getInputStream();
            OutputStream out = sslsocket.getOutputStream();

            // Write a test byte to get a reaction :)
            out.write(1);

            while (in.available() > 0) {
                System.out.print(in.read());
            }
            System.out.println("Successfully connected");

        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}
  1. Compile o código com o comando:
$ javac SSLPoke.java
  1. Execute o comando abaixo, se o resultado for Successfully connected, então o certificado foi importado com sucesso:
$ java SSLPoke <dominio> <port>