Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'issue-296-kerberos'

Conflicts:
	core/src/main/java/me/prettyprint/cassandra/connection/CassandraHostRetryService.java
  • Loading branch information...
commit 08149a03c81b559cba5680d115943dbf334f58fa 2 parents 14bf13a + 4d91e44
@patricioe patricioe authored
Showing with 762 additions and 85 deletions.
  1. +9 −2 core/src/main/java/me/prettyprint/cassandra/connection/CassandraHostRetryService.java
  2. +23 −20 core/src/main/java/me/prettyprint/cassandra/connection/ConcurrentHClientPool.java
  3. +3 −2 core/src/main/java/me/prettyprint/cassandra/connection/DynamicLoadBalancingPolicy.java
  4. +3 −2 core/src/main/java/me/prettyprint/cassandra/connection/HClientPool.java
  5. +18 −9 core/src/main/java/me/prettyprint/cassandra/connection/HConnectionManager.java
  6. +8 −5 core/src/main/java/me/prettyprint/cassandra/connection/LatencyAwareHClientPool.java
  7. +3 −2 core/src/main/java/me/prettyprint/cassandra/connection/LeastActiveBalancingPolicy.java
  8. +22 −2 core/src/main/java/me/prettyprint/cassandra/connection/LoadBalancingPolicy.java
  9. +5 −6 core/src/main/java/me/prettyprint/cassandra/connection/RoundRobinBalancingPolicy.java
  10. +92 −0 core/src/main/java/me/prettyprint/cassandra/connection/client/HClient.java
  11. +95 −0 core/src/main/java/me/prettyprint/cassandra/connection/client/HKerberosThriftClient.java
  12. +40 −19 core/src/main/java/me/prettyprint/cassandra/connection/{ → client}/HThriftClient.java
  13. +25 −0 core/src/main/java/me/prettyprint/cassandra/connection/factory/HClientFactory.java
  14. +26 −0 core/src/main/java/me/prettyprint/cassandra/connection/factory/HClientFactoryProvider.java
  15. +140 −0 core/src/main/java/me/prettyprint/cassandra/connection/factory/HKerberosSecuredThriftClientFactoryImpl.java
  16. +31 −0 core/src/main/java/me/prettyprint/cassandra/connection/factory/HThriftClientFactoryImpl.java
  17. +152 −0 core/src/main/java/me/prettyprint/cassandra/connection/security/KerberosHelper.java
  18. +16 −1 core/src/main/java/me/prettyprint/cassandra/service/CassandraHostConfigurator.java
  19. +6 −2 core/src/test/java/me/prettyprint/cassandra/connection/ConcurrentHClientPoolTest.java
  20. +9 −12 core/src/test/java/me/prettyprint/cassandra/connection/HConnectionManagerTest.java
  21. +1 −0  core/src/test/java/me/prettyprint/cassandra/connection/HThriftClientTest.java
  22. +4 −1 core/src/test/java/me/prettyprint/cassandra/connection/LatencyAwareHClientPoolTest.java
  23. +17 −0 core/src/test/resources/kerberos/jaas.conf
  24. +14 −0 core/src/test/resources/kerberos/krb5.conf
View
11 core/src/main/java/me/prettyprint/cassandra/connection/CassandraHostRetryService.java
@@ -8,6 +8,8 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import me.prettyprint.cassandra.connection.client.HClient;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
import me.prettyprint.cassandra.service.CassandraHost;
import me.prettyprint.cassandra.service.CassandraHostConfigurator;
import me.prettyprint.cassandra.service.ThriftCluster;
@@ -26,11 +28,16 @@
public static final int DEF_QUEUE_SIZE = -1;
public static final int DEF_RETRY_DELAY = 10;
+
+ private final HClientFactory clientFactory;
private final LinkedBlockingQueue<CassandraHost> downedHostQueue;
- public CassandraHostRetryService(HConnectionManager connectionManager,
+ public CassandraHostRetryService(HConnectionManager connectionManager, HClientFactory clientFactory,
CassandraHostConfigurator cassandraHostConfigurator) {
+
super(connectionManager, cassandraHostConfigurator);
+ this.clientFactory = clientFactory;
+
this.retryDelayInSeconds = cassandraHostConfigurator.getRetryDownedHostsDelayInSeconds();
downedHostQueue = new LinkedBlockingQueue<CassandraHost>(cassandraHostConfigurator.getRetryDownedHostsQueueSize() < 1
? Integer.MAX_VALUE : cassandraHostConfigurator.getRetryDownedHostsQueueSize());
@@ -170,7 +177,7 @@ private boolean verifyConnection(CassandraHost cassandraHost) {
return false;
}
boolean found = false;
- HThriftClient client = new HThriftClient(cassandraHost);
+ HClient client = clientFactory.createClient(cassandraHost);
try {
client.open();
found = client.getCassandra().describe_cluster_name() != null;
View
43 core/src/main/java/me/prettyprint/cassandra/connection/ConcurrentHClientPool.java
@@ -7,11 +7,14 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import me.prettyprint.cassandra.connection.client.HClient;
+import me.prettyprint.cassandra.connection.client.HThriftClient;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
import me.prettyprint.cassandra.service.CassandraHost;
import me.prettyprint.hector.api.exceptions.HInactivePoolException;
+import me.prettyprint.hector.api.exceptions.HPoolExhaustedException;
import me.prettyprint.hector.api.exceptions.HectorException;
import me.prettyprint.hector.api.exceptions.HectorTransportException;
-import me.prettyprint.hector.api.exceptions.HPoolExhaustedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -20,7 +23,7 @@
private static final Logger log = LoggerFactory.getLogger(ConcurrentHClientPool.class);
- private final ArrayBlockingQueue<HThriftClient> availableClientQueue;
+ private final ArrayBlockingQueue<HClient> availableClientQueue;
private final AtomicInteger activeClientsCount;
private final AtomicInteger realActiveClientsCount;
@@ -32,10 +35,13 @@
private final long maxWaitTimeWhenExhausted;
- public ConcurrentHClientPool(CassandraHost host) {
+ private final HClientFactory clientFactory;
+
+ public ConcurrentHClientPool(HClientFactory clientFactory, CassandraHost host) {
+ this.clientFactory = clientFactory;
this.cassandraHost = host;
- availableClientQueue = new ArrayBlockingQueue<HThriftClient>(cassandraHost.getMaxActive(), true);
+ availableClientQueue = new ArrayBlockingQueue<HClient>(cassandraHost.getMaxActive(), true);
// This counter can be offset by as much as the number of threads.
activeClientsCount = new AtomicInteger(0);
realActiveClientsCount = new AtomicInteger(0);
@@ -45,7 +51,7 @@ public ConcurrentHClientPool(CassandraHost host) {
maxWaitTimeWhenExhausted = cassandraHost.getMaxWaitTimeWhenExhausted() < 0 ? 0 : cassandraHost.getMaxWaitTimeWhenExhausted();
for (int i = 0; i < cassandraHost.getMaxActive() / 3; i++) {
- availableClientQueue.add(new HThriftClient(cassandraHost).open());
+ availableClientQueue.add(createClient());
}
if ( log.isDebugEnabled() ) {
@@ -58,12 +64,12 @@ public ConcurrentHClientPool(CassandraHost host) {
@Override
- public HThriftClient borrowClient() throws HectorException {
+ public HClient borrowClient() throws HectorException {
if ( !active.get() ) {
throw new HInactivePoolException("Attempt to borrow on in-active pool: " + getName());
}
- HThriftClient cassandraClient = availableClientQueue.poll();
+ HClient cassandraClient = availableClientQueue.poll();
int currentActiveClients = activeClientsCount.incrementAndGet();
try {
@@ -92,8 +98,8 @@ public HThriftClient borrowClient() throws HectorException {
}
- private HThriftClient waitForConnection() {
- HThriftClient cassandraClient = null;
+ private HClient waitForConnection() {
+ HClient cassandraClient = null;
numBlocked.incrementAndGet();
// blocked take on the queue if we are configured to wait forever
@@ -138,16 +144,13 @@ private HThriftClient waitForConnection() {
* having to wait on polling logic. (But still increment all the counters)
* @return
*/
- private HThriftClient createClient() {
- if ( log.isDebugEnabled() ) {
- log.debug("Creation of new client");
- }
- return new HThriftClient(cassandraHost).open();
+ private HClient createClient() {
+ return clientFactory.createClient(cassandraHost).open();
}
/**
* Controlled shutdown of pool. Go through the list of available clients
- * in the queue and call {@link HThriftClient#close()} on each. Toggles
+ * in the queue and call {@link HClient#close()} on each. Toggles
* a flag to indicate we are going into shutdown mode. Any subsequent calls
* will throw an IllegalArgumentException.
*
@@ -159,11 +162,11 @@ public void shutdown() {
throw new IllegalArgumentException("shutdown() called for inactive pool: " + getName());
}
log.info("Shutdown triggered on {}", getName());
- Set<HThriftClient> clients = new HashSet<HThriftClient>();
+ Set<HClient> clients = new HashSet<HClient>();
availableClientQueue.drainTo(clients);
if ( clients.size() > 0 ) {
- for (HThriftClient hThriftClient : clients) {
- hThriftClient.close();
+ for (HClient hClient : clients) {
+ hClient.close();
}
}
log.info("Shutdown complete on {}", getName());
@@ -225,7 +228,7 @@ public String getStatusAsString() {
}
@Override
-public void releaseClient(HThriftClient client) throws HectorException {
+public void releaseClient(HClient client) throws HectorException {
boolean open = client.isOpen();
if ( open ) {
if ( active.get() ) {
@@ -257,7 +260,7 @@ public void releaseClient(HThriftClient client) throws HectorException {
* are releasing at the same time).
* @param client
*/
- private void addClientToPoolGently(HThriftClient client) {
+ private void addClientToPoolGently(HClient client) {
try {
availableClientQueue.add(client);
} catch (IllegalStateException ise) {
View
5 core/src/main/java/me/prettyprint/cassandra/connection/DynamicLoadBalancingPolicy.java
@@ -12,6 +12,7 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
import me.prettyprint.cassandra.service.CassandraHost;
import me.prettyprint.cassandra.utils.DaemonThreadPoolFactory;
@@ -118,8 +119,8 @@ public int compare(HClientPool p1, HClientPool p2) {
}
@Override
- public HClientPool createConnection(CassandraHost host) {
- LatencyAwareHClientPool pool = new LatencyAwareHClientPool(host);
+ public HClientPool createConnection(HClientFactory clientFactory, CassandraHost host) {
+ LatencyAwareHClientPool pool = new LatencyAwareHClientPool(clientFactory, host);
add(pool);
return pool;
}
View
5 core/src/main/java/me/prettyprint/cassandra/connection/HClientPool.java
@@ -1,15 +1,16 @@
package me.prettyprint.cassandra.connection;
+import me.prettyprint.cassandra.connection.client.HClient;
import me.prettyprint.cassandra.service.CassandraHost;
import me.prettyprint.hector.api.exceptions.HectorException;
public interface HClientPool extends PoolMetric {
- public HThriftClient borrowClient() throws HectorException;
+ public HClient borrowClient() throws HectorException;
public CassandraHost getCassandraHost();
public int getNumBeforeExhausted();
public boolean isExhausted();
public int getMaxActive();
public String getStatusAsString();
- public void releaseClient(HThriftClient client) throws HectorException;
+ public void releaseClient(HClient client) throws HectorException;
void shutdown();
}
View
27 core/src/main/java/me/prettyprint/cassandra/connection/HConnectionManager.java
@@ -9,6 +9,11 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import me.prettyprint.cassandra.connection.client.HClient;
+import me.prettyprint.cassandra.connection.client.HThriftClient;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
+import me.prettyprint.cassandra.connection.factory.HClientFactoryProvider;
+import me.prettyprint.cassandra.connection.factory.HThriftClientFactoryImpl;
import me.prettyprint.cassandra.service.CassandraClientMonitor;
import me.prettyprint.cassandra.service.CassandraClientMonitor.Counter;
import me.prettyprint.cassandra.service.CassandraHost;
@@ -44,6 +49,7 @@
private NodeAutoDiscoverService nodeAutoDiscoverService;
private final LoadBalancingPolicy loadBalancingPolicy;
private final CassandraHostConfigurator cassandraHostConfigurator;
+ private final HClientFactory clientFactory;
private HostTimeoutTracker hostTimeoutTracker;
private final ClockResolution clock;
@@ -52,17 +58,20 @@
private HOpTimer timer;
public HConnectionManager(String clusterName, CassandraHostConfigurator cassandraHostConfigurator) {
+
+ clientFactory = HClientFactoryProvider.createFactory(cassandraHostConfigurator);
+
loadBalancingPolicy = cassandraHostConfigurator.getLoadBalancingPolicy();
clock = cassandraHostConfigurator.getClockResolution();
hostPools = new ConcurrentHashMap<CassandraHost, HClientPool>();
suspendedHostPools = new ConcurrentHashMap<CassandraHost, HClientPool>();
this.clusterName = clusterName;
if ( cassandraHostConfigurator.getRetryDownedHosts() ) {
- cassandraHostRetryService = new CassandraHostRetryService(this, cassandraHostConfigurator);
+ cassandraHostRetryService = new CassandraHostRetryService(this, clientFactory, cassandraHostConfigurator);
}
for ( CassandraHost host : cassandraHostConfigurator.buildCassandraHosts()) {
try {
- HClientPool hcp = loadBalancingPolicy.createConnection(host);
+ HClientPool hcp = loadBalancingPolicy.createConnection(clientFactory, host);
hostPools.put(host,hcp);
} catch (HectorTransportException hte) {
log.error("Could not start connection pool for host {}", host);
@@ -101,7 +110,7 @@ public boolean addCassandraHost(CassandraHost cassandraHost) {
HClientPool pool = null;
try {
cassandraHostConfigurator.applyConfig(cassandraHost);
- pool = cassandraHostConfigurator.getLoadBalancingPolicy().createConnection(cassandraHost);
+ pool = cassandraHostConfigurator.getLoadBalancingPolicy().createConnection(clientFactory, cassandraHost);
hostPools.putIfAbsent(cassandraHost, pool);
log.info("Added host {} to pool", cassandraHost.getName());
return true;
@@ -213,7 +222,7 @@ public boolean unsuspendCassandraHost(CassandraHost cassandraHost) {
public void operateWithFailover(Operation<?> op) throws HectorException {
final Object timerToken = timer.start();
int retries = Math.min(op.failoverPolicy.numRetries, hostPools.size());
- HThriftClient client = null;
+ HClient client = null;
HClientPool pool = null;
boolean success = false;
boolean retryable = false;
@@ -293,7 +302,7 @@ public void operateWithFailover(Operation<?> op) throws HectorException {
}
}
- private void closeClient(HThriftClient client) {
+ private void closeClient(HClient client) {
if ( client != null ) {
client.close();
}
@@ -345,11 +354,11 @@ private HClientPool getClientFromLBPolicy(Set<CassandraHost> excludeHosts) {
return loadBalancingPolicy.getPool(hostPoolValues, excludeHosts);
}
- void releaseClient(HThriftClient client) {
+ void releaseClient(HClient client) {
if ( client == null ) return;
- HClientPool pool = hostPools.get(client.cassandraHost);
+ HClientPool pool = hostPools.get(client.getCassandraHost());
if ( pool == null ) {
- pool = suspendedHostPools.get(client.cassandraHost);
+ pool = suspendedHostPools.get(client.getCassandraHost());
}
if ( pool != null ) {
pool.releaseClient(client);
@@ -359,7 +368,7 @@ void releaseClient(HThriftClient client) {
}
}
- HThriftClient borrowClient() {
+ HClient borrowClient() {
HClientPool pool = getClientFromLBPolicy(null);
if ( pool != null ) {
return pool.borrowClient();
View
13 core/src/main/java/me/prettyprint/cassandra/connection/LatencyAwareHClientPool.java
@@ -3,6 +3,9 @@
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;
+import me.prettyprint.cassandra.connection.client.HClient;
+import me.prettyprint.cassandra.connection.client.HThriftClient;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
import me.prettyprint.cassandra.service.CassandraHost;
import me.prettyprint.hector.api.exceptions.HectorException;
@@ -20,20 +23,20 @@
private static final double SENTINEL_COMPARE = 0.768;
private final LinkedBlockingDeque<Double> latencies;
- public LatencyAwareHClientPool(CassandraHost host) {
- super(host);
+ public LatencyAwareHClientPool(HClientFactory clientFactory, CassandraHost host) {
+ super(clientFactory, host);
latencies = new LinkedBlockingDeque<Double>(WINDOW_QUEUE_SIZE);
}
@Override
- public HThriftClient borrowClient() throws HectorException {
- HThriftClient client = super.borrowClient();
+ public HClient borrowClient() throws HectorException {
+ HClient client = super.borrowClient();
client.startToUse();
return client;
}
@Override
- public void releaseClient(HThriftClient client) throws HectorException {
+ public void releaseClient(HClient client) throws HectorException {
add(client.getSinceLastUsed());
super.releaseClient(client);
}
View
5 core/src/main/java/me/prettyprint/cassandra/connection/LeastActiveBalancingPolicy.java
@@ -1,5 +1,6 @@
package me.prettyprint.cassandra.connection;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
import me.prettyprint.cassandra.service.CassandraHost;
import java.util.*;
@@ -55,7 +56,7 @@ public int compare(HClientPool o1, HClientPool o2) {
}
@Override
- public HClientPool createConnection(CassandraHost host) {
- return new ConcurrentHClientPool(host);
+ public HClientPool createConnection(HClientFactory clientFactory, CassandraHost host) {
+ return new ConcurrentHClientPool(clientFactory, host);
}
}
View
24 core/src/main/java/me/prettyprint/cassandra/connection/LoadBalancingPolicy.java
@@ -2,12 +2,32 @@
import java.io.Serializable;
import java.util.Collection;
-import java.util.List;
import java.util.Set;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
import me.prettyprint.cassandra.service.CassandraHost;
+/**
+ * Default interface for all load balancing policies.
+ *
+ */
public interface LoadBalancingPolicy extends Serializable {
+
+ /**
+ * Retrieves a pool from the collection of <code>pools</code> excluding <code>excludeHosts</code>.
+ *
+ * @param pools collection of all available pools
+ * @param excludeHosts excluded pools
+ * @return a pool based on this load balancing policy
+ */
HClientPool getPool(Collection<HClientPool> pools, Set<CassandraHost> excludeHosts);
- HClientPool createConnection(CassandraHost host);
+
+ /**
+ * Creates a connection pool for <code>host</code>.
+ *
+ * @param clientFactory an instance of {@link HClientFactory}
+ * @param host an instance of {@link CassandraHost} representing the host this pool will represent
+ * @return a connection pool
+ */
+ HClientPool createConnection(HClientFactory clientFactory, CassandraHost host);
}
View
11 core/src/main/java/me/prettyprint/cassandra/connection/RoundRobinBalancingPolicy.java
@@ -1,14 +1,13 @@
package me.prettyprint.cassandra.connection;
import java.util.Collection;
-import java.util.List;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import com.google.common.collect.Iterables;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
import me.prettyprint.cassandra.service.CassandraHost;
+import com.google.common.collect.Iterables;
+
/**
* Implements a RoundRobin balancing policy based off the contents
* of the active {@link HClientPool}. If a pool is shutdown by another
@@ -64,7 +63,7 @@ private int getAndIncrement(int size) {
}
@Override
- public HClientPool createConnection(CassandraHost host) {
- return new ConcurrentHClientPool(host);
+ public HClientPool createConnection(HClientFactory clientFactory, CassandraHost host) {
+ return new ConcurrentHClientPool(clientFactory, host);
}
}
View
92 core/src/main/java/me/prettyprint/cassandra/connection/client/HClient.java
@@ -0,0 +1,92 @@
+/**
+ *
+ */
+package me.prettyprint.cassandra.connection.client;
+
+
+import me.prettyprint.cassandra.service.CassandraHost;
+
+import org.apache.cassandra.thrift.Cassandra;
+
+/**
+ * Hector Client Interface.
+ *
+ * @author patricioe (Patricio Echague - patricio@datastax.com)
+ *
+ */
+public interface HClient {
+
+ /**
+ * Returns a new Cassandra.Client on each invocation using the underlying
+ * transport.
+ *
+ * @return Cassandra.Client from the underlying transport
+ * @throws IllegalStateException
+ * if it is called on a closed client
+ */
+ Cassandra.Client getCassandra();
+
+ /**
+ * Returns a new Cassandra.Client on each invocation using the underlying
+ * transport.
+ *
+ * @param keyspaceNameArg
+ * a keyspace
+ *
+ * @return Cassandra.Client from the underlying transport
+ * @throws IllegalStateException
+ * if it is called on a closed client
+ * @throws HInvalidRequestException
+ * if the keyspace does not exist or if it is malformed
+ * @throws HectorTransportException
+ * if any other error occurs
+ */
+ Cassandra.Client getCassandra(String keyspaceNameArg);
+
+ /**
+ * Close this client and its underlying connection.
+ *
+ * @return this object
+ */
+ HClient close();
+
+ /**
+ * Open a connection for this client.
+ *
+ * @return this object
+ * @throws IllegalStateException
+ * if this method is called from a client with an open connection
+ * @throws HectorTransportException
+ * if the connection cannot be established
+ */
+ HClient open();
+
+ /**
+ * Retrieves whether the underlying connection for this client is open or not.
+ *
+ * @return <code>TRUE</code> if the underlying connection for this client is
+ * open. <code>FALSE<code> otherwise
+ */
+ boolean isOpen();
+
+ /**
+ * Start tracking the beginning of use for this client. This is expected to be
+ * called per operation basis. Followed by a {@link HClient#getSinceLastUsed}
+ */
+ void startToUse();
+
+ /**
+ * Retrieves the time in milliseconds since this client was used last time.
+ *
+ * @return time in milliseconds since last used.
+ */
+ long getSinceLastUsed();
+
+ /**
+ * Retrieves the CassandraHost associate to this client.
+ *
+ * @return the @link {@link CassandraHost} object for this client
+ */
+ CassandraHost getCassandraHost();
+
+}
View
95 core/src/main/java/me/prettyprint/cassandra/connection/client/HKerberosThriftClient.java
@@ -0,0 +1,95 @@
+package me.prettyprint.cassandra.connection.client;
+
+import java.net.Socket;
+import java.net.SocketException;
+
+import javax.security.auth.Subject;
+
+import me.prettyprint.cassandra.connection.security.KerberosHelper;
+import me.prettyprint.cassandra.service.CassandraHost;
+import me.prettyprint.hector.api.exceptions.HectorTransportException;
+
+import org.apache.thrift.transport.TFramedTransport;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.TTransportException;
+import org.ietf.jgss.GSSContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Hector client that authenticate against kerberos.
+ *
+ * @author patricioe (Patricio Echague - patricioe@gmail.com)
+ */
+public class HKerberosThriftClient extends HThriftClient implements HClient {
+
+ private static Logger log = LoggerFactory.getLogger(HKerberosThriftClient.class);
+
+ private Subject kerberosTicket;
+ private String servicePrincipalName;
+
+ /**
+ * Constructor
+ * @param kerberosTicket
+ * @param cassandraHost
+ */
+ public HKerberosThriftClient(Subject kerberosTicket, CassandraHost cassandraHost, String servicePrincipalName) {
+ super(cassandraHost);
+ this.kerberosTicket = kerberosTicket;
+ this.servicePrincipalName = servicePrincipalName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public HKerberosThriftClient open() {
+ if ( isOpen() ) {
+ throw new IllegalStateException("Open called on already open connection. You should not have gotten here.");
+ }
+ if ( log.isDebugEnabled() ) {
+ log.debug("Creating a new thrift connection to {}", cassandraHost);
+ }
+
+ TSocket socket = new TSocket(cassandraHost.getHost(), cassandraHost.getPort(), timeout);
+ if ( cassandraHost.getUseSocketKeepalive() ) {
+ try {
+ socket.getSocket().setKeepAlive(true);
+ } catch (SocketException se) {
+ throw new HectorTransportException("Could not set SO_KEEPALIVE on socket: ", se);
+ }
+ }
+
+ // TODO (patricioe) What should I do with it ?
+ // KerberosHelper.getSourcePrinciple(clientContext));
+
+ if (cassandraHost.getUseThriftFramedTransport()) {
+ transport = new TFramedTransport(socket);
+ } else {
+ transport = socket;
+ }
+
+ try {
+ transport.open();
+ } catch (TTransportException e) {
+ // Thrift exceptions aren't very good in reporting, so we have to catch the exception here and
+ // add details to it.
+ log.debug("Unable to open transport to " + cassandraHost.getName());
+ //clientMonitor.incCounter(Counter.CONNECT_ERROR);
+ throw new HectorTransportException("Unable to open transport to " + cassandraHost.getName() +" , " +
+ e.getLocalizedMessage(), e);
+ }
+
+ // Kerberos authentication
+ Socket internalSocket = socket.getSocket();
+
+ final GSSContext clientContext = KerberosHelper.authenticateClient(internalSocket, kerberosTicket, servicePrincipalName);
+
+ if (clientContext == null) {
+ close();
+ throw new HectorTransportException("Kerberos context couldn't be established with client.");
+ }
+
+ return this;
+ }
+
+}
View
59 ...t/cassandra/connection/HThriftClient.java → ...ndra/connection/client/HThriftClient.java
@@ -1,6 +1,5 @@
-package me.prettyprint.cassandra.connection;
+package me.prettyprint.cassandra.connection.client;
-import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.atomic.AtomicLong;
@@ -22,31 +21,36 @@
import org.slf4j.LoggerFactory;
-public class HThriftClient {
+public class HThriftClient implements HClient {
private static Logger log = LoggerFactory.getLogger(HThriftClient.class);
+ private static final String NAME_FORMAT = "CassandraClient<%s-%d>";
+
private static final AtomicLong serial = new AtomicLong(0);
final CassandraHost cassandraHost;
private final long mySerial;
- private final int timeout;
- private String keyspaceName;
+ protected final int timeout;
+ protected String keyspaceName;
private long useageStartTime;
- private TTransport transport;
- private Cassandra.Client cassandraClient;
+ protected TTransport transport;
+ protected Cassandra.Client cassandraClient;
- HThriftClient(CassandraHost cassandraHost) {
+ /**
+ * Constructor
+ * @param cassandraHost
+ */
+ public HThriftClient(CassandraHost cassandraHost) {
this.cassandraHost = cassandraHost;
this.timeout = getTimeout(cassandraHost);
mySerial = serial.incrementAndGet();
}
/**
- * Returns a new Cassandra.Client on each invocation using the underlying transport
- *
+ * {@inheritDoc}
*/
public Cassandra.Client getCassandra() {
if ( !isOpen() ) {
@@ -58,13 +62,16 @@
return cassandraClient;
}
+ /**
+ * {@inheritDoc}
+ */
public Cassandra.Client getCassandra(String keyspaceNameArg) {
getCassandra();
if ( keyspaceNameArg != null && !StringUtils.equals(keyspaceName, keyspaceNameArg)) {
if ( log.isDebugEnabled() )
log.debug("keyspace reseting from {} to {}", keyspaceName, keyspaceNameArg);
try {
- cassandraClient.set_keyspace(keyspaceNameArg);
+ cassandraClient.set_keyspace(keyspaceNameArg);
} catch (InvalidRequestException ire) {
throw new HInvalidRequestException(ire);
} catch (TException e) {
@@ -75,7 +82,10 @@
return cassandraClient;
}
- HThriftClient close() {
+ /**
+ * {@inheritDoc}
+ */
+ public HThriftClient close() {
if ( log.isDebugEnabled() ) {
log.debug("Closing client {}", this);
}
@@ -95,8 +105,10 @@ HThriftClient close() {
return this;
}
-
- HThriftClient open() {
+ /**
+ * {@inheritDoc}
+ */
+ public HThriftClient open() {
if ( isOpen() ) {
throw new IllegalStateException("Open called on already open connection. You should not have gotten here.");
}
@@ -131,8 +143,10 @@ HThriftClient open() {
return this;
}
-
- boolean isOpen() {
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isOpen() {
boolean open = false;
if (transport != null) {
open = transport.isOpen();
@@ -168,12 +182,15 @@ private int getTimeout(CassandraHost cassandraHost) {
return timeoutVar;
}
+ /**
+ * {@inheritDoc}
+ */
public void startToUse() {
useageStartTime = System.currentTimeMillis();
}
/**
- * @return Time in MS since it was used.
+ * {@inheritDoc}
*/
public long getSinceLastUsed() {
return System.currentTimeMillis() - useageStartTime;
@@ -192,7 +209,11 @@ public boolean equals(Object obj) {
return this.toString().equals(obj.toString());
}
+ /**
+ * {@inheritDoc}
+ */
+ public CassandraHost getCassandraHost() {
+ return cassandraHost;
+ }
-
- private static final String NAME_FORMAT = "CassandraClient<%s-%d>";
}
View
25 core/src/main/java/me/prettyprint/cassandra/connection/factory/HClientFactory.java
@@ -0,0 +1,25 @@
+/**
+ *
+ */
+package me.prettyprint.cassandra.connection.factory;
+
+import me.prettyprint.cassandra.connection.client.HClient;
+import me.prettyprint.cassandra.service.CassandraHost;
+
+/**
+ * Basic interface for all implementations of this factory.
+ *
+ * @author patricioe (Patricio Echague - patricio@datastax.com)
+ *
+ */
+public interface HClientFactory {
+
+ /**
+ * Creates a Hector Client against the host represented by <code>ch</code>
+ *
+ * @param ch a {@link CassandraHost}
+ * @return a new HClient
+ */
+ HClient createClient(CassandraHost ch);
+
+}
View
26 core/src/main/java/me/prettyprint/cassandra/connection/factory/HClientFactoryProvider.java
@@ -0,0 +1,26 @@
+package me.prettyprint.cassandra.connection.factory;
+
+import me.prettyprint.cassandra.service.CassandraHostConfigurator;
+
+/**
+ * Provides different factory implementations based on {@link CassandraHostConfigurator} settings.
+ *
+ * @author patricioe (Patricio Echague - patricioe@gmail.com)
+ *
+ */
+public class HClientFactoryProvider {
+
+ /**
+ * Create a {@link HClientFactory} based on the setting in <code>chc</code>.
+ *
+ * @param chc a {@link CassandraHostConfigurator} instance
+ * @return an implementation of {@link HClientFactory}
+ */
+ public static HClientFactory createFactory(CassandraHostConfigurator chc) {
+ if (chc.isUseKerberosAuthentication())
+ return new HKerberosSecuredThriftClientFactoryImpl();
+ else
+ return new HThriftClientFactoryImpl();
+ }
+
+}
View
140 .../me/prettyprint/cassandra/connection/factory/HKerberosSecuredThriftClientFactoryImpl.java
@@ -0,0 +1,140 @@
+package me.prettyprint.cassandra.connection.factory;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
+import me.prettyprint.cassandra.connection.client.HClient;
+import me.prettyprint.cassandra.connection.client.HKerberosThriftClient;
+import me.prettyprint.cassandra.connection.security.KerberosHelper;
+import me.prettyprint.cassandra.service.CassandraHost;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Client Factory that provides Secure sockets using Kerberos as authentication
+ * mechanism.
+ *
+ * It expects few system properties to be set up:
+ * <ul>
+ * <li><code>java.security.auth.login.config</code>: location of the "jaas.conf"
+ * file. Default is <code>jaas.conf</code> at the root of the classpath.
+ * <li><code>java.security.krb5.conf</code>: location of the "krb5.conf"
+ * file. Default is <code>krb5.conf</code> at the root of the classpath.
+ * <li><code>sun.security.krb5.debug</code>. Set to <code>TRUE</code> for debug. Default is <code>FALSE</code>.
+ * <li><code>kerberos.client.reference.name</code> Kerberos client reference name specified in <code>jaas.conf</code>.
+ * Default: "Client".
+ * <li><code>kerberos.service.principal.name</code> Kerberos Service principal name without the domain. Default: "cassandra".
+ * <li><code>kerberos.client.principal.name</code> Username for when .keytab file is not specified.
+ * <li><code>kerberos.client.password</code> Password for then .keytab file is not specified.
+ * </ul>
+ * <p>
+ *
+ * If a <code>.keytab</code> is going to be used, please avoid setting <code>kerberos.client.username</code> and
+ * <code>kerberos.client.password</code>.
+ *
+ * {@link HKerberosThriftClient} completes the authentication that this factory started against Kerberos.
+ *
+ * Sample <code>jaas.conf</code> file:
+ * <p>
+ *
+ * <pre>
+ * Client {
+ * com.sun.security.auth.module.Krb5LoginModule required
+ * useKeyTab=true
+ * keyTab="./hector-kerberos.keytab"
+ * useTicketCache=true
+ * renewTGT=true
+ * storeKey=true
+ * principal="<user_name>@your_realm";
+ * };
+ *
+ * Server {
+ * com.sun.security.auth.module.Krb5LoginModule required
+ * useKeyTab=false
+ * storeKey=true
+ * useTicketCache=false
+ * principal="service_principal@your_realm";
+ * };
+ * </pre>
+ *
+ * <code>useKeyTab</code> and <code>keytab</code> can be omitted if <code>kerberos.client.principal.name</code>
+ * and <code>kerberos.client.password</code> are specified.
+ *
+ * @see HKerberosThriftClient
+ *
+ * @author patricioe (Patricio Echague - patricioe@gmail.com)
+ *
+ */
+public class HKerberosSecuredThriftClientFactoryImpl implements HClientFactory {
+
+ private static final Logger log = LoggerFactory.getLogger(HKerberosSecuredThriftClientFactoryImpl.class);
+
+ public static final String JAAS_CONFIG = "jaas.conf";
+ public static final String KRB5_CONFIG = "krb5.conf";
+
+ private final Subject kerberosTicket;
+ private String krbServicePrincipalName;
+
+ public HKerberosSecuredThriftClientFactoryImpl() {
+ String jaasConf = System.getProperty("java.security.auth.login.config");
+ String krb5Conf = System.getProperty("java.security.krb5.conf");
+ String krbDebug = System.getProperty("sun.security.krb5.debug");
+ String krbClientReferenceName = System.getProperty("kerberos.client.reference.name");
+ String krbClientUsername = System.getProperty("kerberos.client.principal.name");
+ String krbClientPassword = System.getProperty("kerberos.client.password");
+ krbServicePrincipalName = System.getProperty("kerberos.service.principal.name");
+
+ if (krbDebug == null)
+ System.setProperty("sun.security.krb5.debug", "false");
+
+ if (jaasConf == null)
+ System.setProperty("java.security.auth.login.config", JAAS_CONFIG);
+
+ if (krb5Conf == null)
+ System.setProperty("java.security.krb5.conf", KRB5_CONFIG);
+
+ if (krbClientReferenceName == null)
+ krbClientReferenceName = "Client";
+
+ if (krbServicePrincipalName == null)
+ krbServicePrincipalName = "cassandra";
+
+ System.setProperty("javax.security.auth.useSubjectCredsOnly", "true");
+
+ log.info("Kerberos V5 was enabled for client<->server communications.");
+ log.info("Properties:");
+ log.info(" sun.security.krb5.debug = {}", System.getProperty("sun.security.krb5.debug"));
+ log.info(" java.security.auth.login.config = {}", System.getProperty("java.security.auth.login.config"));
+ log.info(" java.security.krb5.conf = {}", System.getProperty("java.security.krb5.conf"));
+ log.info(" kerberos.client.reference.name = {}", System.getProperty("kerberos.client.reference.name", krbClientReferenceName));
+ log.info(" kerberos.service.principal.name = {}", System.getProperty("kerberos.service.principal.name", krbServicePrincipalName));
+ log.info(" kerberos.client.principal.name = {}", System.getProperty("kerberos.client.principal.name"));
+ log.info(" kerberos.client.password = {}", System.getProperty("kerberos.client.password"));
+ log.info(" javax.security.auth.useSubjectCredsOnly = true");
+
+ log.info("Trying to login to the KDC...");
+
+ try {
+ // Ticket Granting Ticket (TGT) from the Authentication Server (AS)
+ if (krbClientUsername != null && krbClientPassword != null)
+ kerberosTicket = KerberosHelper.loginService(krbClientReferenceName, krbClientUsername, krbClientPassword);
+ else
+ kerberosTicket = KerberosHelper.loginService(krbClientReferenceName);
+ } catch (LoginException e) {
+ throw new RuntimeException(e);
+ }
+ log.info("Kerberos authenticated successfully against KDC");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public HClient createClient(CassandraHost ch) {
+ if (log.isDebugEnabled()) {
+ log.debug("Creation of new client");
+ }
+ return new HKerberosThriftClient(kerberosTicket, ch, krbServicePrincipalName);
+ }
+
+}
View
31 core/src/main/java/me/prettyprint/cassandra/connection/factory/HThriftClientFactoryImpl.java
@@ -0,0 +1,31 @@
+/**
+ *
+ */
+package me.prettyprint.cassandra.connection.factory;
+
+import me.prettyprint.cassandra.connection.client.HClient;
+import me.prettyprint.cassandra.connection.client.HThriftClient;
+import me.prettyprint.cassandra.service.CassandraHost;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author patricioe (Patricio Echague - patricio@datastax.com)
+ *
+ */
+public class HThriftClientFactoryImpl implements HClientFactory {
+
+ private static final Logger log = LoggerFactory.getLogger(HThriftClientFactoryImpl.class);
+
+ /**
+ * {@inheritDoc}
+ */
+ public HClient createClient(CassandraHost ch) {
+ if ( log.isDebugEnabled() ) {
+ log.debug("Creation of new client for host: " + ch.getIp());
+ }
+ return new HThriftClient(ch);
+ }
+
+}
View
152 core/src/main/java/me/prettyprint/cassandra/connection/security/KerberosHelper.java
@@ -0,0 +1,152 @@
+package me.prettyprint.cassandra.connection.security;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class KerberosHelper {
+
+ private static Logger log = LoggerFactory.getLogger(KerberosHelper.class);
+
+ /**
+ * Log in using the service name for jaas.conf file and .keytab instead of specifying username and password
+ *
+ * @param serviceName service name defined in jass.conf file
+ * @return the authenticated Subject or <code>null</code> is the authentication failed
+ * @throws LoginException if there is any error during the login
+ */
+ public static Subject loginService(String serviceName) throws LoginException {
+ LoginContext loginCtx = new LoginContext(serviceName, new CallbackHandler() {
+ // as we use .keytab file there is no need to specify any options in callback
+ public void handle(Callback[] callbacks) throws IOException,
+ UnsupportedCallbackException {
+ }
+ });
+
+ loginCtx.login();
+ return loginCtx.getSubject();
+ }
+
+ /**
+ *
+ * @param serviceName service name defined in jass.conf file
+ * @param username username
+ * @param password password
+ * @return the authenticated Subject or <code>null</code> is the authentication failed
+ * @throws LoginException if there is any error during the login
+ */
+ public static Subject loginService(String serviceName, String username, String password) throws LoginException {
+ LoginContext loginCtx = new LoginContext(serviceName, new LoginCallbackHandler(username, password));
+ loginCtx.login();
+ return loginCtx.getSubject();
+ }
+
+ /**
+ * Authenticate client to use this service and return secure context
+ *
+ * @param socket
+ * The socket used for communication
+ * @param subject
+ * The Kerberos service subject
+ * @param servicePrincipalName
+ * Service principal name
+ *
+ * @return context if authorized or null
+ */
+ public static GSSContext authenticateClient(final Socket socket, Subject subject, final String servicePrincipalName) {
+ return Subject.doAs(subject, new PrivilegedAction<GSSContext>() {
+ public GSSContext run() {
+ try {
+ GSSManager manager = GSSManager.getInstance();
+ GSSName peerName = manager.createName(servicePrincipalName, GSSName.NT_HOSTBASED_SERVICE);
+ GSSContext context = manager.createContext(peerName, null, null, GSSContext.DEFAULT_LIFETIME);
+
+ // Loop while the context is still not established
+ while (!context.isEstablished()) {
+ context.initSecContext(socket.getInputStream(), socket.getOutputStream());
+ }
+
+ return context;
+ } catch (Exception e) {
+ log.error("Unable to authenticate client against Kerberos", e);
+ return null;
+ }
+ }
+ });
+ }
+
+ public static String getSourcePrinciple(GSSContext context) {
+ try {
+ return context.getSrcName().toString();
+ } catch (GSSException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Password callback handler for resolving password/usernames for a JAAS login.
+ *
+ * @author patricioe (Patricio Echague - patricioe@gmail.com)
+ */
+ static class LoginCallbackHandler implements CallbackHandler {
+
+ public LoginCallbackHandler() {
+ super();
+ }
+
+ public LoginCallbackHandler( String name, String password) {
+ super();
+ this.username = name;
+ this.password = password;
+ }
+
+ public LoginCallbackHandler( String password) {
+ super();
+ this.password = password;
+ }
+
+ private String password;
+ private String username;
+
+ /**
+ * Handles the callbacks, and sets the user/password.
+ * @param callbacks the callbacks to handle
+ * @throws IOException if an input or output error occurs.
+ */
+ public void handle( Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+
+ for ( int i=0; i<callbacks.length; i++) {
+ if ( callbacks[i] instanceof NameCallback && username != null) {
+ NameCallback nc = (NameCallback) callbacks[i];
+ nc.setName( username);
+ }
+ else if ( callbacks[i] instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback) callbacks[i];
+ pc.setPassword( password.toCharArray());
+ }
+ else {
+ /*throw new UnsupportedCallbackException(
+ callbacks[i], "Unrecognized Callback");*/
+ }
+ }
+ }
+
+
+ }
+}
View
17 core/src/main/java/me/prettyprint/cassandra/service/CassandraHostConfigurator.java
@@ -49,6 +49,7 @@
private boolean runAutoDiscoveryAtStartup = false;
private boolean useSocketKeepalive = false;
private HOpTimer opTimer = new NullOpTimer();
+ private boolean useKerberosAuthentication = false;
public CassandraHostConfigurator() {
@@ -324,6 +325,20 @@ public void setUseSocketKeepalive(boolean useSocketKeepalive) {
this.useSocketKeepalive = useSocketKeepalive;
}
-
+ /**
+ * Retrieves whether Kerberos authentication is enabled or not.
+ * @return <code>TRUE</code> if Kerberos in enabled. <code>FALSE</code> otherwise.
+ */
+ public boolean isUseKerberosAuthentication() {
+ return useKerberosAuthentication;
+ }
+
+ /**
+ * Set Kerberos Authentication.
+ * @param useKerberosAuthentication
+ */
+ public void setUseKerberosAuthentication(boolean useKerberosAuthentication) {
+ this.useKerberosAuthentication = useKerberosAuthentication;
+ }
}
View
8 core/src/test/java/me/prettyprint/cassandra/connection/ConcurrentHClientPoolTest.java
@@ -3,6 +3,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import me.prettyprint.cassandra.BaseEmbededServerSetupTest;
+import me.prettyprint.cassandra.connection.client.HClient;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
+import me.prettyprint.cassandra.connection.factory.HThriftClientFactoryImpl;
import me.prettyprint.cassandra.service.CassandraHost;
import me.prettyprint.hector.api.exceptions.HInactivePoolException;
@@ -18,7 +21,8 @@
public void setupTest() {
setupClient();
cassandraHost = cassandraHostConfigurator.buildCassandraHosts()[0];
- clientPool = new ConcurrentHClientPool(cassandraHost);
+ HClientFactory factory = new HThriftClientFactoryImpl();
+ clientPool = new ConcurrentHClientPool(factory, cassandraHost);
}
@Test
@@ -46,7 +50,7 @@ public void testShutdown() {
@Test
public void testBorrowRelease() {
- HThriftClient client = clientPool.borrowClient();
+ HClient client = clientPool.borrowClient();
assertEquals(1, clientPool.getNumActive());
clientPool.releaseClient(client);
assertEquals(0, clientPool.getNumActive());
View
21 core/src/test/java/me/prettyprint/cassandra/connection/HConnectionManagerTest.java
@@ -1,12 +1,10 @@
package me.prettyprint.cassandra.connection;
-import static org.junit.Assert.*;
-
-import org.apache.cassandra.thrift.Cassandra.Client;
-import org.junit.Before;
-import org.junit.Test;
-
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import me.prettyprint.cassandra.BaseEmbededServerSetupTest;
+import me.prettyprint.cassandra.connection.client.HClient;
import me.prettyprint.cassandra.service.CassandraHost;
import me.prettyprint.cassandra.service.CassandraHostConfigurator;
import me.prettyprint.cassandra.service.FailoverPolicy;
@@ -14,13 +12,12 @@
import me.prettyprint.cassandra.service.OperationType;
import me.prettyprint.hector.api.exceptions.HTimedOutException;
import me.prettyprint.hector.api.exceptions.HectorException;
-import me.prettyprint.hector.api.exceptions.HectorTransportException;
+
+import org.apache.cassandra.thrift.Cassandra.Client;
+import org.junit.Test;
public class HConnectionManagerTest extends BaseEmbededServerSetupTest {
-
-
-
@Test
public void testRemoveHost() {
setupClient();
@@ -51,8 +48,8 @@ public void testMarkHostDownWithNoRetry() {
cassandraHostConfigurator.setRetryDownedHosts(false);
connectionManager = new HConnectionManager(clusterName, cassandraHostConfigurator);
CassandraHost cassandraHost = new CassandraHost("127.0.0.1", 9170);
- HThriftClient client = connectionManager.borrowClient();
- connectionManager.markHostAsDown(client.cassandraHost);
+ HClient client = connectionManager.borrowClient();
+ connectionManager.markHostAsDown(client.getCassandraHost());
assertEquals(0,connectionManager.getActivePools().size());
}
View
1  core/src/test/java/me/prettyprint/cassandra/connection/HThriftClientTest.java
@@ -3,6 +3,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import me.prettyprint.cassandra.BaseEmbededServerSetupTest;
+import me.prettyprint.cassandra.connection.client.HThriftClient;
import me.prettyprint.cassandra.service.CassandraHost;
import me.prettyprint.hector.api.Cluster;
import me.prettyprint.hector.api.ddl.KeyspaceDefinition;
View
5 core/src/test/java/me/prettyprint/cassandra/connection/LatencyAwareHClientPoolTest.java
@@ -2,6 +2,8 @@
import static org.junit.Assert.assertTrue;
import me.prettyprint.cassandra.BaseEmbededServerSetupTest;
+import me.prettyprint.cassandra.connection.factory.HClientFactory;
+import me.prettyprint.cassandra.connection.factory.HThriftClientFactoryImpl;
import me.prettyprint.cassandra.service.CassandraHost;
import org.junit.Before;
@@ -17,7 +19,8 @@
public void setupTest() {
setupClient();
cassandraHost = cassandraHostConfigurator.buildCassandraHosts()[0];
- clientPool = new LatencyAwareHClientPool(cassandraHost);
+ HClientFactory factory = new HThriftClientFactoryImpl();
+ clientPool = new LatencyAwareHClientPool(factory, cassandraHost);
}
@Test
View
17 core/src/test/resources/kerberos/jaas.conf
@@ -0,0 +1,17 @@
+
+Client {
+ com.sun.security.auth.module.Krb5LoginModule required
+ useKeyTab=false
+ useTicketCache=true
+ renewTGT=true
+ storeKey=true
+ principal="pato@SOMEDOMAIN.COM";
+};
+
+Server {
+ com.sun.security.auth.module.Krb5LoginModule required
+ useKeyTab=false
+ storeKey=true
+ useTicketCache=false
+ principal="cassandra/HOST@SOMEDOMAIN.COM";
+};
View
14 core/src/test/resources/kerberos/krb5.conf
@@ -0,0 +1,14 @@
+[libdefaults]
+ default_realm = SOMEDOMAIN.COM
+ default_checksum = rsa-md5
+
+[realms]
+ SOMEDOMAIN.COM = {
+ kdc = somadomain.com
+ admin_server = somedomain.com
+ }
+
+[domain_realm]
+ somedomain.com = SOMEDOMAIN.COM
+}
+
Please sign in to comment.
Something went wrong with that request. Please try again.