Search in sources :

Example 1 with SaslMechanism

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;
}
Also used : SaslMechanism(org.apache.accumulo.core.rpc.SaslConnectionParams.SaslMechanism) TTransportException(org.apache.thrift.transport.TTransportException) TSaslClientTransport(org.apache.thrift.transport.TSaslClientTransport) SSLContext(javax.net.ssl.SSLContext) IOException(java.io.IOException) TTransport(org.apache.thrift.transport.TTransport) SSLSocketFactory(javax.net.ssl.SSLSocketFactory) UserGroupInformation(org.apache.hadoop.security.UserGroupInformation) TSocket(org.apache.thrift.transport.TSocket)

Example 2 with SaslMechanism

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);
    }
}
Also used : TException(org.apache.thrift.TException) TSaslServerTransport(org.apache.thrift.transport.TSaslServerTransport) SaslServer(javax.security.sasl.SaslServer) SaslMechanism(org.apache.accumulo.core.rpc.SaslConnectionParams.SaslMechanism) TTransport(org.apache.thrift.transport.TTransport) TException(org.apache.thrift.TException) IOException(java.io.IOException) UserGroupInformation(org.apache.hadoop.security.UserGroupInformation)

Aggregations

IOException (java.io.IOException)2 SaslMechanism (org.apache.accumulo.core.rpc.SaslConnectionParams.SaslMechanism)2 UserGroupInformation (org.apache.hadoop.security.UserGroupInformation)2 TTransport (org.apache.thrift.transport.TTransport)2 SSLContext (javax.net.ssl.SSLContext)1 SSLSocketFactory (javax.net.ssl.SSLSocketFactory)1 SaslServer (javax.security.sasl.SaslServer)1 TException (org.apache.thrift.TException)1 TSaslClientTransport (org.apache.thrift.transport.TSaslClientTransport)1 TSaslServerTransport (org.apache.thrift.transport.TSaslServerTransport)1 TSocket (org.apache.thrift.transport.TSocket)1 TTransportException (org.apache.thrift.transport.TTransportException)1