Как я могу получить соединение HBase в улье UDF с Kerberos? - PullRequest
0 голосов
/ 18 июня 2019

Я хочу написать UDF, чтобы получить что-то от HBase, я использую это для установки токена в hiveconf, но я не могу подключиться к HBase с помощью hiveconf, он выдаст NullPointException

Я пробовал много способов, вот так: https://www.programcreek.com/java-api-examples/index.php?api=org.apache.hadoop.hbase.security.token.TokenUtil

но все равно выдается исключение NullPointException

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.apache.hadoop.hbase.client.Connection;

import org.apache.hadoop.hbase.client.ConnectionFactory;

import org.apache.hadoop.hbase.security.User;

import org.apache.hadoop.hbase.security.token.AuthenticationTokenIdentifier;

import org.apache.hadoop.hbase.security.token.TokenUtil;

import org.apache.hadoop.hive.conf.HiveConf;

import org.apache.hadoop.hive.ql.hooks.ExecuteWithHookContext;

import org.apache.hadoop.hive.ql.hooks.HookContext;

import org.apache.hadoop.security.UserGroupInformation;

import org.apache.hadoop.security.token.Token;

public class HbaseTokenFetcherHook implements ExecuteWithHookContext{   

    private static final Log LOG = LogFactory.getLog(HbaseTokenFetcherHook.class);

    @Override

    public void run(HookContext hookContext) throws Exception {

          HiveConf hiveConf = hookContext.getConf();

          /* If required */

          hiveConf.set(“zookeeper.znode.parent”, "/hbase-secure");   

          try {               

               UserGroupInformation.setConfiguration(hiveConf);

               Connection tokenConnection = ConnectionFactory.createConnection(hiveConf);

               Token<AuthenticationTokenIdentifier> token = TokenUtil.obtainToken(tokenConnection, User.getCurrent());

               String urlString = token.encodeToUrlString();

               hiveConf.set(“HBASE_AUTH_TOKEN”, urlString);

          } catch (IOException | InterruptedException e) {

               LOG.error("Error while fetching token for hbase"

                         + e.getMessage(), e);

          }

     }

}

выдается исключение в:

Token<AuthenticationTokenIdentifier> token = TokenUtil.obtainToken(tokenConnection, User.getCurrent());

Сообщение об ошибке: вызвано: java.lang.NullPointException atorg.apache.hadoop.hbase.zookeeper.

Ответы [ 2 ]

0 голосов
/ 19 июня 2019

Чтобы получить объект конфигурации, инициализированный с помощью UserGroupInformation (проверьте this ), вам может потребоваться предоставить гораздо больше информации. Вы можете подумать, что hiveConf, полученный из hookContext.getConf, должен иметь всю необходимую Kerberos конфигурацию, но это не так. Возможно, этот код может дать вам подсказку:

import javax.security.auth.login.AppConfigurationEntry;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.security.UserGroupInformation;

public String obtainHBASEDataWithKerberos(String key, String namespace, String tableName, String family, String qualifier) {
    try {
        Configuration conf = HBaseConfiguration.create();
        conf.set("hbase.zookeeper.quorum", "node1:2181, node2:2181, node3:2181");
        conf.set("hadoop.security.authentication","Kerberos");
        System.setProperty("javax.security.auth.useSubjectCredsOnly","false"); // https://stackoverflow.com/questions/33829017/gssexception-no-valid-credentials-provided-mechanism-level-failed-to-find-any
        conf.set("hbase.zookeeper.property.clientPort","2181");
        conf.set("hbase.cluster.distributed","true");       
        conf.set("zookeeper.znode.parent","/hbase-secure");
        conf.set("hbase.security.authentication", "Kerberos");
        UserGroupInformation.setConfiguration(conf);
        UserGroupInformation.loginUserFromSubject(null);
        UserGroupInformation ugi=UserGroupInformation.getLoginUser();
        String kerberos_principal=ugi.getUserName();
        if (kerberos_principal!=null) {
            if (kerberos_principal.contains("@")) {
                String domain=kerberos_principal.split("@")[1];
                conf.set("hbase.master.kerberos.principal", "hbase/_HOST@"+domain);
                conf.set("hbase.regionserver.kerberos.principal", "hbase/_HOST@"+domain);
            }
            // Create in-memory jaas file
            // Create HBASE entry options.
            HashMap<String, Object> hbase_options = new HashMap<String, Object>();
            hbase_options.put("doNotPrompt", "true");
            hbase_options.put("useTicketCache", "true");
            hbase_options.put("principal",kerberos_principal);
            hbase_options.put("storeKey","true");
            hbase_options.put("debug","true");

            // Create entries.
            final AppConfigurationEntry[] hbase_entries = {
                    new AppConfigurationEntry(
                            "com.sun.security.auth.module.Krb5LoginModule",
                            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
                            hbase_options)
            };

            // Create configuration.
            javax.security.auth.login.Configuration jaasConfig = new javax.security.auth.login.Configuration() {
                @Override
                public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                    if ("Client".equals(name)) {
                        return hbase_entries;
                    }
                    else return null;
                }
            };

            javax.security.auth.login.Configuration.setConfiguration(jaasConfig);
            UserGroupInformation.setConfiguration(conf);

            Connection conn = null;
            Table table = null;

            conn=CentralKerberosUGI.getHBaseConnection();
            table = conn.getTable(TableName.valueOf(namespace + ":" + tableName));
            Result result = table.get(new Get(key.getBytes()));
            byte[] value = result.getValue(Bytes.toBytes(family), Bytes.toBytes(qualifier));
            return Bytes.toString(value);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
0 голосов
/ 18 июня 2019

Попробуйте Прополис UDF сторонних разработчиков Hive, он имеет различные функции HBase get для получения значения или всей семьи.Инструкции по сборке и использованию содержатся в README, для получения дополнительной информации о конкретном типе UDF describe и имени функции.Я протестировал его на кластере Hadoop с Kerberos, и он работал нормально.

...