0
votes

I am using elasticsearch 7.1.0. I want to connect to a secure elasicsearch cluster. When I am trying to write data with the the RestHighLevelClient I always get the exception no matter what.

I am running on Ubuntu 18.04.2 LTS and intellJ is using /usr/lib/jvm/java-11-openjdk-amd64 and I am using spring boot First I am creating an keystore and than I am adding the private key and the certificate chain. Than I am assigining the keystore to the Truststore. When the @Bean HighRestLevelClient gets created I am adding the sslContext to the Rest client like shown here:

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/_encrypted_communication.html

Please See the code.

@Bean

    public void initKeyStore() {
        try {
            log.info("start creating keystore");
            KeyStore keyStore = KeyStore.getInstance("JKS");
            char[] pwdArray = "pwd".toCharArray();
            keyStore.load(null, pwdArray);
            FileOutputStream fos = new FileOutputStream("absolutPathToKeystore/elasticKeyStore");
            keyStore.store(fos, pwdArray);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            Certificate certCA = cf.generateCertificate(new FileInputStream("es-certs/ca.crt"));
            Certificate esNodeCert = cf.generateCertificate(new FileInputStream("es-node.crt"));
            X509Certificate[] certificates = new X509Certificate[2];
            certificates[0] = (X509Certificate)esNodeCert;
            certificates[1] = (X509Certificate)certCA;
            byte[] keyBytes = Files.readAllBytes(Paths.get("es-node-pkcs8.der"));;
            PKCS8EncodedKeySpec pubSpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = kf.generatePrivate(pubSpec);
            keyStore.setKeyEntry("secure-elastic-connection", privateKey, pwdArray, certificates);
            System.setProperty("javax.net.ssl.trustStore", "absolutPathToKeystore/elasticKeyStore");
        } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | InvalidKeySpecException e) {
            log.error("something went wrong creating keystore");
            log.error(e.getMessage());
        }
        log.info("finished creating keystore");
    }

@Bean(destroyMethod = "close")
@DependsOn("initKeyStore")
public RestHighLevelClient client() {

        RestHighLevelClient client = null;
        try {
            log.info("start setting up elastic search connection");
            final CredentialsProvider credentialsProvider =
                    new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY,
                    new UsernamePasswordCredentials("elasticuser", "pwd"));
            KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());
            truststore.load(new FileInputStream("absolutPathTo/elasticKeyStore"), "pwd".toCharArray());
            SSLContextBuilder sslBuilder = SSLContexts.custom()
                    .loadTrustMaterial(truststore, null);
            final SSLContext sslContext = sslBuilder.build();
            client = new RestHighLevelClient(
                    RestClient.builder(new HttpHost(esHost, esPort, "https"))
                            .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                                @Override
                                public HttpAsyncClientBuilder customizeHttpClient(
                                        HttpAsyncClientBuilder httpClientBuilder) {
                                    return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider).setSSLContext(sslContext);
                                }
                            }));
        } catch (KeyStoreException | IOException | CertificateException e) {
            log.info("something went wrong loading keystore for elasticsearch");
            log.error(e.getMessage());
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            log.info("something went wrong loading sslcontext for elasticsearch");
            log.error(e.getMessage());
        }
        log.info("finished setting up elasic search connection");
        return client;
    }

java.io.IOException: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    at org.elasticsearch.client.RestClient$SyncResponseListener.get(RestClient.java:948)
    at org.elasticsearch.client.RestClient.performRequest(RestClient.java:227)
    at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1433)
    at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1403)
    at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:1373)
    at org.elasticsearch.client.RestHighLevelClient.index(RestHighLevelClient.java:821)
    at com.x24factory.monitoring.service.ElasticsearchServiceImpl.sendOverviewPOJOToElastic(ElasticsearchServiceImpl.java:43)
    at com.x24factory.monitoring.service.MonitoringCreatorServiceImpl.sendOverviewToElasticsearch(MonitoringCreatorServiceImpl.java:77)
    at com.x24factory.monitoring.service.MonitoringCreatorServiceImpl.createMonitoring(MonitoringCreatorServiceImpl.java:38)
    at com.x24factory.monitoring.MonitoringApplication.run(MonitoringApplication.java:56)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:813)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:797)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
    at com.x24factory.monitoring.MonitoringApplication.main(MonitoringApplication.java:33)
Caused by: javax.net.ssl.SSLException: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    at org.apache.http.nio.reactor.ssl.SSLIOSession.convert(SSLIOSession.java:258)
    at org.apache.http.nio.reactor.ssl.SSLIOSession.doWrap(SSLIOSession.java:265)
    at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:301)
    at org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:509)
    at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:120)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    at java.base/java.security.cert.PKIXParameters.setTrustAnchors(PKIXParameters.java:200)
    at java.base/java.security.cert.PKIXParameters.<init>(PKIXParameters.java:120)
    at java.base/java.security.cert.PKIXBuilderParameters.<init>(PKIXBuilderParameters.java:104)
    at java.base/sun.security.validator.PKIXValidator.<init>(PKIXValidator.java:86)
    at java.base/sun.security.validator.Validator.getInstance(Validator.java:181)
    at java.base/sun.security.ssl.X509TrustManagerImpl.getValidator(X509TrustManagerImpl.java:308)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrustedInit(X509TrustManagerImpl.java:176)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:249)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:141)
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:620)
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:461)
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:361)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:448)
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1065)
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1052)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:999)
    at org.apache.http.nio.reactor.ssl.SSLIOSession.doRunTask(SSLIOSession.java:281)
    at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:339)
    ... 9 more
1
Don't you also need absolute file paths for your FileInputStreams to generate certificates from?Val
not according to this example baeldung.com/java-keystorepodoi17
Nobody has some help?podoi17

1 Answers

0
votes

I'm facing the same error on Elastic client for v6.8.2, although the client is created using ApacheHTTPClient and is working well on one environment but not on other.

On digging up a bit, seems like OCP 4.x has some changes on route behaviors when it comes to Passthrough. On 3.6, the certificate is still required for Passthrough, but for 4.x, it just don't look for certificate at all. When changed the route to use Re-encrypt TLS termination policy, I started getting the above error (Edge being out of option since ES is SSL enabled).

Tried debugging the client code and SSL handshake was going fine, cert being picked up, validated by server and vice versa for server cert, but then abruptly closed connection.