This is an automated email from the ASF dual-hosted git repository.

mehul pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new c647cfd  RANGER-3264 : Add support/Fix Test connection with Solr 
service
c647cfd is described below

commit c647cfdac8c44b3b7b30e4f02ad8052c935b67ac
Author: mateenmansoori <ma3naus...@gmail.com>
AuthorDate: Tue May 18 14:14:09 2021 +0530

    RANGER-3264 : Add support/Fix Test connection with Solr service
    
    Signed-off-by: Mehul Parikh <me...@apache.org>
---
 .../services/solr/client/ServiceSolrClient.java    | 215 ++++++++++++++++++---
 .../solr/client/ServiceSolrConnectionMgr.java      |  23 +--
 2 files changed, 195 insertions(+), 43 deletions(-)

diff --git 
a/plugin-solr/src/main/java/org/apache/ranger/services/solr/client/ServiceSolrClient.java
 
b/plugin-solr/src/main/java/org/apache/ranger/services/solr/client/ServiceSolrClient.java
index d2f9055..4b69fb9 100644
--- 
a/plugin-solr/src/main/java/org/apache/ranger/services/solr/client/ServiceSolrClient.java
+++ 
b/plugin-solr/src/main/java/org/apache/ranger/services/solr/client/ServiceSolrClient.java
@@ -20,23 +20,38 @@
 package org.apache.ranger.services.solr.client;
 
 import java.io.IOException;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 
+import javax.security.auth.Subject;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.security.SecureClientLogin;
 import org.apache.log4j.Logger;
 import org.apache.ranger.plugin.client.BaseClient;
+import org.apache.ranger.plugin.client.HadoopConfigHolder;
+import org.apache.ranger.plugin.client.HadoopException;
 import org.apache.ranger.plugin.service.ResourceLookupContext;
 import org.apache.ranger.plugin.util.PasswordUtils;
 import org.apache.ranger.plugin.util.TimedEventUtil;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrResponse;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.HttpClientUtil;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.Krb5HttpClientBuilder;
+import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.CoreAdminRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
@@ -44,7 +59,6 @@ import 
org.apache.solr.client.solrj.response.CoreAdminResponse;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.common.params.CoreAdminParams.CoreAdminAction;
 import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.commons.collections.CollectionUtils;
 
 public class ServiceSolrClient {
        private static final Logger LOG = 
Logger.getLogger(ServiceSolrClient.class);
@@ -63,41 +77,58 @@ public class ServiceSolrClient {
 
        private String username;
        private String password;
+       private String serviceName;
        private SolrClient solrClient = null;
        private boolean isSolrCloud = true;
+       private boolean isKerberosAuth;
+       private String url;
+       private Subject loginSubject;
+       private String authType;
 
-       public ServiceSolrClient(SolrClient solrClient,
-                       boolean isSolrCloud, Map<String, String> configs) {
-               this.solrClient = solrClient;
-               this.isSolrCloud = isSolrCloud;
+       public ServiceSolrClient(String serviceName, Map<String, String> 
configs, String url, boolean isSolrCloud) {
                this.username = configs.get("username");
                this.password = configs.get("password");
+               this.authType = 
configs.get(HadoopConfigHolder.RANGER_AUTH_TYPE);
+               this.isKerberosAuth = 
HadoopConfigHolder.HADOOP_SECURITY_AUTHENTICATION_METHOD.equalsIgnoreCase(this.authType);
+               this.url = url;
+               this.serviceName = serviceName;
+               this.isSolrCloud = isSolrCloud;
+               this.createSolrClientInstance();
+               this.login(configs);
        }
 
        public Map<String, Object> connectionTest() throws Exception {
-               String errMsg = errMessage;
                Map<String, Object> responseData = new HashMap<String, 
Object>();
 
+               if(this.isKerberosAuth) {
+                       Subject.doAs(this.loginSubject, new 
PrivilegedAction<Void>() {
+                               @Override
+                               public Void run() {
+                                       testConnection(responseData);
+                                       return null;
+                               }
+                       });
+               } else {
+                       testConnection(responseData);
+               }
+               return responseData;
+       }
+
+       private void testConnection(Map<String, Object> responseData) {
+               String successMsg = "ConnectionTest Successful";
                try {
                        getCollectionList(null);
                        // If it doesn't throw exception, then assume the 
instance is
                        // reachable
-                       String successMsg = "ConnectionTest Successful";
-                       BaseClient.generateResponseDataMap(true, successMsg,
-                                       successMsg, null, null, responseData);
-               } catch (IOException e) {
+                       BaseClient.generateResponseDataMap(true, successMsg, 
successMsg, null, null, responseData);
+               } catch (Exception e) {
                        LOG.error("Error connecting to Solr. solrClient=" + 
solrClient, e);
-                       String failureMsg = "Unable to connect to Solr 
instance."
-                                       + e.getMessage();
-                       BaseClient.generateResponseDataMap(false, failureMsg,
-                                       failureMsg + errMsg, null, null, 
responseData);
-
+                       String failureMsg = "Unable to connect to Solr 
instance." + e.getMessage();
+                       BaseClient.generateResponseDataMap(false, failureMsg, 
failureMsg + errMessage, null, null, responseData);
                }
-
-               return responseData;
        }
 
-       public List<String> getCollectionList(List<String> ignoreCollectionList)
+       private List<String> getCollectionList(List<String> 
ignoreCollectionList)
                        throws Exception {
                if (!isSolrCloud) {
                        return getCoresList(ignoreCollectionList);
@@ -105,11 +136,10 @@ public class ServiceSolrClient {
 
                CollectionAdminRequest<?> request = new 
CollectionAdminRequest.List();
                String decPassword = getDecryptedPassword();
-        if (username != null && decPassword != null) {
+        if (!this.isKerberosAuth && username != null && decPassword != null) {
                    request.setBasicAuthCredentials(username, decPassword);
                }
                SolrResponse response = request.process(solrClient);
-
                List<String> list = new ArrayList<String>();
                List<String> responseCollectionList = 
(ArrayList<String>)response.getResponse().get("collections");
                if(CollectionUtils.isEmpty(responseCollectionList)) {
@@ -124,12 +154,12 @@ public class ServiceSolrClient {
                return list;
        }
 
-       public List<String> getCoresList(List<String> ignoreCollectionList)
+       private List<String> getCoresList(List<String> ignoreCollectionList)
                        throws Exception {
                CoreAdminRequest request = new CoreAdminRequest();
                request.setAction(CoreAdminAction.STATUS);
                String decPassword = getDecryptedPassword();
-        if (username != null && decPassword != null) {
+        if (!this.isKerberosAuth && username != null && decPassword != null) {
                    request.setBasicAuthCredentials(username, decPassword);
                }
                CoreAdminResponse cores = request.process(solrClient);
@@ -145,7 +175,7 @@ public class ServiceSolrClient {
                return coreList;
        }
 
-       public List<String> getFieldList(String collection,
+       private List<String> getFieldList(String collection,
                        List<String> ignoreFieldList) throws Exception {
                // TODO: Best is to get the collections based on the collection 
value
                // which could contain wild cards
@@ -158,7 +188,7 @@ public class ServiceSolrClient {
                query.setRequestHandler(queryStr);
                QueryRequest req = new QueryRequest(query);
                String decPassword = getDecryptedPassword();
-               if (username != null && decPassword != null) {
+               if (!this.isKerberosAuth && username != null && decPassword != 
null) {
                    req.setBasicAuthCredentials(username, decPassword);
                }
                QueryResponse response = req.process(solrClient);
@@ -182,7 +212,7 @@ public class ServiceSolrClient {
                return fieldList;
        }
 
-       public List<String> getFieldList(List<String> collectionList,
+       private List<String> getFieldList(List<String> collectionList,
                        List<String> ignoreFieldList) throws Exception {
 
                Set<String> fieldSet = new LinkedHashSet<String>();
@@ -232,7 +262,6 @@ public class ServiceSolrClient {
                                break;
                        }
                }
-
                if (userInput != null) {
                        try {
                                Callable<List<String>> callableObj = null;
@@ -248,7 +277,23 @@ public class ServiceSolrClient {
                                                public List<String> call() {
                                                        List<String> retList = 
new ArrayList<String>();
                                                        try {
-                                                               List<String> 
list = getCollectionList(finalCollectionList);
+                                                               List<String> 
list = null;
+                                                               if 
(isKerberosAuth) {
+                                                                       list = 
Subject.doAs(loginSubject, new PrivilegedAction<List<String>>() {
+                                                                               
@Override
+                                                                               
public List<String> run() {
+                                                                               
        List<String> ret = null;
+                                                                               
        try {
+                                                                               
                ret = getCollectionList(finalCollectionList);
+                                                                               
        } catch (Exception e) {
+                                                                               
                LOG.error("Unable to get collections, Error : " + 
e.getMessage(), new Throwable(e));
+                                                                               
        }
+                                                                               
        return ret;
+                                                                               
}
+                                                                       });
+                                                               } else {
+                                                                       list = 
getCollectionList(finalCollectionList);
+                                                               }
                                                                if 
(userInputFinal != null
                                                                                
&& !userInputFinal.isEmpty()) {
                                                                        for 
(String value : list) {
@@ -271,8 +316,23 @@ public class ServiceSolrClient {
                                                public List<String> call() {
                                                        List<String> retList = 
new ArrayList<String>();
                                                        try {
-                                                               List<String> 
list = getFieldList(
-                                                                               
finalCollectionList, finalFieldList);
+                                                               List<String> 
list = null;
+                                                               if 
(isKerberosAuth) {
+                                                                       list = 
Subject.doAs(loginSubject, new PrivilegedAction<List<String>>() {
+                                                                               
@Override
+                                                                               
public List<String> run() {
+                                                                               
        List<String> ret = new ArrayList<String>();
+                                                                               
        try {
+                                                                               
                ret = getFieldList(finalCollectionList, finalFieldList);
+                                                                               
        } catch (Exception e) {
+                                                                               
                LOG.error("Unable to get field list, Error : " + 
e.getMessage(), new Throwable(e));
+                                                                               
        }
+                                                                               
        return ret;
+                                                                               
}
+                                                                       });
+                                                               } else {
+                                                                       list = 
getFieldList(finalCollectionList, finalFieldList);
+                                                               }
                                                                if 
(userInputFinal != null
                                                                                
&& !userInputFinal.isEmpty()) {
                                                                        for 
(String value : list) {
@@ -298,7 +358,7 @@ public class ServiceSolrClient {
                                        }
                                }
                        } catch (Exception e) {
-                               LOG.error("Unable to get hive resources.", e);
+                               LOG.error("Unable to get solr resources.", e);
                        }
                }
 
@@ -320,4 +380,99 @@ public class ServiceSolrClient {
 
         return decryptedPwd;
        }
+
+       private void createSolrClientInstance() {
+               this.setHttpClientBuilderForKrb();
+               if (this.isSolrCloud) {
+                       List<String> zookeeperHosts = Arrays.asList(this.url);
+                       this.solrClient = new 
CloudSolrClient.Builder(zookeeperHosts, Optional.empty()).build();
+               } else {
+                       HttpSolrClient.Builder builder = new 
HttpSolrClient.Builder();
+                       builder.withBaseSolrUrl(this.url);
+                       this.solrClient = builder.build();
+               }
+       }
+
+       private void setHttpClientBuilderForKrb() {
+               if (this.isKerberosAuth) {
+                       Krb5HttpClientBuilder krbBuild = new 
Krb5HttpClientBuilder();
+                       SolrHttpClientBuilder kb = krbBuild.getBuilder();
+                       HttpClientUtil.setHttpClientBuilder(kb);
+               }
+       }
+
+       private void login(Map<String, String> configs) {
+               try {
+                       String adminPrincipal = 
configs.get(HadoopConfigHolder.RANGER_PRINCIPAL);
+                       String adminKeytab = 
configs.get(HadoopConfigHolder.RANGER_KEYTAB);
+                       String nameRules = 
configs.get(HadoopConfigHolder.RANGER_NAME_RULES);
+                       if (StringUtils.isEmpty(nameRules)) {
+                               if (LOG.isDebugEnabled()) {
+                                       LOG.debug("Name Rule is empty. Setting 
Name Rule as 'DEFAULT'");
+                               }
+                               nameRules = "DEFAULT";
+                       }
+                       String userName = this.username;
+                       if (StringUtils.isEmpty(adminPrincipal) || 
StringUtils.isEmpty(adminKeytab)) {
+                               if (userName == null) {
+                                       throw createException("Unable to find 
login username for hadoop environment, [" + serviceName + "]", null);
+                               }
+                               String keyTabFile = 
configs.get(HadoopConfigHolder.RANGER_KEYTAB);
+                               if (keyTabFile != null) {
+                                       if (this.isKerberosAuth) {
+                                               LOG.info("Init Login: security 
enabled, using username/keytab");
+                                               this.loginSubject = 
SecureClientLogin.loginUserFromKeytab(userName, keyTabFile, nameRules);
+                                       } else {
+                                               LOG.info("Init Login: using 
username");
+                                               this.loginSubject = 
SecureClientLogin.login(userName);
+                                       }
+                               } else {
+                                       String encryptedPwd = this.password;
+                                       String password = null;
+                                       if (encryptedPwd != null) {
+                                               try {
+                                                       password = 
PasswordUtils.decryptPassword(encryptedPwd);
+                                               } catch (Exception ex) {
+                                                       LOG.info("Password 
decryption failed; trying connection with received password string");
+                                                       password = null;
+                                               } finally {
+                                                       if (password == null) {
+                                                               password = 
encryptedPwd;
+                                                       }
+                                               }
+                                       } else {
+                                               LOG.info("Password decryption 
failed: no password was configured");
+                                       }
+                                       if (this.isKerberosAuth) {
+                                               LOG.info("Init Login: using 
username/password");
+                                               this.loginSubject = 
SecureClientLogin.loginUserWithPassword(userName, password);
+                                       } else {
+                                               LOG.info("Init Login: security 
not enabled, using username");
+                                               this.loginSubject = 
SecureClientLogin.login(userName);
+                                       }
+                               }
+                       } else {
+                               if (this.isKerberosAuth) {
+                                       LOG.info("Init Lookup Login: security 
enabled, using lookupPrincipal/lookupKeytab");
+                                       this.loginSubject = 
SecureClientLogin.loginUserFromKeytab(adminPrincipal, adminKeytab, nameRules);
+                               } else {
+                                       LOG.info("Init Login: security not 
enabled, using username");
+                                       this.loginSubject = 
SecureClientLogin.login(userName);
+                               }
+                       }
+               } catch (IOException ioe) {
+                       throw createException("Unable to login to Hadoop 
environment [" + serviceName + "]", ioe);
+               } catch (SecurityException se) {
+                       throw createException("Unable to login to Hadoop 
environment [" + serviceName + "]", se);
+               }
+       }
+
+       private HadoopException createException(String msgDesc, Exception exp) {
+               HadoopException hdpException = new HadoopException(msgDesc, 
exp);
+               final String fullDescription = exp != null ? 
BaseClient.getMessage(exp) : msgDesc;
+               hdpException.generateResponseDataMap(false, fullDescription + 
errMessage,
+                       msgDesc + errMessage, null, null);
+               return hdpException;
+       }
+
 }
diff --git 
a/plugin-solr/src/main/java/org/apache/ranger/services/solr/client/ServiceSolrConnectionMgr.java
 
b/plugin-solr/src/main/java/org/apache/ranger/services/solr/client/ServiceSolrConnectionMgr.java
index f56373b..f9aeca9 100644
--- 
a/plugin-solr/src/main/java/org/apache/ranger/services/solr/client/ServiceSolrConnectionMgr.java
+++ 
b/plugin-solr/src/main/java/org/apache/ranger/services/solr/client/ServiceSolrConnectionMgr.java
@@ -21,26 +21,23 @@ package org.apache.ranger.services.solr.client;
 
 import java.util.Map;
 
-import org.apache.solr.client.solrj.SolrClient;
-import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.commons.lang.StringUtils;
 
 public class ServiceSolrConnectionMgr {
 
+       private static final String SOLR_ZOOKEEPER_QUORUM = 
"solr.zookeeper.quorum";
+       private static final String SOLR_URL = "solr.url";
+
        static public ServiceSolrClient getSolrClient(String serviceName,
                        Map<String, String> configs) throws Exception {
-               String url = configs.get("solr.url");
-               if (url != null) {
-                       //TODO: Determine whether the instance is SolrCloud
-                       boolean isSolrCloud = true;
-                       HttpSolrClient.Builder builder = new 
HttpSolrClient.Builder();
-                       builder.withBaseSolrUrl(url);
-                       SolrClient solrClient = builder.build();
-                       ServiceSolrClient serviceSolrClient = new 
ServiceSolrClient(
-                                       solrClient, isSolrCloud, configs);
+               String solr_url = configs.get(SOLR_URL);
+               String zk_url = configs.get(SOLR_ZOOKEEPER_QUORUM);
+               if (solr_url != null || zk_url != null) {
+                       final boolean isSolrCloud = 
StringUtils.isNotEmpty(zk_url);
+                       final String url = isSolrCloud ? zk_url : solr_url;
+                       ServiceSolrClient serviceSolrClient = new 
ServiceSolrClient(serviceName, configs, url, isSolrCloud);
                        return serviceSolrClient;
                }
-               // TODO: Need to add method to create SolrClient using 
ZooKeeper for
-               // SolrCloud
                throw new Exception("Required properties are not set for "
                                + serviceName + ". URL or Zookeeper information 
not provided.");
        }

Reply via email to