[ 
https://issues.apache.org/jira/browse/DRILL-6187?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16393341#comment-16393341
 ] 

ASF GitHub Bot commented on DRILL-6187:
---------------------------------------

Github user vrozov commented on a diff in the pull request:

    https://github.com/apache/drill/pull/1145#discussion_r173529523
  
    --- Diff: 
exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BitRpcUtility.java ---
    @@ -0,0 +1,110 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one
    + * or more contributor license agreements.  See the NOTICE file
    + * distributed with this work for additional information
    + * regarding copyright ownership.  The ASF licenses this file
    + * to you under the Apache License, Version 2.0 (the
    + * "License"); you may not use this file except in compliance
    + * with the License.  You may obtain a copy of the License at
    + *
    + *    http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package org.apache.drill.exec.rpc;
    +
    +import com.google.common.collect.ImmutableList;
    +import com.google.protobuf.Internal.EnumLite;
    +import com.google.protobuf.MessageLite;
    +import org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint;
    +import org.apache.drill.exec.rpc.security.AuthenticatorFactory;
    +import org.apache.drill.exec.rpc.security.SaslProperties;
    +import org.apache.hadoop.security.UserGroupInformation;
    +
    +import java.io.IOException;
    +import java.util.List;
    +import java.util.Map;
    +
    +/**
    + * Utility class providing common methods shared between {@link 
org.apache.drill.exec.rpc.data.DataClient} and
    + * {@link org.apache.drill.exec.rpc.control.ControlClient}
    + */
    +public final class BitRpcUtility {
    +  private static final org.slf4j.Logger logger = 
org.slf4j.LoggerFactory.getLogger(BitRpcUtility.class);
    +
    +  /**
    +   * Method to do validation on the handshake message received from server 
side. Only used by BitClients NOT UserClient.
    +   * Verify if rpc version of handshake message matches the supported 
RpcVersion and also validates the
    +   * security configuration between client and server
    +   * @param handshakeRpcVersion - rpc version received in handshake message
    +   * @param remoteAuthMechs - authentication mechanisms supported by server
    +   * @param rpcVersion - supported rpc version on client
    +   * @param connection - client connection
    +   * @param config - client connectin config
    +   * @param client - data client or control client
    +   * @return - Immutable list of authentication mechanisms supported by 
server or null
    +   * @throws RpcException - exception is thrown if rpc version or 
authentication configuration mismatch is found
    +   */
    +  public static List<String> validateHandshake(int handshakeRpcVersion, 
List<String> remoteAuthMechs, int rpcVersion,
    +                                               ClientConnection 
connection, BitConnectionConfig config,
    +                                               BasicClient client) throws 
RpcException {
    +
    +    if (handshakeRpcVersion != rpcVersion) {
    +      throw new RpcException(String.format("Invalid rpc version.  Expected 
%d, actual %d.",
    +        handshakeRpcVersion, rpcVersion));
    +    }
    +
    +    if (remoteAuthMechs.size() != 0) { // remote requires authentication
    +      client.setAuthComplete(false);
    +      return ImmutableList.copyOf(remoteAuthMechs);
    +    } else {
    +      if (config.getAuthMechanismToUse() != null) { // local requires 
authentication
    +        throw new RpcException(String.format("Remote Drillbit does not 
require auth, but auth is enabled in " +
    +          "local Drillbit configuration. [Details: connection: (%s) and 
LocalAuthMechanism: (%s). Please check " +
    +          "security configuration for bit-to-bit.", connection.getName(), 
config.getAuthMechanismToUse()));
    +      }
    +    }
    +    return null;
    +  }
    +
    +  /**
    +   * Creates various instances needed to start the SASL handshake. This is 
called from
    +   * {@link BasicClient#prepareSaslHandshake(RpcConnectionHandler, List)} 
only for
    +   * {@link org.apache.drill.exec.rpc.data.DataClient} and {@link 
org.apache.drill.exec.rpc.control.ControlClient}
    +   *
    +   * @param connectionHandler    - Connection handler used by client's to 
know about success/failure conditions.
    +   * @param serverAuthMechanisms - List of auth mechanisms configured on 
server side
    +   * @param connection - ClientConnection used for authentication
    +   * @param config - ClientConnection config
    +   * @param endpoint - Remote DrillbitEndpoint
    +   * @param client - Either of DataClient/ControlClient instance
    +   * @param saslRpcType - SASL_MESSAGE RpcType for Data and Control channel
    +   */
    +  public static <T extends EnumLite, CC extends ClientConnection, HS 
extends MessageLite, HR extends MessageLite>
    +  void prepareSaslHandshake(final RpcConnectionHandler<CC> 
connectionHandler, List<String> serverAuthMechanisms,
    +                            CC connection, BitConnectionConfig config, 
DrillbitEndpoint endpoint,
    +                            final BasicClient<T, CC, HS, HR> client, T 
saslRpcType) {
    +    try {
    +      final Map<String, String> saslProperties = 
SaslProperties.getSaslProperties(connection.isEncryptionEnabled(),
    +        connection.getMaxWrappedSize());
    +      final UserGroupInformation ugi = UserGroupInformation.getLoginUser();
    +      final AuthenticatorFactory factory = 
config.getAuthFactory(serverAuthMechanisms);
    +      client.startSaslHandshake(connectionHandler, 
config.getSaslClientProperties(endpoint, saslProperties),
    +        ugi, factory, saslRpcType);
    +    } catch (final IOException e) {
    +      logger.error("Failed while doing setup for starting sasl handshake 
for connection", connection.getName());
    +      final Exception ex = new RpcException(String.format("Failed to 
initiate authentication to %s",
    +        endpoint.getAddress()), e);
    +      
connectionHandler.connectionFailed(RpcConnectionHandler.FailureType.AUTHENTICATION,
 ex);
    +    }
    +  }
    +
    +  // Suppress default constructor
    +  private BitRpcUtility() throws Exception {
    --- End diff --
    
    Exception is not required, just make the constructor private.


> Exception in RPC communication between DataClient/ControlClient and 
> respective servers when bit-to-bit security is on
> ---------------------------------------------------------------------------------------------------------------------
>
>                 Key: DRILL-6187
>                 URL: https://issues.apache.org/jira/browse/DRILL-6187
>             Project: Apache Drill
>          Issue Type: Bug
>          Components: Execution - RPC, Security
>            Reporter: Sorabh Hamirwasia
>            Assignee: Sorabh Hamirwasia
>            Priority: Major
>             Fix For: 1.13.0
>
>
>  
> {color:#000000}Below is the summary of issue: {color}
>  
> {color:#000000}*Scenario:*{color}
> {color:#000000}It seems like first sendRecordBatch was sent to Foreman which 
> initiated the Authentication handshake. But before initiating handshake for 
> auth we establish a connection and store that in a registry. Now if in 
> parallel there is another recordBatch (by a different minor fragment running 
> on same Drillbit) to be sent then that will see the connection available in 
> registry and will initiate the send. Before the authentication is completed 
> this second request reached foreman and it throws below exception saying RPC 
> type 3 message is not allowed and closes the connection. This also fails the 
> authentication handshake which was in progress.{color}{color:#000000} Here 
> the logs with details:{color}
> {color:#000000} {color}
> {color:#000000}*Forman received the SASL_START message from another 
> node:*{color}
> {color:#000000}*_2018-02-21 18:43:30,759 
> [_*{color}{color:#000000}_BitServer-4] TRACE 
> o.a.d.e.r.s.ServerAuthenticationHandler - Received SASL message SASL_START 
> from /10.10.100.161:35482_{color}
> {color:#000000} {color}
> {color:#000000}*Then around same time it received another message from client 
> of Rpc Type 3 which is for SendRecordBatch and fails since handshake is not 
> completed yet.*{color}
> {color:#000000} {color}
> {color:#000000}*_2018-02-21 18:43:30,762_*{color}{color:#000000} 
> _[BitServer-4] ERROR o.a.d.exec.rpc.RpcExceptionHandler - Exception in RPC 
> communication.  Connection: /10.10.100.162:31012 <--> /__10.10.100.161:35482_ 
> _(data server).  Closing connection._{color}
> {color:#000000}_io.netty.handler.codec.DecoderException: 
> org.apache.drill.exec.rpc.RpcException: Request of type 3 is not allowed 
> without authentication. Client on /__10.10.100.161:35482_ _must authenticate 
> before making requests. Connection dropped. [Details: Encryption: enabled , 
> MaxWrappedSize: 65536 , WrapSizeLimit: 0]_{color}
> {color:#000000} {color}
> {color:#000000}*Then client receives an channel closed exception:*{color}
> {color:#000000} {color}
> {color:#000000}*2018-02-21 18:43:30,764 [*{color}{color:#000000}BitClient-4] 
> WARN  o.a.d.exec.rpc.RpcExceptionHandler - Exception occurred with closed 
> channel.  Connection: /_10.10.100.161:35482_ <--> _10.10.100.162:31012_ (data 
> client){color}
> {color:#000000} {color}
> {color:#000000}*and due to this it's initial command for authentication also 
> fails. Since there is channel closed exception above I will think that 
> triggered the failure of authentication request as well.*{color}
> {color:#000000} {color}
> {color:#000000}_Caused by: org.apache.drill.exec.rpc.RpcException: Command 
> failed while establishing connection.  Failure type AUTHENTICATION._{color}
> {color:#000000}        _at 
> org.apache.drill.exec.rpc.RpcException.mapException(RpcException.java:67) 
> ~[drill-rpc-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000}        _at 
> org.apache.drill.exec.rpc.ListeningCommand.connectionFailed(ListeningCommand.java:66)
>  ~[drill-rpc-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000}        _at 
> org.apache.drill.exec.rpc.data.DataTunnel$SendBatchAsyncListen.connectionFailed(DataTunnel.java:166)
>  ~[drill-java-exec-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000}        _at 
> org.apache.drill.exec.rpc.data.DataClient$AuthenticationCommand.connectionSucceeded(DataClient.java:203)
>  ~[drill-java-exec-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000}        _at 
> org.apache.drill.exec.rpc.data.DataClient$AuthenticationCommand.connectionSucceeded(DataClient.java:147)
>  ~[drill-java-exec-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000}        _at 
> org.apache.drill.exec.rpc.ReconnectingConnection$ConnectionListeningFuture.waitAndRun(ReconnectingConnection.java:122)
>  ~[drill-rpc-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000}        _at 
> org.apache.drill.exec.rpc.ReconnectingConnection.runCommand(ReconnectingConnection.java:83)
>  ~[drill-rpc-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000}        _at 
> org.apache.drill.exec.rpc.data.DataTunnel._{color}{color:#000000}*_sendRecordBatch_*{color}{color:#000000}_(DataTunnel.java:84)
>  ~[drill-java-exec-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000}        _at 
> org.apache.drill.exec.ops.AccountingDataTunnel.sendRecordBatch(AccountingDataTunnel.java:45)
>  ~[drill-java-exec-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000}        _at 
> org.apache.drill.exec.physical.impl.SingleSenderCreator$SingleSenderRootExec.innerNext(SingleSenderCreator.java:127)
>  ~[drill-java-exec-1.12.0-mapr.jar:1.12.0-mapr]_{color}
> {color:#000000} {color}
> {color:#000000}So I think there is a concurrency issue where even though the 
> authentication is not completed the other requests are send to remote node as 
> soon as TCP connection is available. Instead it should wait until 
> authentication is completed. Something like TCP connection should be made 
> available from registry only if authentication is completed.{color}
>  
>  



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to