This is an automated email from the ASF dual-hosted git repository. rajeshbabu pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/phoenix-omid.git
The following commit(s) were added to refs/heads/master by this push: new 86dcf1e OMID-194 OmidTableManager cannot create commit and timestamp tables in kerberos cluster(Rajeshbabu) 86dcf1e is described below commit 86dcf1e1d0d177af217838be7d951b58d783034d Author: Rajeshbabu Chintaguntla <rajeshb...@apache.org> AuthorDate: Tue Feb 9 10:38:45 2021 +0530 OMID-194 OmidTableManager cannot create commit and timestamp tables in kerberos cluster(Rajeshbabu) --- .../org/apache/omid/tools/hbase/HBaseLogin.java | 90 +++++++++++++++++++--- .../apache/omid/tools/hbase/OmidTableManager.java | 7 +- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/hbase-common/src/main/java/org/apache/omid/tools/hbase/HBaseLogin.java b/hbase-common/src/main/java/org/apache/omid/tools/hbase/HBaseLogin.java index 92b4904..0241fc0 100644 --- a/hbase-common/src/main/java/org/apache/omid/tools/hbase/HBaseLogin.java +++ b/hbase-common/src/main/java/org/apache/omid/tools/hbase/HBaseLogin.java @@ -17,7 +17,11 @@ */ package org.apache.omid.tools.hbase; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.authentication.util.KerberosUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,22 +33,38 @@ public final class HBaseLogin { private static final Logger LOG = LoggerFactory.getLogger(HBaseLogin.class); private static volatile UserGroupInformation ugi; + private static final Object KERBEROS_LOGIN_LOCK = new Object(); @Nullable public static UserGroupInformation loginIfNeeded(SecureHBaseConfig config) throws IOException { + return loginIfNeeded(config, null); + } - if (UserGroupInformation.isSecurityEnabled()) { - LOG.info("Security enabled when connecting to HBase"); - if (ugi == null) { // Use lazy initialization with double-checked locking - synchronized (HBaseLogin.class) { - if (ugi == null) { - LOG.info("Login with Kerberos. User={}, keytab={}", config.getPrincipal(), config.getKeytab()); - UserGroupInformation.loginUserFromKeytab(config.getPrincipal(), config.getKeytab()); - ugi = UserGroupInformation.getCurrentUser(); + @Nullable + public static UserGroupInformation loginIfNeeded(SecureHBaseConfig config, Configuration hbaseConf) throws IOException { + boolean credsProvided = null != config.getPrincipal() && null != config.getKeytab(); + if (UserGroupInformation.isSecurityEnabled() && credsProvided) { + // Check if we need to authenticate with kerberos so that we cache the correct ConnectionInfo + UserGroupInformation currentUser = UserGroupInformation.getCurrentUser(); + if (!currentUser.hasKerberosCredentials() || !isSameName(currentUser.getUserName(), config.getPrincipal())) { + synchronized (KERBEROS_LOGIN_LOCK) { + // Double check the current user, might have changed since we checked last. Don't want + // to re-login if it's the same user. + currentUser = UserGroupInformation.getCurrentUser(); + if (!currentUser.hasKerberosCredentials() || !isSameName(currentUser.getUserName(), config.getPrincipal())) { + final Configuration hbaseConfig = getConfiguration(hbaseConf, config.getPrincipal(), config.getKeytab()); + LOG.info("Trying to connect to a secure cluster as {} " + + "with keytab {}", + hbaseConfig.get(SecureHBaseConfig.HBASE_CLIENT_PRINCIPAL_KEY), + hbaseConfig.get(SecureHBaseConfig.HBASE_CLIENT_KEYTAB_KEY)); + UserGroupInformation.setConfiguration(hbaseConfig); + User.login(hbaseConfig, SecureHBaseConfig.HBASE_CLIENT_KEYTAB_KEY, SecureHBaseConfig.HBASE_CLIENT_PRINCIPAL_KEY, null); + LOG.info("Successful login to secure cluster"); } } } else { - LOG.info("User {}, already trusted (Kerberos). Avoiding 2nd login as it causes problems", ugi.toString()); + // The user already has Kerberos creds, so there isn't anything to change in the ConnectionInfo. + LOG.debug("Already logged in as {}", currentUser); } } else { LOG.warn("Security NOT enabled when connecting to HBase. Act at your own risk. NULL UGI returned"); @@ -52,4 +72,56 @@ public final class HBaseLogin { return ugi; } + static boolean isSameName(String currentName, String newName, String hostname, String defaultRealm) throws IOException { + final boolean newNameContainsRealm = newName.indexOf('@') != -1; + // Make sure to replace "_HOST" if it exists before comparing the principals. + if (newName.contains(org.apache.hadoop.security.SecurityUtil.HOSTNAME_PATTERN)) { + if (newNameContainsRealm) { + newName = org.apache.hadoop.security.SecurityUtil.getServerPrincipal(newName, hostname); + } else { + // If the principal ends with "/_HOST", replace "_HOST" with the hostname. + if (newName.endsWith("/_HOST")) { + newName = newName.substring(0, newName.length() - 5) + hostname; + } + } + } + // The new name doesn't contain a realm and we could compute a default realm + if (!newNameContainsRealm && defaultRealm != null) { + return currentName.equals(newName + "@" + defaultRealm); + } + // We expect both names to contain a realm, so we can do a simple equality check + return currentName.equals(newName); + } + + static boolean isSameName(String currentName, String newName) throws IOException { + return isSameName(currentName, newName, null, getDefaultKerberosRealm()); + } + + /** + * Computes the default kerberos realm if one is available. If one cannot be computed, null + * is returned. + * + * @return The default kerberos realm, or null. + */ + static String getDefaultKerberosRealm() { + try { + return KerberosUtil.getDefaultRealm(); + } catch (Exception e) { + return null; + } + } + + private static Configuration getConfiguration(Configuration conf, String principal, String keytab) { + if(conf == null) { + conf = HBaseConfiguration.create(); + } + // Set the principal and keytab if provided from the URL (overriding those provided in Properties) + if (null != principal) { + conf.set(SecureHBaseConfig.HBASE_CLIENT_PRINCIPAL_KEY, principal); + } + if (null != keytab) { + conf.set(SecureHBaseConfig.HBASE_CLIENT_KEYTAB_KEY, keytab); + } + return conf; + } } diff --git a/hbase-tools/src/main/java/org/apache/omid/tools/hbase/OmidTableManager.java b/hbase-tools/src/main/java/org/apache/omid/tools/hbase/OmidTableManager.java index 8e25530..104f2e8 100644 --- a/hbase-tools/src/main/java/org/apache/omid/tools/hbase/OmidTableManager.java +++ b/hbase-tools/src/main/java/org/apache/omid/tools/hbase/OmidTableManager.java @@ -78,8 +78,11 @@ public class OmidTableManager { } public void executeActionsOnHBase(Configuration hbaseConf) throws IOException { - - HBaseLogin.loginIfNeeded(mainConfig.loginFlags); + mainConfig.loginFlags.setPrincipal( + hbaseConf.get(SecureHBaseConfig.HBASE_CLIENT_PRINCIPAL_KEY)); + mainConfig.loginFlags.setKeytab( + hbaseConf.get(SecureHBaseConfig.HBASE_CLIENT_KEYTAB_KEY)); + HBaseLogin.loginIfNeeded(mainConfig.loginFlags, hbaseConf); try (Connection conn = ConnectionFactory.createConnection(hbaseConf); Admin hBaseAdmin = conn.getAdmin()) {