use of org.apache.accumulo.core.rpc.SaslConnectionParams.SaslMechanism in project accumulo by apache.
the class ThriftUtil method createClientTransport.
/**
* Create a TTransport for clients to the given address with the provided socket timeout and session-layer configuration
*
* @param address
* Server address to connect to
* @param timeout
* Client socket timeout
* @param sslParams
* RPC options for SSL servers
* @param saslParams
* RPC options for SASL servers
* @return An open TTransport which must be closed when finished
*/
public static TTransport createClientTransport(HostAndPort address, int timeout, SslConnectionParams sslParams, SaslConnectionParams saslParams) throws TTransportException {
boolean success = false;
TTransport transport = null;
try {
if (sslParams != null) {
// The check in AccumuloServerContext ensures that servers are brought up with sane configurations, but we also want to validate clients
if (null != saslParams) {
throw new IllegalStateException("Cannot use both SSL and SASL");
}
log.trace("Creating SSL client transport");
// TSSLTransportFactory handles timeout 0 -> forever natively
if (sslParams.useJsse()) {
transport = TSSLTransportFactory.getClientSocket(address.getHost(), address.getPort(), timeout);
} else {
// JDK6's factory doesn't appear to pass the protocol onto the Socket properly so we have
// to do some magic to make sure that happens. Not an issue in JDK7
// Taken from thrift-0.9.1 to make the SSLContext
SSLContext sslContext = createSSLContext(sslParams);
// Create the factory from it
SSLSocketFactory sslSockFactory = sslContext.getSocketFactory();
// Wrap the real factory with our own that will set the protocol on the Socket before returning it
ProtocolOverridingSSLSocketFactory wrappingSslSockFactory = new ProtocolOverridingSSLSocketFactory(sslSockFactory, new String[] { sslParams.getClientProtocol() });
// Create the TSocket from that
transport = createClient(wrappingSslSockFactory, address.getHost(), address.getPort(), timeout);
// TSSLTransportFactory leaves transports open, so no need to open here
}
transport = ThriftUtil.transportFactory().getTransport(transport);
} else if (null != saslParams) {
if (!UserGroupInformation.isSecurityEnabled()) {
throw new IllegalStateException("Expected Kerberos security to be enabled if SASL is in use");
}
log.trace("Creating SASL connection to {}:{}", address.getHost(), address.getPort());
// Make sure a timeout is set
try {
transport = TTimeoutTransport.create(address, timeout);
} catch (IOException e) {
log.warn("Failed to open transport to {}", address);
throw new TTransportException(e);
}
try {
// Log in via UGI, ensures we have logged in with our KRB credentials
final UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
final UserGroupInformation userForRpc;
if (AuthenticationMethod.PROXY == currentUser.getAuthenticationMethod()) {
// that the current user is the user that has some credentials.
if (currentUser.getRealUser() != null) {
userForRpc = currentUser.getRealUser();
log.trace("{} is a proxy user, using real user instead {}", currentUser, userForRpc);
} else {
// The current user has no credentials, let it fail naturally at the RPC layer (no ticket)
// We know this won't work, but we can't do anything else
log.warn("The current user is a proxy user but there is no underlying real user (likely that RPCs will fail): {}", currentUser);
userForRpc = currentUser;
}
} else {
// The normal case: the current user has its own ticket
userForRpc = currentUser;
}
// Is this pricey enough that we want to cache it?
final String hostname = InetAddress.getByName(address.getHost()).getCanonicalHostName();
final SaslMechanism mechanism = saslParams.getMechanism();
log.trace("Opening transport to server as {} to {}/{} using {}", userForRpc, saslParams.getKerberosServerPrimary(), hostname, mechanism);
// Create the client SASL transport using the information for the server
// Despite the 'protocol' argument seeming to be useless, it *must* be the primary of the server being connected to
transport = new TSaslClientTransport(mechanism.getMechanismName(), null, saslParams.getKerberosServerPrimary(), hostname, saslParams.getSaslProperties(), saslParams.getCallbackHandler(), transport);
// Wrap it all in a processor which will run with a doAs the current user
transport = new UGIAssumingTransport(transport, userForRpc);
// Open the transport
transport.open();
} catch (TTransportException e) {
log.warn("Failed to open SASL transport", e);
// We might have had a valid ticket, but it expired. We'll let the caller retry, but we will attempt to re-login to make the next attempt work.
// Sadly, we have no way to determine the actual reason we got this TTransportException other than inspecting the exception msg.
log.debug("Caught TTransportException opening SASL transport, checking if re-login is necessary before propagating the exception.");
attemptClientReLogin();
throw e;
} catch (IOException e) {
log.warn("Failed to open SASL transport", e);
throw new TTransportException(e);
}
} else {
log.trace("Opening normal transport");
if (timeout == 0) {
transport = new TSocket(address.getHost(), address.getPort());
transport.open();
} else {
try {
transport = TTimeoutTransport.create(address, timeout);
} catch (IOException ex) {
log.warn("Failed to open transport to {}", address);
throw new TTransportException(ex);
}
// Open the transport
transport.open();
}
transport = ThriftUtil.transportFactory().getTransport(transport);
}
success = true;
} finally {
if (!success && transport != null) {
transport.close();
}
}
return transport;
}
use of org.apache.accumulo.core.rpc.SaslConnectionParams.SaslMechanism in project accumulo by apache.
the class UGIAssumingProcessor method process.
@Override
public boolean process(final TProtocol inProt, final TProtocol outProt) throws TException {
TTransport trans = inProt.getTransport();
if (!(trans instanceof TSaslServerTransport)) {
throw new TException("Unexpected non-SASL transport " + trans.getClass() + ": " + trans);
}
TSaslServerTransport saslTrans = (TSaslServerTransport) trans;
SaslServer saslServer = saslTrans.getSaslServer();
String authId = saslServer.getAuthorizationID();
String endUser = authId;
SaslMechanism mechanism;
try {
mechanism = SaslMechanism.get(saslServer.getMechanismName());
} catch (Exception e) {
log.error("Failed to process RPC with SASL mechanism {}", saslServer.getMechanismName());
throw e;
}
switch(mechanism) {
case GSSAPI:
UserGroupInformation clientUgi = UserGroupInformation.createProxyUser(endUser, loginUser);
final String remoteUser = clientUgi.getUserName();
try {
// Set the principal in the ThreadLocal for access to get authorizations
rpcPrincipal.set(remoteUser);
return wrapped.process(inProt, outProt);
} finally {
// Unset the principal after we're done using it just to be sure that it's not incorrectly
// used in the same thread down the line.
rpcPrincipal.set(null);
}
case DIGEST_MD5:
// the rpcPrincipal for us. We don't need to do it again here.
try {
rpcMechanism.set(mechanism);
return wrapped.process(inProt, outProt);
} finally {
// Unset the mechanism after we're done using it just to be sure that it's not incorrectly
// used in the same thread down the line.
rpcMechanism.set(null);
}
default:
throw new IllegalArgumentException("Cannot process SASL mechanism " + mechanism);
}
}
Aggregations