Add back support for 3rd party auth providers to bulk loader patch by Mike Adamson; reviewed by yukim for CASSANDRA-10873
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/fa18880e Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/fa18880e Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/fa18880e Branch: refs/heads/trunk Commit: fa18880e73f7f3bdbb1075c0baa54a7df3e667d0 Parents: 2e09583 Author: Mike Adamson <madam...@datastax.com> Authored: Wed Dec 16 10:37:47 2015 +0000 Committer: Yuki Morishita <yu...@apache.org> Committed: Fri Dec 18 17:09:28 2015 -0600 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../org/apache/cassandra/tools/BulkLoader.java | 79 ++++++++++++++++++-- .../utils/NativeSSTableLoaderClient.java | 16 ++-- 3 files changed, 84 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/fa18880e/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index e6ab5dd..199e374 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.3 + * Add back support for 3rd party auth providers to bulk loader (CASSANDRA-10873) * Eliminate the dependency on jgrapht for UDT resolution (CASSANDRA-10653) * (Hadoop) Close Clusters and Sessions in Hadoop Input/Output classes (CASSANDRA-1837) * Fix sstableloader not working with upper case keyspace name (CASSANDRA-10806) http://git-wip-us.apache.org/repos/asf/cassandra/blob/fa18880e/src/java/org/apache/cassandra/tools/BulkLoader.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/tools/BulkLoader.java b/src/java/org/apache/cassandra/tools/BulkLoader.java index 73194a1..2b94a68 100644 --- a/src/java/org/apache/cassandra/tools/BulkLoader.java +++ b/src/java/org/apache/cassandra/tools/BulkLoader.java @@ -19,6 +19,8 @@ package org.apache.cassandra.tools; import java.io.File; import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.UnknownHostException; @@ -28,6 +30,8 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import org.apache.commons.cli.*; +import com.datastax.driver.core.AuthProvider; +import com.datastax.driver.core.PlainTextAuthProvider; import com.datastax.driver.core.SSLOptions; import javax.net.ssl.SSLContext; import org.apache.cassandra.config.*; @@ -50,6 +54,7 @@ public class BulkLoader private static final String NATIVE_PORT_OPTION = "port"; private static final String USER_OPTION = "username"; private static final String PASSWD_OPTION = "password"; + private static final String AUTH_PROVIDER_OPTION = "auth-provider"; private static final String THROTTLE_MBITS = "throttle"; /* client encryption options */ @@ -67,15 +72,14 @@ public class BulkLoader public static void main(String args[]) { Config.setClientMode(true); - LoaderOptions options = LoaderOptions.parseArgs(args); + LoaderOptions options = LoaderOptions.parseArgs(args).validateArguments(); OutputHandler handler = new OutputHandler.SystemOutput(options.verbose, options.debug); SSTableLoader loader = new SSTableLoader( options.directory, new ExternalClient( options.hosts, options.nativePort, - options.user, - options.passwd, + options.authProvider, options.storagePort, options.sslStoragePort, options.serverEncOptions, @@ -277,14 +281,13 @@ public class BulkLoader public ExternalClient(Set<InetAddress> hosts, int port, - String user, - String passwd, + AuthProvider authProvider, int storagePort, int sslStoragePort, EncryptionOptions.ServerEncryptionOptions serverEncryptionOptions, SSLOptions sslOptions) { - super(hosts, port, user, passwd, sslOptions); + super(hosts, port, authProvider, sslOptions); this.storagePort = storagePort; this.sslStoragePort = sslStoragePort; this.serverEncOptions = serverEncryptionOptions; @@ -307,6 +310,8 @@ public class BulkLoader public int nativePort = 9042; public String user; public String passwd; + public String authProviderName; + public AuthProvider authProvider; public int throttle = 0; public int storagePort; public int sslStoragePort; @@ -374,6 +379,9 @@ public class BulkLoader if (cmd.hasOption(PASSWD_OPTION)) opts.passwd = cmd.getOptionValue(PASSWD_OPTION); + if (cmd.hasOption(AUTH_PROVIDER_OPTION)) + opts.authProviderName = cmd.getOptionValue(AUTH_PROVIDER_OPTION); + if (cmd.hasOption(INITIAL_HOST_ADDRESS_OPTION)) { String[] nodes = cmd.getOptionValue(INITIAL_HOST_ADDRESS_OPTION).split(","); @@ -494,6 +502,64 @@ public class BulkLoader } } + public LoaderOptions validateArguments() + { + // Both username and password need to be provided + if ((user != null) != (passwd != null)) + errorMsg("Username and password must both be provided", getCmdLineOptions()); + + if (user != null) + { + // Support for 3rd party auth providers that support plain text credentials. + // In this case the auth provider must provide a constructor of the form: + // + // public MyAuthProvider(String username, String password) + if (authProviderName != null) + { + try + { + Class authProviderClass = Class.forName(authProviderName); + Constructor constructor = authProviderClass.getConstructor(String.class, String.class); + authProvider = (AuthProvider)constructor.newInstance(user, passwd); + } + catch (ClassNotFoundException e) + { + errorMsg("Unknown auth provider: " + e.getMessage(), getCmdLineOptions()); + } + catch (NoSuchMethodException e) + { + errorMsg("Auth provider does not support plain text credentials: " + e.getMessage(), getCmdLineOptions()); + } + catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) + { + errorMsg("Could not create auth provider with plain text credentials: " + e.getMessage(), getCmdLineOptions()); + } + } + else + { + // If a 3rd party auth provider wasn't provided use the driver plain text provider + authProvider = new PlainTextAuthProvider(user, passwd); + } + } + // Alternate support for 3rd party auth providers that don't use plain text credentials. + // In this case the auth provider must provide a nullary constructor of the form: + // + // public MyAuthProvider() + else if (authProviderName != null) + { + try + { + authProvider = (AuthProvider)Class.forName(authProviderName).newInstance(); + } + catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) + { + errorMsg("Unknown auth provider" + e.getMessage(), getCmdLineOptions()); + } + } + + return this; + } + private static void errorMsg(String msg, CmdLineOptions options) { System.err.println(msg); @@ -513,6 +579,7 @@ public class BulkLoader options.addOption("t", THROTTLE_MBITS, "throttle", "throttle speed in Mbits (default unlimited)"); options.addOption("u", USER_OPTION, "username", "username for cassandra authentication"); options.addOption("pw", PASSWD_OPTION, "password", "password for cassandra authentication"); + options.addOption("ap", AUTH_PROVIDER_OPTION, "auth provider", "custom AuthProvider class name for cassandra authentication"); options.addOption("cph", CONNECTIONS_PER_HOST, "connectionsPerHost", "number of concurrent connections-per-host."); // ssl connection-related options options.addOption("ts", SSL_TRUSTSTORE, "TRUSTSTORE", "Client SSL: full path to truststore"); http://git-wip-us.apache.org/repos/asf/cassandra/blob/fa18880e/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java b/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java index bb927fc..225e453 100644 --- a/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java +++ b/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java @@ -40,18 +40,22 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client protected final Map<String, CFMetaData> tables; private final Collection<InetAddress> hosts; private final int port; - private final String username; - private final String password; + private final AuthProvider authProvider; private final SSLOptions sslOptions; + public NativeSSTableLoaderClient(Collection<InetAddress> hosts, int port, String username, String password, SSLOptions sslOptions) { + this(hosts, port, new PlainTextAuthProvider(username, password), sslOptions); + } + + public NativeSSTableLoaderClient(Collection<InetAddress> hosts, int port, AuthProvider authProvider, SSLOptions sslOptions) + { super(); this.tables = new HashMap<>(); this.hosts = hosts; this.port = port; - this.username = username; - this.password = password; + this.authProvider = authProvider; this.sslOptions = sslOptions; } @@ -60,8 +64,8 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client Cluster.Builder builder = Cluster.builder().addContactPoints(hosts).withPort(port); if (sslOptions != null) builder.withSSL(sslOptions); - if (username != null && password != null) - builder = builder.withCredentials(username, password); + if (authProvider != null) + builder = builder.withAuthProvider(authProvider); try (Cluster cluster = builder.build(); Session session = cluster.connect()) {