stoty commented on code in PR #5881:
URL: https://github.com/apache/hbase/pull/5881#discussion_r1601547952


##########
hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/client/Client.java:
##########
@@ -377,19 +476,59 @@ public HttpResponse execute(Cluster cluster, 
HttpUriRequest method, Header[] hea
    * @param uri    the String to parse as a URL.
    * @throws IOException if unknown protocol is found.
    */
-  private void negotiate(HttpUriRequest method, String uri) throws IOException 
{
+  private void negotiate(HttpUriRequest method, String uri)
+    throws IOException, GeneralSecurityException {
     try {
       AuthenticatedURL.Token token = new AuthenticatedURL.Token();
-      KerberosAuthenticator authenticator = new KerberosAuthenticator();
-      authenticator.authenticate(new URL(uri), token);
-      // Inject the obtained negotiated token in the method cookie
-      injectToken(method, token);
+      if (authenticator == null) {
+        authenticator = new KerberosAuthenticator();
+        if (trustStore.isPresent()) {
+          // The authenticator does not use Apache HttpClient, so we need to
+          // configure it separately to use the specified trustStore
+          Configuration sslConf = setupTrustStoreForHadoop(trustStore.get());
+          SSLFactory sslFactory = new SSLFactory(Mode.CLIENT, sslConf);
+          sslFactory.init();
+          authenticator.setConnectionConfigurator(sslFactory);
+        }
+      }
+      URL url = new URL(uri);
+      authenticator.authenticate(url, token);
+      if (sticky) {
+        BasicClientCookie authCookie = new BasicClientCookie("hadoop.auth", 
token.toString());
+        // Hadoop eats the domain even if set by server
+        authCookie.setDomain(url.getHost());
+        stickyContext.getCookieStore().addCookie(authCookie);
+      } else {
+        // session cookie is NOT set for backwards compatibility for 
non-sticky mode
+        // Inject the obtained negotiated token in the method cookie
+        // This is only done for this single request, the next one will 
trigger a new SPENGO
+        // handshake
+        injectToken(method, token);
+      }
     } catch (AuthenticationException e) {
       LOG.error("Failed to negotiate with the server.", e);
       throw new IOException(e);
     }
   }
 
+  private Configuration setupTrustStoreForHadoop(KeyStore trustStore)
+    throws IOException, KeyStoreException, NoSuchAlgorithmException, 
CertificateException {
+    String tmpdir =
+      
Files.createTempDirectory("hbase_rest_client_truststore").toFile().getAbsolutePath();
+    String trustStoreLocation = tmpdir + File.separator + "truststore.jks";

Review Comment:
   Done



##########
hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/client/Client.java:
##########
@@ -176,22 +229,56 @@ public Client(Cluster cluster, Configuration conf, 
boolean sslEnabled) {
    */
   public Client(Cluster cluster, String trustStorePath, Optional<String> 
trustStorePassword,
     Optional<String> trustStoreType) {
-    this(cluster, HBaseConfiguration.create(), trustStorePath, 
trustStorePassword, trustStoreType);
+    this(cluster, HBaseConfiguration.create(), true, trustStorePath, 
trustStorePassword,
+      trustStoreType);
   }
 
   /**
-   * Constructor, allowing to define custom trust store (only for SSL 
connections)
+   * Constructor that accepts an optional trustStore and authentication 
information for either BASIC
+   * or BEARER authentication in sticky mode, which does not use the old 
faulty load balancing
+   * logic, and enables correct session handling. If neither 
userName/password, nor the bearer token
+   * is specified, the client falls back to SPNEGO auth. The loadTrustsore 
static method can be used
+   * to load a local trustStore file. This is the preferred constructor to use.
+   * @param cluster     the cluster definition
+   * @param conf        HBase/Hadoop configuration
+   * @param sslEnabled  use HTTPS
+   * @param trustStore  the optional trustStore object
+   * @param userName    for BASIC auth
+   * @param password    for BASIC auth
+   * @param bearerToken for BEAERER auth
+   */
+  public Client(Cluster cluster, Configuration conf, boolean sslEnabled,
+    Optional<KeyStore> trustStore, Optional<String> userName, Optional<String> 
password,
+    Optional<String> bearerToken) {
+    initialize(cluster, conf, sslEnabled, true, trustStore, userName, 
password, bearerToken);
+  }
+
+  /**
+   * Constructor, allowing to define custom trust store (only for SSL 
connections) This constructor
+   * also enables sticky mode. This is a preferred constructor when not using 
BASIC or JWT
+   * authentication. Clients created by this will not use the old faulty load 
balancing logic.
    * @param cluster            the cluster definition
-   * @param conf               Configuration
+   * @param conf               HBase/Hadoop Configuration
    * @param trustStorePath     custom trust store to use for SSL connections
    * @param trustStorePassword password to use for custom trust store
    * @param trustStoreType     type of custom trust store
    * @throws ClientTrustStoreInitializationException if the trust store file 
can not be loaded
    */
-  public Client(Cluster cluster, Configuration conf, String trustStorePath,
+  public Client(Cluster cluster, Configuration conf, boolean sslEnabled, 
String trustStorePath,

Review Comment:
   Done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@hbase.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to