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

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

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

    https://github.com/apache/drill/pull/578#discussion_r99261692
  
    --- Diff: 
exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java ---
    @@ -88,22 +129,183 @@ public void submitQuery(UserResultsListener 
resultsListener, RunQuery query) {
         send(queryResultHandler.getWrappedListener(resultsListener), 
RpcType.RUN_QUERY, query, QueryId.class);
       }
     
    -  public void connect(RpcConnectionHandler<ServerConnection> handler, 
DrillbitEndpoint endpoint,
    -                      UserProperties props, UserBitShared.UserCredentials 
credentials) {
    +  public CheckedFuture<Void, RpcException> connect(DrillbitEndpoint 
endpoint, DrillProperties parameters,
    +                                                   UserCredentials 
credentials) {
    +    final FutureHandler handler = new FutureHandler();
         UserToBitHandshake.Builder hsBuilder = UserToBitHandshake.newBuilder()
             .setRpcVersion(UserRpcConfig.RPC_VERSION)
             .setSupportListening(true)
             .setSupportComplexTypes(supportComplexTypes)
             .setSupportTimeout(true)
             .setCredentials(credentials)
    -        .setClientInfos(UserRpcUtils.getRpcEndpointInfos(clientName));
    +        .setClientInfos(UserRpcUtils.getRpcEndpointInfos(clientName))
    +        .setSaslSupport(SaslSupport.SASL_AUTH)
    +        .setProperties(parameters.serializeForServer());
    +    this.properties = parameters;
    +
    +    
connectAsClient(queryResultHandler.getWrappedConnectionHandler(handler),
    +        hsBuilder.build(), endpoint.getAddress(), endpoint.getUserPort());
    +    return handler;
    +  }
    +
    +  /**
    +   * Check (after {@link #connect connecting}) if server requires 
authentication.
    +   *
    +   * @return true if server requires authentication
    +   */
    +  public boolean serverRequiresAuthentication() {
    +    return supportedAuthMechs != null;
    +  }
    +
    +  /**
    +   * Returns a list of supported authentication mechanism. If called 
before {@link #connect connecting},
    +   * returns null. If called after {@link #connect connecting}, returns a 
list of supported mechanisms
    +   * iff authentication is required.
    +   *
    +   * @return list of supported authentication mechanisms
    +   */
    +  public List<String> getSupportedAuthenticationMechanisms() {
    +    return supportedAuthMechs;
    +  }
     
    -    if (props != null) {
    -      hsBuilder.setProperties(props);
    +  /**
    +   * Authenticate to the server asynchronously. Returns a future that 
{@link CheckedFuture#checkedGet results}
    +   * in null if authentication succeeds, or throws a {@link SaslException} 
with relevant message if
    +   * authentication fails.
    +   *
    +   * This method uses properties provided at {@link #connect connection 
time} and override them with the
    +   * given properties, if any.
    +   *
    +   * @param overrides parameter overrides
    +   * @return result of authentication request
    +   */
    +  public CheckedFuture<Void, SaslException> authenticate(final 
DrillProperties overrides) {
    +    if (supportedAuthMechs == null) {
    +      throw new IllegalStateException("Server does not require 
authentication.");
         }
    +    properties.merge(overrides);
    +    final Map<String, String> propertiesMap = 
properties.stringPropertiesAsMap();
     
    -    
this.connectAsClient(queryResultHandler.getWrappedConnectionHandler(handler),
    -        hsBuilder.build(), endpoint.getAddress(), endpoint.getUserPort());
    +    final SettableFuture<Void> settableFuture = SettableFuture.create(); 
// future used in SASL exchange
    +    final CheckedFuture<Void, SaslException> future =
    +        new AbstractCheckedFuture<Void, SaslException>(settableFuture) {
    +
    +          @Override
    +          protected SaslException mapException(Exception e) {
    +            if (connection != null) {
    +              connection.close(); // to ensure connection is dropped
    +            }
    +            if (e instanceof ExecutionException) {
    +              final Throwable cause = e.getCause();
    +              if (cause instanceof SaslException) {
    +                return new SaslException("Authentication failed: " + 
cause.getMessage(), cause);
    +              }
    +            }
    +            return new SaslException("Authentication failed 
unexpectedly.", e);
    +          }
    +        };
    +
    +    final AuthenticatorFactory factory;
    +    try {
    +      factory = getAuthenticatorFactory();
    +    } catch (final SaslException e) {
    +      settableFuture.setException(e);
    +      return future;
    +    }
    +
    +    final String mechanismName = factory.getSimpleName();
    +    logger.trace("Will try to login for {} mechanism.", mechanismName);
    +    final UserGroupInformation ugi;
    +    try {
    +      ugi = factory.createAndLoginUser(propertiesMap);
    +    } catch (final IOException e) {
    +      settableFuture.setException(e);
    +      return future;
    +    }
    +
    +    logger.trace("Will try to authenticate to server using {} mechanism.", 
mechanismName);
    +    final SaslClient saslClient;
    +    try {
    +      saslClient = factory.createSaslClient(ugi, propertiesMap);
    +      connection.setSaslClient(saslClient);
    +    } catch (final SaslException e) {
    +      settableFuture.setException(e);
    +      return future;
    +    }
    +
    +    if (saslClient == null) {
    +      settableFuture.setException(new SaslException("Cannot initiate 
authentication. Insufficient credentials?"));
    +      return future;
    +    }
    +
    +    logger.trace("Initiating SASL exchange.");
    +    new AuthenticationOutcomeListener<>(this, connection, 
RpcType.SASL_MESSAGE, ugi, new RpcOutcomeListener<Void>(){
    +
    +      @Override
    +      public void failed(RpcException ex) {
    +        settableFuture.setException(ex);
    +      }
    +
    +      @Override
    +      public void success(Void value, ByteBuf buffer) {
    +        authComplete = true;
    +        settableFuture.set(null);
    +      }
    +
    +      @Override
    +      public void interrupted(InterruptedException e) {
    +        settableFuture.setException(e);
    +      }
    +    })
    +        .initiate(mechanismName);
    --- End diff --
    
    please move this up.


> Kerberos Authentication
> -----------------------
>
>                 Key: DRILL-4280
>                 URL: https://issues.apache.org/jira/browse/DRILL-4280
>             Project: Apache Drill
>          Issue Type: Improvement
>            Reporter: Keys Botzum
>            Assignee: Sudheesh Katkam
>              Labels: security
>
> Drill should support Kerberos based authentication from clients. This means 
> that both the ODBC and JDBC drivers as well as the web/REST interfaces should 
> support inbound Kerberos. For Web this would most likely be SPNEGO while for 
> ODBC and JDBC this will be more generic Kerberos.
> Since Hive and much of Hadoop supports Kerberos there is a potential for a 
> lot of reuse of ideas if not implementation.
> Note that this is related to but not the same as 
> https://issues.apache.org/jira/browse/DRILL-3584 



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Reply via email to