Blog
clouderaimpalajdbctlsldapkeytool

Applying TLS + LDAP Authentication to Cloudera Impala JDBC

Escape PKIX errors for good. Extract the certificate chain, create a dedicated TrustStore, and build the Impala JDBC URL — all with plain JDBC.

Data DynamicsApril 11, 20268 min read

It's a common scenario in the field: Cloudera Impala connects fine over plaintext in the dev environment, but in production it fails with PKIX path building failed. This post walks through the entire process of applying TLS + LDAP authentication to connect to Impala using only the Cloudera Impala JDBC Connector (Simba-based commercial driver) and plain JDBC DriverManager — no frameworks involved.

TL;DR

  1. Request the root CA certificate PEM file (ca.pem) from your cluster administrator.
  2. Use keytool to create a new application-specific TrustStore (JKS) and import the CA.
  3. Add SSL=1;SSLTrustStore=...;AuthMech=3 to the JDBC URL, and separate UID/PWD/SSLTrustStorePwd into Properties.
  4. Call Class.forName("com.cloudera.impala.jdbc.Driver") then DriverManager.getConnection().
  5. Run SELECT 1 — if it succeeds, you're done.

1. Prerequisites

Make sure you have everything below before starting. If anything is missing, request it from your cluster administrator.

#ItemExample
1Cloudera Impala JDBC Connector JARImpalaJDBC42.jar + any dependency JARs provided with it
2TLS-enabled Impala daemon endpointimpalad-lb.corp.example.com:21050
3Cluster's root CA certificate (PEM)ca.pem
4LDAP credentialsUID / PWD. Confirm the format with your administrator
5JDK 8 or laterjava -version

You only need the root CA — the full chain is not necessary.

2. Import the TLS Certificate into a TrustStore

2.1 Why use an application-specific TrustStore

You could add it directly to the JDK's cacerts, but this is not recommended for the following reasons:

  • It can affect all other applications using the same JDK
  • Upgrading the JDK replaces cacerts, causing your import to disappear
  • You'd need to rebuild the container image every time

The alternative is to create a dedicated TrustStore file (JKS) that ships with your application. It's unaffected by JDK upgrades, provides a clear security boundary, and for Docker images it's just one line: COPY truststore.jks /app/.

2.2 Obtaining the certificate

Method 1 — Get the PEM file from the administrator (recommended)

First, verify that the received file is correct:

openssl x509 -in ca.pem -noout -subject -issuer -dates

If Subject: and Issuer: are identical, it's the root CA.

Method 2 — Extract directly from the server using openssl s_client

openssl s_client -connect impalad-lb.corp.example.com:21050 \
  -showcerts </dev/null 2>/dev/null \
  | awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/' \
  > impala-chain.pem

To find the root CA in the chain, compare the subject/issuer of each certificate:

csplit -z -s -f cert- -b '%02d.pem' impala-chain.pem \
  '/-----BEGIN CERTIFICATE-----/' '{*}'
 
for f in cert-*.pem; do
  echo "=== $f ==="
  openssl x509 -in "$f" -noout -subject -issuer
done

The file where Subject: and Issuer: are identical is the root CA.

2.3 Create the TrustStore with keytool

This is the key step of this post.

keytool -importcert -noprompt \
  -file ca.pem \
  -alias cloudera-root-ca \
  -keystore ./truststore.jks \
  -storepass 'CHANGE_ME_STRONG_PASSPHRASE' \
  -storetype JKS

Here's what each option does:

OptionDescription
-importcertAdd an X.509 certificate to the keystore
-nopromptSkip prompts. Required for scripting
-fileThe certificate file to import
-aliasInternal identifier within the keystore. Re-importing with the same alias overwrites
-keystoreTrustStore file path. Creates a new file if it doesn't exist
-storepassKeystore password. Recommended to inject via environment variables
-storetype JKSExplicitly specify the format. JDK 9+ defaults to PKCS12, so it's safer to be explicit

2.4 Verify the TrustStore

Confirm that the CA was properly imported into the TrustStore:

keytool -list -v \
  -keystore ./truststore.jks \
  -storepass 'CHANGE_ME_STRONG_PASSPHRASE' \
  -alias cloudera-root-ca

Points to verify in the output:

  • Owner: matches the DN of the received root CA
  • Valid from ... until: expiration date
  • Cross-check the SHA-256 fingerprint with the value provided by the administrator (the last line of defense against MITM)

2.5 Common pitfalls

Review these before deployment:

  • Did you import only the root CA?
  • Does the -alias conflict with an existing one?
  • Is the TrustStore path accessible at runtime? Watch out for relative paths
  • Do you have certificate expiration monitoring in place?
  • Is the -storepass hardcoded in source code?

3. Composing the Impala JDBC URL

3.1 URL template

jdbc:impala://impalad-lb.corp.example.com:21050;AuthMech=3;SSL=1;SSLTrustStore=/app/truststore.jks

3.2 Parameter descriptions

ParameterValueDescription
AuthMech3User Name And Password. This means LDAP bind authentication
SSL1Enable TLS. Must be uppercase SSL=1. Lowercase ssl=true is Apache Hive JDBC syntax and is not recognized by the Cloudera driver
SSLTrustStore/app/truststore.jksAbsolute path to the TrustStore created earlier

3.3 Never put sensitive information in the URL

Do not put UID/PWD and SSLTrustStorePwd in the URL. JDBC URLs commonly appear in logs, thread dumps, and error stack traces. Separate them using java.util.Properties:

Properties props = new Properties();
props.setProperty("UID", System.getenv("IMPALA_LDAP_UID"));
props.setProperty("PWD", System.getenv("IMPALA_LDAP_PWD"));
props.setProperty("SSLTrustStorePwd", System.getenv("IMPALA_TRUSTSTORE_PWD"));

The Cloudera driver treats URL parameters and Properties identically.

4. Connecting with plain JDBC

Here's a minimal reproducible example without any framework. You can put it in a main method and run it directly.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
 
public class ImpalaJdbcSmokeTest {
 
  private static final String DRIVER_CLASS =
      "com.cloudera.impala.jdbc.Driver";
 
  // No secrets included.
  private static final String JDBC_URL =
      "jdbc:impala://impalad-lb.corp.example.com:21050"
          + ";AuthMech=3"
          + ";SSL=1"
          + ";SSLTrustStore=/app/truststore.jks";
 
  public static void main(String[] args) throws Exception {
    Class.forName(DRIVER_CLASS);
 
    Properties props = new Properties();
    props.setProperty("UID", requireEnv("IMPALA_LDAP_UID"));
    props.setProperty("PWD", requireEnv("IMPALA_LDAP_PWD"));
    props.setProperty("SSLTrustStorePwd", requireEnv("IMPALA_TRUSTSTORE_PWD"));
 
    try (Connection conn = DriverManager.getConnection(JDBC_URL, props);
         PreparedStatement ps = conn.prepareStatement("SELECT 1 AS ok");
         ResultSet rs = ps.executeQuery()) {
      if (rs.next()) {
        System.out.println("connected, result = " + rs.getInt("ok"));
      }
    }
  }
 
  private static String requireEnv(String name) {
    String v = System.getenv(name);
    if (v == null || v.isEmpty()) {
      throw new IllegalStateException("Environment variable " + name + " is empty.");
    }
    return v;
  }
}

Running:

export IMPALA_LDAP_UID='alice'
export IMPALA_LDAP_PWD='...'
export IMPALA_TRUSTSTORE_PWD='CHANGE_ME_STRONG_PASSPHRASE'
 
java -cp 'ImpalaJDBC42.jar:libs/*:.' ImpalaJdbcSmokeTest

If connected, result = 1 appears, the entire TLS + LDAP path is working.

Debugging

If the connection fails, enabling SSL handshake logging in the JVM almost always reveals the cause:

java -Djavax.net.debug=ssl:handshake \
     -cp 'ImpalaJDBC42.jar:libs/*:.' \
     ImpalaJdbcSmokeTest

Check the output at the ServerHello, Certificate, and ServerHelloDone stages to see if the chain sent by the server links to your TrustStore. Be sure to disable this in production — the log volume is significant.

5. Common Errors and Solutions

PKIX path building failed

Cause: Java cannot link the server certificate to a trust chain. Most commonly, the root CA is missing from the TrustStore or the file path is wrong.

  • Verify the alias actually exists with keytool -list
  • Check that the SSLTrustStore path in the JDBC URL is correct relative to the execution context
  • If both JVM options (-Djavax.net.ssl.trustStore=...) and URL parameters exist, the URL takes precedence

Unrecognized SSL message, plaintext connection?

Cause: The client is speaking TLS but the server is responding in plaintext. The port number is wrong, or you're using SSL=1 on a non-TLS port.

  • Re-confirm the TLS-enabled Impala daemon port with the administrator
  • If using HTTP transport, check whether TransportMode=http;HttpPath=... is additionally required

No subject alternative names matching IP address

Cause: The server certificate's SAN does not include the connection hostname. This usually happens when the internal LB FQDN is missing from the certificate.

  • Ask the administrator to reissue the certificate with the LB FQDN added to the SAN (the proper approach)
  • AllowHostNameCNMismatch=1 can work around this, but it disables MITM protection — never use in production

Invalid operation: LDAP authentication failed

Cause: TLS passed and the UID/PWD reached the server, but LDAP bind failed.

  • Verify the UID format. Confirm with the administrator whether it's sAMAccountName (alice), DOMAIN\alice, or DN (uid=alice,...)
  • If the password contains semicolons, quotes, or spaces, you must use the Properties approach (do not put it in the URL)
  • Check with the AD administrator whether the account is locked

Could not open client transport

Cause: Failure at the TCP/SASL level. Often a network issue.

  • Test TCP connectivity with telnet impalad-lb.corp.example.com 21050
  • Check if the port is allowed through corporate proxy/firewall
  • The cluster may actually be enforcing Kerberos while you're connecting with AuthMech=3. Re-confirm the actual required authentication method with the administrator

6. Production Checklist

This list helps prevent scenarios where things work on a dev PC but break days after production deployment.

  • Is the TrustStore file included in the deployment artifact (JAR/WAR/Docker image) and deployed together?
  • Is the storepass injected via environment variable or secret store?
  • Is the JDBC URL free of secrets even when it appears in logs, using Properties for sensitive values?
  • Is there certificate expiration monitoring in place? (openssl x509 -in ca.pem -noout -enddate)
  • Is the Cloudera Impala JDBC Connector version pinned?
  • Does CI run a SELECT 1 smoke test against a real Impala endpoint?
  • Is there a failure-count-based alarm for connection failures? (to distinguish from transient network jitter)

If you've followed along this far, you can now connect to Cloudera Impala with TLS + LDAP locally, and you have the diagnostic tools to identify which layer failed when something goes wrong.

— Data Dynamics Engineering Team