TechnologyNovember 6, 2013

Accessing secure DSE clusters with CQL native protocol

Accessing secure DSE clusters with CQL native protocol

Apache Cassandra provides a number of features designed to help you secure your data. For deployments where Cassandra's internal authentication mechanism is not sufficient, DataStax Enterprise adds support for enterprise-grade authentication using Kerberos.

The DataStax Java driver for the CQL native protocol can be used with both DSE and Apache C* to access your data in a secure manner. If you're running a secure DSE cluster using Kerberos authentication and/or SSL for client to node encryption, you might find these examples useful.

 

DataStax Enterprise with Kerberos Authentication

In order to support Kerberos authentication, it was necessary to backport the authentication mechanism from version 2 of the CQL native protocol (CASSANDRA-5545) into the C* 1.2 which ships with DSE. For this reason, we also publish a DSE-specific version of the DataStax java driver for use with secure DSE clusters. This DSE extension to the driver is open source and available from the same Github repository as the mainstream version, where you can find it in the dse_3.1 branch. It's a drop in replacement for the mainstream driver, so to include it in your maven project just use these maven coordinates:

    <dependency>
      <groupId>com.datastax.cassandra</groupId>
      <artifactId>cassandra-driver-core</artifactId>
      <version>1.0.4-dse</version>
    </dependency>

(Incidentally, we employ a similar approach when it comes to the C# driver. I won't cover the details here, but to use the C# driver with Kerberos and DSE, check out this branch).

This DSE version of the java driver includes some additional authentication classes, amongst which is com.datastax.driver.core.sasl.DseAuthProvider that handles the negotiation of secure connections with DSE using GSSAPI & SASL.

When using DseAuthProvider, Kerberos options are set using a standard JAAS Login configuration file. The location of the file can be set using the standard Java mechanisms; by setting the java.security.auth.login.config system property or by adding a login.config.url.n entry in the java.security properties file.

Below are a couple of examples of JAAS config files which demonstrate the most commonly used means of providing Kerberos credentials. Both contain an entry named DseClient, which is the reference that DseAuthProvider uses to retrieve the login configuration (and so this shouldn't be changed). Both examples also specify the JVM standard Krb5LoginModule be used, for obvious reasons.

Obtaining User Credentials From a Keytab

To authenticate using a credentials from a keytab file, specify its location on disk. If your keytab contains more than one principal key, you should also specify which one to select.

    DseClient {
        com.sun.security.auth.module.Krb5LoginModule required
          useKeyTab=true
          keyTab="/path/to/file.keytab"
          principal="user@MYDOMAIN.COM";
    };

Obtaining Credentials From a Local Ticket Cache

To authenticate using credentials obtained from the local per-user Kerberos ticket cache, you just need a few changes to the config. You must run kinit to obtain a ticket and populate the cache before connecting.

    DseClient {
        com.sun.security.auth.module.Krb5LoginModule required
          useTicketCache=true
          renewTGT=true;
    };

A full list of the options supported by Krb5LoginModule can be found in its javadoc. You can read more about the details of what may be specified by the login file here and more on JAAS in general here.

Having provided a JAAS configuration, connecting to a secure DSE cluster is as simple as creating a DseAuthProvider instance.

    Cluster cluster = Cluster.builder()
                             .addContactPoints("192.168.10.10", "192.168.10.11")
                             .withAuthProvider(new DseAuthProvider())
                             .build();
    Session session = cluster.connect();

 

Client to Node Encryption with SSL

As well as the option to encrypt all internode communication, Apache Cassandra also supports client to server encryption using SSL. To open an encrypted connection with the java-driver, whether using Apache Cassandra or DSE, simply use the withSSL() method when constructing your Cluster instance

    Cluster cluster = Cluster.builder()
                             .addContactPoints("192.168.10.10", "192.168.10.11")
                             .withSSL()
                             .build();

By default this will instantiate connections using the system's default SSL context, which can be configured using system properties as documented here. The same end can also be achieved programatically, by constructing an SSLContext and handing that to the Cluster builder

    public static void main(String[] args)
    {
        .
        .
        .
        SSLContext context = getSSLContext(truststorePath, 
                                           truststorePassword, 
                                           keystorePath, 
                                           keystorePassword);

        // Default cipher suites supported by C*
        String[] cipherSuites = { "TLS_RSA_WITH_AES_128_CBC_SHA", 
                                  "TLS_RSA_WITH_AES_256_CBC_SHA" };

        Cluster cluster = Cluster.builder()
                                 .addContactPoints("192.168.10.10", "192.168.10.11")
                                 .withSSL(new SSLOptions(context, cipherSuites))
                                 .build();
        Session session = cluster.connect();
    }

    private static SSLContext getSSLContext(String truststorePath, 
                                            String truststorePassword,
                                            String keystorePath, 
                                            String keystorePassword)
    throws Exception 
    {
        FileInputStream tsf = new FileInputStream(truststorePath);
        FileInputStream ksf = new FileInputStream(keystorePath);
        SSLContext ctx = SSLContext.getInstance("SSL");

        KeyStore ts = KeyStore.getInstance("JKS");
        ts.load(tsf, truststorePassword.toCharArray());
        TrustManagerFactory tmf = 
                   TrustManagerFactory.getInstance(
                        TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ts);

        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(ksf, keystorePassword.toCharArray());
        KeyManagerFactory kmf = 
                   KeyManagerFactory.getInstance(
                        KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, keystorePassword.toCharArray());

        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
        return ctx;
    }

That just about covers using the DataStax CQL driver for accessing secured clusters in Java. DSE also supports Kerberos authentication in its Solr HTTP API, using SPNEGO. Next time, I'll cover some examples using those APIs from the command line with cURL and from Java with SolrJ.

Share

One-stop Data API for Production GenAI

Astra DB gives JavaScript developers a complete data API and out-of-the-box integrations that make it easier to build production RAG apps with high relevancy and low latency.