![JAR search and dependency download from the Maven repository](/logo.png)
com.datastax.driver.dse.auth.DseGSSAPIAuthProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dse-driver Show documentation
Show all versions of dse-driver Show documentation
A driver for DataStax Enterprise clusters (DSE), supporting DSE-specific features such as geospatial types, DSE Graph and DSE authentication.
The newest version!
/*
* Copyright (C) 2012-2016 DataStax Inc.
*
* This software can be used solely with DataStax Enterprise. Please consult the license at
* http://www.datastax.com/terms/datastax-dse-driver-license-terms
*/
package com.datastax.driver.dse.auth;
import com.datastax.driver.core.AuthProvider;
import com.datastax.driver.core.Authenticator;
import com.datastax.driver.core.exceptions.AuthenticationException;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
import javax.security.auth.Subject;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
import java.net.InetSocketAddress;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.Map;
/**
* {@link AuthProvider} that provides GSSAPI authenticator instances for clients to connect
* to DSE clusters secured with {@code DseAuthenticator}.
*
* To create a cluster using this auth provider, declare the following:
* {@code
* Cluster cluster = Cluster.builder()
* .addContactPoint(hostname)
* .withAuthProvider(new DseGSSAPIAuthProvider())
* .build();
* }
* Kerberos Authentication
* Keytab and ticket cache settings are specified using a standard JAAS
* configuration file. The location of the file can be set using the
* java.security.auth.login.config
system property or by adding a
* login.config.url.n
entry in the java.security
properties
* file.
*
* Alternatively a {@link Configuration} object can be provided using {@link #DseGSSAPIAuthProvider(Configuration)} to
* set the JAAS configuration programmatically.
*
* See the following documents for further details:
*
* - JAAS Login Configuration File;
* - JAAS Authentication Tutorial
* for more on JAAS in general.
*
* Authentication using ticket cache
* Run kinit
to obtain a ticket and populate the cache before
* connecting. JAAS config:
*
* DseClient {
* com.sun.security.auth.module.Krb5LoginModule required
* useTicketCache=true
* renewTGT=true;
* };
*
* Authentication using a keytab file
* To enable authentication using 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="[email protected]";
* };
*
* Specifying SASL protocol name
* The SASL protocol name used by this auth provider defaults to "{@value #DEFAULT_SASL_PROTOCOL_NAME}
".
*
* Important: the SASL protocol name should match the username of the
* Kerberos service principal used by the DSE server.
* This information is specified in the dse.yaml file by the {@code service_principal} option under the
* kerberos_options
* section, and may vary from one DSE installation to another – especially if you
* installed DSE with an automated package installer.
*
* For example, if your dse.yaml file contains the following:
* {@code
* kerberos_options:
* ...
* service_principal: cassandra/[email protected]
* }
* The correct SASL protocol name to use when authenticating against this DSE server is "{@code cassandra}".
*
* Should you need to change the SASL protocol name, use one of the methods below:
*
* - Specify the protocol name via one of the following constructors:
* {@link #DseGSSAPIAuthProvider(String)} or {@link #DseGSSAPIAuthProvider(Configuration, String)};
* - Specify the protocol name with the {@code dse.sasl.protocol} system property when starting your application,
* e.g. {@code -Ddse.sasl.protocol=cassandra}.
*
* If a non-null SASL protocol name is provided to the aforementioned constructors, that name takes precedence over
* the contents of the {@code dse.sasl.protocol} system property.
*
* @see Authenticating a DSE cluster with Kerberos
*/
public class DseGSSAPIAuthProvider implements AuthProvider {
/**
* The default SASL protocol name used by this auth provider.
*/
public static final String DEFAULT_SASL_PROTOCOL_NAME = "dse";
/**
* The name of the system property to use to specify the SASL protocol name.
*/
public static final String SASL_PROTOCOL_NAME_PROPERTY = "dse.sasl.protocol";
private final Configuration loginConfiguration;
private final String saslProtocol;
/**
* Creates an instance of {@code DseGSSAPIAuthProvider} with default login configuration options and default
* SASL protocol name ({@value #DEFAULT_SASL_PROTOCOL_NAME}).
*/
public DseGSSAPIAuthProvider() {
this(null, null);
}
/**
* Creates an instance of {@code DseGSSAPIAuthProvider} with the given login configuration and default
* SASL protocol name ({@value #DEFAULT_SASL_PROTOCOL_NAME}).
*
* @param loginConfiguration The login configuration to use to create a {@link LoginContext}.
*/
public DseGSSAPIAuthProvider(Configuration loginConfiguration) {
this(loginConfiguration, null);
}
/**
* Creates an instance of {@code DseGSSAPIAuthProvider} with default login configuration and the given
* SASL protocol name.
*
* @param saslProtocol The SASL protocol name to use; should match the username of the
* Kerberos service principal used by the DSE server.
*/
public DseGSSAPIAuthProvider(String saslProtocol) {
this(null, saslProtocol);
}
/**
* Creates an instance of {@code DseGSSAPIAuthProvider} with the given login configuration and the given
* SASL protocol name.
*
* @param loginConfiguration The login configuration to use to create a {@link LoginContext}.
* @param saslProtocol The SASL protocol name to use; should match the username of the
* Kerberos service principal used by the DSE server.
*/
public DseGSSAPIAuthProvider(Configuration loginConfiguration, String saslProtocol) {
this.loginConfiguration = loginConfiguration;
this.saslProtocol = saslProtocol;
}
@Override
public Authenticator newAuthenticator(InetSocketAddress host, String authenticator) throws AuthenticationException {
return new GSSAPIAuthenticator(authenticator, host, loginConfiguration, saslProtocol);
}
private static class GSSAPIAuthenticator extends BaseDseAuthenticator {
private static final String JAAS_CONFIG_ENTRY = "DseClient";
private static final String[] SUPPORTED_MECHANISMS = new String[]{"GSSAPI"};
private static final Map DEFAULT_PROPERTIES =
ImmutableMap.builder().put(Sasl.SERVER_AUTH, "true")
.put(Sasl.QOP, "auth")
.build();
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private static final byte[] MECHANISM = "GSSAPI".getBytes(Charsets.UTF_8);
private static final byte[] SERVER_INITIAL_CHALLENGE = "GSSAPI-START".getBytes(Charsets.UTF_8);
private final Subject subject;
private final SaslClient saslClient;
private GSSAPIAuthenticator(String authenticator, InetSocketAddress host, Configuration loginConfiguration, String saslProtocol) {
super(authenticator);
try {
String protocol = saslProtocol;
if (protocol == null) {
protocol = System.getProperty(SASL_PROTOCOL_NAME_PROPERTY, DEFAULT_SASL_PROTOCOL_NAME);
}
LoginContext login = new LoginContext(JAAS_CONFIG_ENTRY, null, null, loginConfiguration);
login.login();
subject = login.getSubject();
saslClient = Sasl.createSaslClient(SUPPORTED_MECHANISMS,
null,
protocol,
host.getAddress().getCanonicalHostName(),
DEFAULT_PROPERTIES,
null);
} catch (LoginException e) {
throw new RuntimeException(e);
} catch (SaslException e) {
throw new RuntimeException(e);
}
}
public byte[] getMechanism() {
return MECHANISM.clone();
}
public byte[] getInitialServerChallenge() {
return SERVER_INITIAL_CHALLENGE.clone();
}
public byte[] evaluateChallenge(byte[] challenge) {
if (Arrays.equals(SERVER_INITIAL_CHALLENGE, challenge)) {
if (!saslClient.hasInitialResponse()) {
return EMPTY_BYTE_ARRAY;
}
challenge = EMPTY_BYTE_ARRAY;
}
final byte[] internalChallenge = challenge;
try {
return Subject.doAs(subject, new PrivilegedExceptionAction() {
public byte[] run() throws SaslException {
return saslClient.evaluateChallenge(internalChallenge);
}
});
} catch (PrivilegedActionException e) {
throw new RuntimeException(e.getException());
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy