You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by ta...@apache.org on 2016/05/12 22:10:15 UTC

[40/50] [abbrv] incubator-impala git commit: IMPALA-2660: Respect auth_to_local configs from hdfs configs

IMPALA-2660: Respect auth_to_local configs from hdfs configs

This patch implements a new feature to read the auth_to_local
configs from hdfs configuration files, using the parameter
hadoop.security.auth_to_local. This is done by modifying the
User#getShortName() method to use its hdfs equivalent.

This patch includes an end to end authorization test using
sentry where we add specific auth_to_local setting for a certain
user and test if the sentry authorization passes for this user
after applying these rules. Given we don't have tests that run
on a kerberized min-cluster, this patch adds a hack to load this
configuration during even on non-kerberized 'test runs'.

However this feature is disabled by default to preserve the
existing behavior. To enable it,

1. Use kerberos as authentication mechanism (by setting --principal) and
2. Add "--load_auth_to_local_rules=true" to the cluster startup args

Change-Id: I76485b83c14ba26f6fce66e5f83e8014667829e0
Reviewed-on: http://gerrit.cloudera.org:8080/2800
Reviewed-by: Bharath Vissapragada <bh...@cloudera.com>
Tested-by: Internal Jenkins


Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/3092c966
Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/3092c966
Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/3092c966

Branch: refs/heads/master
Commit: 3092c96619f54bd47d71c2bc19c99bb03807ec1a
Parents: c0ee93b
Author: Bharath Vissapragada <bh...@cloudera.com>
Authored: Fri Mar 4 09:46:16 2016 -0800
Committer: Tim Armstrong <ta...@cloudera.com>
Committed: Thu May 12 14:18:01 2016 -0700

----------------------------------------------------------------------
 be/src/catalog/catalog.cc                       |  11 +-
 be/src/common/global-flags.cc                   |   5 +
 be/src/service/frontend.cc                      |   9 +-
 .../impala/analysis/AnalysisContext.java        |   9 +-
 .../impala/analysis/ShowGrantRoleStmt.java      |   3 +-
 .../cloudera/impala/analysis/ShowRolesStmt.java |   5 +-
 .../authorization/AuthorizationChecker.java     |   8 +-
 .../com/cloudera/impala/authorization/User.java |  81 +++++++--
 .../cloudera/impala/service/BackendConfig.java  |  11 +-
 .../com/cloudera/impala/service/Frontend.java   |   9 +-
 .../com/cloudera/impala/service/JniCatalog.java |   6 +-
 .../cloudera/impala/service/JniFrontend.java    |   4 +-
 .../impala/util/RequestPoolService.java         |  10 +-
 .../cloudera/impala/analysis/AuditingTest.java  |   3 +-
 .../impala/analysis/AuthorizationTest.java      | 165 ++++++++++++++-----
 .../impala/util/TestRequestPoolService.java     |   4 +-
 fe/src/test/resources/authz-policy.ini.template |   3 +
 .../common/etc/hadoop/conf/core-site.xml.tmpl   |  11 ++
 18 files changed, 277 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/be/src/catalog/catalog.cc
----------------------------------------------------------------------
diff --git a/be/src/catalog/catalog.cc b/be/src/catalog/catalog.cc
index 606aa8f..26810f1 100644
--- a/be/src/catalog/catalog.cc
+++ b/be/src/catalog/catalog.cc
@@ -25,6 +25,9 @@
 
 using namespace impala;
 
+DECLARE_bool(load_auth_to_local_rules);
+DECLARE_string(principal);
+
 DEFINE_bool(load_catalog_in_background, false,
     "If true, loads catalog metadata in the background. If false, metadata is loaded "
     "lazily (on access).");
@@ -38,7 +41,7 @@ DECLARE_int32(non_impala_java_vlog);
 
 Catalog::Catalog() {
   JniMethodDescriptor methods[] = {
-    {"<init>", "(ZILjava/lang/String;II)V", &catalog_ctor_},
+    {"<init>", "(ZILjava/lang/String;IIZ)V", &catalog_ctor_},
     {"updateCatalog", "([B)[B", &update_metastore_id_},
     {"execDdl", "([B)[B", &exec_ddl_id_},
     {"resetMetadata", "([B)[B", &reset_metadata_id_},
@@ -64,9 +67,13 @@ Catalog::Catalog() {
   jboolean load_in_background = FLAGS_load_catalog_in_background;
   jint num_metadata_loading_threads = FLAGS_num_metadata_loading_threads;
   jstring sentry_config = jni_env->NewStringUTF(FLAGS_sentry_config.c_str());
+  // auth_to_local rules are read if --load_auth_to_local_rules is set to true
+  // and impala is kerberized.
+  jboolean auth_to_local = FLAGS_load_auth_to_local_rules && !FLAGS_principal.empty();
   jobject catalog = jni_env->NewObject(catalog_class_, catalog_ctor_,
       load_in_background, num_metadata_loading_threads, sentry_config,
-      FlagToTLogLevel(FLAGS_v), FlagToTLogLevel(FLAGS_non_impala_java_vlog));
+      FlagToTLogLevel(FLAGS_v), FlagToTLogLevel(FLAGS_non_impala_java_vlog),
+      auth_to_local);
   EXIT_IF_EXC(jni_env);
   ABORT_IF_ERROR(JniUtil::LocalToGlobalRef(jni_env, catalog, &catalog_));
 }

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/be/src/common/global-flags.cc
----------------------------------------------------------------------
diff --git a/be/src/common/global-flags.cc b/be/src/common/global-flags.cc
index f0315ca..b3f83d9 100644
--- a/be/src/common/global-flags.cc
+++ b/be/src/common/global-flags.cc
@@ -76,6 +76,11 @@ DEFINE_string(minidump_path, "/tmp/impala-minidumps", "Directory to write minidu
 DEFINE_int32(max_minidumps, 9, "Maximum number of minidump files to keep per daemon. "
     "Older files are removed first. Set to 0 to keep all minidump files.");
 
+DEFINE_bool(load_auth_to_local_rules, false, "If true, load auth_to_local configuration "
+    "from hdfs' core-site.xml. When enabled, impalad reads the rules from the property "
+    "hadoop.security.auth_to_local and applies them to translate the Kerberos principal "
+    "to its corresponding local user name for authorization.");
+
 // Stress option for testing failed memory allocation. Debug builds only.
 #ifndef NDEBUG
 DEFINE_int32(stress_free_pool_alloc, 0, "A stress option which causes memory allocations "

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/be/src/service/frontend.cc
----------------------------------------------------------------------
diff --git a/be/src/service/frontend.cc b/be/src/service/frontend.cc
index a0b76c3..2b7c5b0 100644
--- a/be/src/service/frontend.cc
+++ b/be/src/service/frontend.cc
@@ -28,6 +28,8 @@ using namespace impala;
 
 DECLARE_string(sentry_config);
 DECLARE_int32(non_impala_java_vlog);
+DECLARE_bool(load_auth_to_local_rules);
+DECLARE_string(principal);
 
 DEFINE_bool(load_catalog_at_startup, false, "if true, load all catalog data at startup");
 
@@ -56,7 +58,7 @@ DEFINE_string(authorized_proxy_user_config_delimiter, ",",
 Frontend::Frontend() {
   JniMethodDescriptor methods[] = {
     {"<init>", "(ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;"
-        "Ljava/lang/String;II)V", &fe_ctor_},
+        "Ljava/lang/String;IIZ)V", &fe_ctor_},
     {"createExecRequest", "([B)[B", &create_exec_request_id_},
     {"getExplainPlan", "([B)Ljava/lang/String;", &get_explain_plan_id_},
     {"getHadoopConfig", "([B)[B", &get_hadoop_config_id_},
@@ -101,9 +103,12 @@ Frontend::Frontend() {
       jni_env->NewStringUTF(FLAGS_sentry_config.c_str());
   jstring auth_provider_class =
       jni_env->NewStringUTF(FLAGS_authorization_policy_provider_class.c_str());
+  // auth_to_local rules are read if --load_auth_to_local_rules is set to true
+  // and impala is kerberized.
+  jboolean auth_to_local = FLAGS_load_auth_to_local_rules && !FLAGS_principal.empty();
   jobject fe = jni_env->NewObject(fe_class_, fe_ctor_, lazy, server_name,
       policy_file_path, sentry_config, auth_provider_class, FlagToTLogLevel(FLAGS_v),
-      FlagToTLogLevel(FLAGS_non_impala_java_vlog));
+      FlagToTLogLevel(FLAGS_non_impala_java_vlog), auth_to_local);
   EXIT_IF_EXC(jni_env);
   ABORT_IF_ERROR(JniUtil::LocalToGlobalRef(jni_env, fe, &fe_));
 }

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/analysis/AnalysisContext.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AnalysisContext.java b/fe/src/main/java/com/cloudera/impala/analysis/AnalysisContext.java
index 31c156c..098501c 100644
--- a/fe/src/main/java/com/cloudera/impala/analysis/AnalysisContext.java
+++ b/fe/src/main/java/com/cloudera/impala/analysis/AnalysisContext.java
@@ -32,6 +32,7 @@ import com.cloudera.impala.catalog.AuthorizationException;
 import com.cloudera.impala.catalog.Db;
 import com.cloudera.impala.catalog.ImpaladCatalog;
 import com.cloudera.impala.common.AnalysisException;
+import com.cloudera.impala.common.InternalException;
 import com.cloudera.impala.common.Pair;
 import com.cloudera.impala.thrift.TAccessEvent;
 import com.cloudera.impala.thrift.TLineageGraph;
@@ -384,7 +385,8 @@ public class AnalysisContext {
    * analyze() must have already been called. Throws an AuthorizationException if the
    * user doesn't have sufficient privileges to run this statement.
    */
-  public void authorize(AuthorizationChecker authzChecker) throws AuthorizationException {
+  public void authorize(AuthorizationChecker authzChecker)
+      throws AuthorizationException, InternalException {
     Preconditions.checkNotNull(analysisResult_);
     Analyzer analyzer = getAnalyzer();
     // Process statements for which column-level privilege requests may be registered.
@@ -451,7 +453,7 @@ public class AnalysisContext {
    * this request. Also, checks if the request references a system database.
    */
   private void authorizePrivilegeRequest(AuthorizationChecker authzChecker,
-    PrivilegeRequest request) throws AuthorizationException {
+    PrivilegeRequest request) throws AuthorizationException, InternalException {
     Preconditions.checkNotNull(request);
     String dbName = null;
     if (request.getAuthorizeable() != null) {
@@ -474,7 +476,8 @@ public class AnalysisContext {
    * sufficient privileges.
    */
   private void authorizeTableAccess(AuthorizationChecker authzChecker,
-      List<PrivilegeRequest> requests) throws AuthorizationException {
+      List<PrivilegeRequest> requests)
+      throws AuthorizationException, InternalException {
     Preconditions.checkState(!requests.isEmpty());
     Analyzer analyzer = getAnalyzer();
     boolean hasTableSelectPriv = true;

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/analysis/ShowGrantRoleStmt.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/analysis/ShowGrantRoleStmt.java b/fe/src/main/java/com/cloudera/impala/analysis/ShowGrantRoleStmt.java
index b543a57..1d921c8 100644
--- a/fe/src/main/java/com/cloudera/impala/analysis/ShowGrantRoleStmt.java
+++ b/fe/src/main/java/com/cloudera/impala/analysis/ShowGrantRoleStmt.java
@@ -16,6 +16,7 @@ package com.cloudera.impala.analysis;
 
 import com.cloudera.impala.catalog.Role;
 import com.cloudera.impala.common.AnalysisException;
+import com.cloudera.impala.common.InternalException;
 import com.cloudera.impala.thrift.TShowGrantRoleParams;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
@@ -36,7 +37,7 @@ public class ShowGrantRoleStmt extends AuthorizationStmt {
     privilegeSpec_ = privilegeSpec;
   }
 
-  public TShowGrantRoleParams toThrift() {
+  public TShowGrantRoleParams toThrift() throws InternalException {
     TShowGrantRoleParams params = new TShowGrantRoleParams();
     params.setRole_name(roleName_);
     params.setRequesting_user(requestingUser_.getShortName());

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/analysis/ShowRolesStmt.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/analysis/ShowRolesStmt.java b/fe/src/main/java/com/cloudera/impala/analysis/ShowRolesStmt.java
index 54ad698..1e1b59e 100644
--- a/fe/src/main/java/com/cloudera/impala/analysis/ShowRolesStmt.java
+++ b/fe/src/main/java/com/cloudera/impala/analysis/ShowRolesStmt.java
@@ -16,6 +16,7 @@ package com.cloudera.impala.analysis;
 
 import com.cloudera.impala.authorization.User;
 import com.cloudera.impala.common.AnalysisException;
+import com.cloudera.impala.common.InternalException;
 import com.cloudera.impala.thrift.TShowRolesParams;
 import com.google.common.base.Preconditions;
 
@@ -50,7 +51,7 @@ public class ShowRolesStmt extends AuthorizationStmt {
     }
   }
 
-  public TShowRolesParams toThrift() {
+  public TShowRolesParams toThrift() throws InternalException {
     TShowRolesParams params = new TShowRolesParams();
     params.setRequesting_user(requestingUser_.getShortName());
     params.setIs_show_current_roles(isShowCurrentRoles_);
@@ -65,4 +66,4 @@ public class ShowRolesStmt extends AuthorizationStmt {
     super.analyze(analyzer);
     requestingUser_ = analyzer.getUser();
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/authorization/AuthorizationChecker.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/authorization/AuthorizationChecker.java b/fe/src/main/java/com/cloudera/impala/authorization/AuthorizationChecker.java
index 6d978ab..a4a45ed 100644
--- a/fe/src/main/java/com/cloudera/impala/authorization/AuthorizationChecker.java
+++ b/fe/src/main/java/com/cloudera/impala/authorization/AuthorizationChecker.java
@@ -32,6 +32,7 @@ import org.apache.sentry.provider.file.SimpleFileProviderBackend;
 
 import com.cloudera.impala.catalog.AuthorizationException;
 import com.cloudera.impala.catalog.AuthorizationPolicy;
+import com.cloudera.impala.common.InternalException;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 
@@ -108,7 +109,7 @@ public class AuthorizationChecker {
    * that is in the AuthorizationProvider to properly resolve Hadoop groups or
    * local group mappings.
    */
-  public Set<String> getUserGroups(User user) {
+  public Set<String> getUserGroups(User user) throws InternalException {
     return provider_.getGroupMapping().getGroups(user.getShortName());
   }
 
@@ -117,7 +118,7 @@ public class AuthorizationChecker {
    * the user does not have sufficient privileges.
    */
   public void checkAccess(User user, PrivilegeRequest privilegeRequest)
-      throws AuthorizationException {
+      throws AuthorizationException, InternalException {
     Preconditions.checkNotNull(privilegeRequest);
 
     if (!hasAccess(user, privilegeRequest)) {
@@ -145,7 +146,8 @@ public class AuthorizationChecker {
    * Returns true if the given user has permission to execute the given
    * request, false otherwise. Always returns true if authorization is disabled.
    */
-  public boolean hasAccess(User user, PrivilegeRequest request) {
+  public boolean hasAccess(User user, PrivilegeRequest request)
+      throws InternalException {
     Preconditions.checkNotNull(user);
     Preconditions.checkNotNull(request);
 

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/authorization/User.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/authorization/User.java b/fe/src/main/java/com/cloudera/impala/authorization/User.java
index 4f19813..d87944c 100644
--- a/fe/src/main/java/com/cloudera/impala/authorization/User.java
+++ b/fe/src/main/java/com/cloudera/impala/authorization/User.java
@@ -15,34 +15,87 @@
 package com.cloudera.impala.authorization;
 
 import com.google.common.base.Preconditions;
+import com.google.common.annotations.VisibleForTesting;
+import com.cloudera.impala.common.InternalException;
+import com.cloudera.impala.common.RuntimeEnv;
+import com.cloudera.impala.service.BackendConfig;
+
+import java.io.IOException;
+
+import org.apache.hadoop.conf.Configuration;
+import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTH_TO_LOCAL;
+import org.apache.hadoop.security.authentication.util.KerberosName;
 
 /*
  * Class that represents a User of an Impala session.
  */
 public class User {
+
+  static {
+    // If auth_to_local is enabled, we read the configuration hadoop.security.auth_to_local
+    // from core-site.xml and use it for principal to short name conversion. If it is not,
+    // we use the defaultRule ("RULE:[1:$1] RULE:[2:$1]"), which just extracts the user
+    // name from any principal of form a@REALM or a/b@REALM. If auth_to_local is enabled
+    // and hadoop.security.auth_to_local is not specified in the hadoop configs, we use
+    // the "DEFAULT" rule that just extracts the username from any principal in the
+    // cluster's local realm. For more details on principal to short name translation,
+    // refer to org.apache.hadoop.security.KerberosName.
+    final String defaultRule = "RULE:[1:$1] RULE:[2:$1]";
+    final Configuration conf = new Configuration();
+    if (BackendConfig.isAuthToLocalEnabled()) {
+      KerberosName.setRules(conf.get(HADOOP_SECURITY_AUTH_TO_LOCAL, "DEFAULT"));
+    } else {
+      // just extract the simple user name
+      KerberosName.setRules(defaultRule);
+    }
+  }
+
   private final String name_;
 
+  private KerberosName kerberosName_;
+
   public User(String name) {
     Preconditions.checkNotNull(name);
-    this.name_ = name;
+    name_ = name;
+    this.kerberosName_ = new KerberosName(name);
   }
 
   public String getName() { return name_; }
 
+  public String getShortName() throws InternalException {
+    try {
+      return kerberosName_.getShortName();
+    } catch (IOException e) {
+      throw new InternalException(
+          "Error calling getShortName() for user: " + getName(), e);
+    }
+  }
+
   /*
-   * Get the short version of the user name (the user's name up to the first '/' or '@')
-   * from the full principal name.
-   * Similar to: org.apache.hadoop.security.UserGroupInformation.getShortName()
+   * Returns the shortname for the user after applying auth_to_local
+   * rules from string 'rules'. This is exposed for testing purposes only.
+   * Ideally these rules are populated from hdfs configuration files.
    */
-  public String getShortName() {
-    int idx = name_.indexOf('/');
-    int idx2 = name_.indexOf('@');
-    int endIdx = Math.min(idx, idx2);
-    // At least one of them was not found.
-    if (endIdx == -1) endIdx = Math.max(idx,  idx2);
-
-    // If neither are found (or are found at the beginning of the user name),
-    // return the username.
-    return (endIdx <= 0) ? name_ : name_.substring(0, endIdx);
+  @VisibleForTesting
+  public String getShortNameForTesting(String rules) {
+    Preconditions.checkNotNull(rules);
+    Preconditions.checkState(RuntimeEnv.INSTANCE.isTestEnv());
+    String currentRules = KerberosName.getRules();
+    KerberosName.setRules(rules);
+    String shortName = null;
+    try {
+      shortName = getShortName();
+    } catch (InternalException e) {
+      e.printStackTrace();
+    }
+    // reset the rules
+    KerberosName.setRules(currentRules);
+    return shortName;
+  }
+
+  @VisibleForTesting
+  public static void setRulesForTesting(String rules) {
+    Preconditions.checkState(RuntimeEnv.INSTANCE.isTestEnv());
+    KerberosName.setRules(rules);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/service/BackendConfig.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/service/BackendConfig.java b/fe/src/main/java/com/cloudera/impala/service/BackendConfig.java
index 9d743c1..5dd6216 100644
--- a/fe/src/main/java/com/cloudera/impala/service/BackendConfig.java
+++ b/fe/src/main/java/com/cloudera/impala/service/BackendConfig.java
@@ -28,10 +28,19 @@ public class BackendConfig {
   // the default FLAGS_read_size used by the IO manager in the backend.
   private final long READ_SIZE;
 
+  // This is overriden by JniFrontend/JniCatalog classes with user set configuration.
+  // TODO: Read this from backend instead of using static variables.
+  private static boolean allowAuthToLocalRules_ = false;
+
   private BackendConfig() {
     // TODO: Populate these by making calls to the backend instead of default constants.
     READ_SIZE = 8 * 1024 * 1024L;
   }
 
   public long getReadSize() { return READ_SIZE; }
-}
\ No newline at end of file
+
+  public static boolean isAuthToLocalEnabled() { return allowAuthToLocalRules_; }
+  public static void setAuthToLocal(boolean authToLocal) {
+    allowAuthToLocalRules_ = authToLocal;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/service/Frontend.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/service/Frontend.java b/fe/src/main/java/com/cloudera/impala/service/Frontend.java
index fc1f2fc..9288c05 100644
--- a/fe/src/main/java/com/cloudera/impala/service/Frontend.java
+++ b/fe/src/main/java/com/cloudera/impala/service/Frontend.java
@@ -249,7 +249,7 @@ public class Frontend {
    * result argument.
    */
   private void createCatalogOpRequest(AnalysisContext.AnalysisResult analysis,
-      TExecRequest result) {
+      TExecRequest result) throws InternalException {
     TCatalogOpRequest ddl = new TCatalogOpRequest();
     TResultSetMetadata metadata = new TResultSetMetadata();
     if (analysis.isUseStmt()) {
@@ -614,7 +614,7 @@ public class Frontend {
    * the given user. If pattern is null, it matches all columns.
    */
   public List<Column> getColumns(Table table, PatternMatcher columnPattern,
-      User user) {
+      User user) throws InternalException {
     Preconditions.checkNotNull(table);
     List<Column> columns = Lists.newArrayList();
     for (Column column: table.getColumnsInHiveOrder()) {
@@ -635,7 +635,7 @@ public class Frontend {
    * Returns all databases that match the pattern and
    * are accessible to the given user. If pattern is null, matches all dbs.
    */
-  public List<Db> getDbs(String dbPattern, User user) {
+  public List<Db> getDbs(String dbPattern, User user) throws InternalException {
     List<Db> dbs = impaladCatalog_.getDbs(dbPattern);
     // If authorization is enabled, filter out the databases the user does not
     // have permissions on.
@@ -652,7 +652,8 @@ public class Frontend {
   /**
    * Check whether database is accessible to given user.
    */
-  private boolean isAccessibleToUser(Db db, User user) {
+  private boolean isAccessibleToUser(Db db, User user)
+      throws InternalException {
     if (db.getName().toLowerCase().equals(Catalog.DEFAULT_DB.toLowerCase())) {
       // Default DB should always be shown.
       return true;

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/service/JniCatalog.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/service/JniCatalog.java b/fe/src/main/java/com/cloudera/impala/service/JniCatalog.java
index 64efd58..eb3ac92 100644
--- a/fe/src/main/java/com/cloudera/impala/service/JniCatalog.java
+++ b/fe/src/main/java/com/cloudera/impala/service/JniCatalog.java
@@ -33,6 +33,7 @@ import com.cloudera.impala.catalog.Function;
 import com.cloudera.impala.common.ImpalaException;
 import com.cloudera.impala.common.InternalException;
 import com.cloudera.impala.common.JniUtil;
+import com.cloudera.impala.service.BackendConfig;
 import com.cloudera.impala.thrift.TCatalogObject;
 import com.cloudera.impala.thrift.TDatabase;
 import com.cloudera.impala.thrift.TDdlExecRequest;
@@ -75,8 +76,9 @@ public class JniCatalog {
   }
 
   public JniCatalog(boolean loadInBackground, int numMetadataLoadingThreads,
-      String sentryServiceConfig, int impalaLogLevel, int otherLogLevel)
-      throws InternalException {
+      String sentryServiceConfig, int impalaLogLevel, int otherLogLevel,
+      boolean allowAuthToLocal) throws InternalException {
+    BackendConfig.setAuthToLocal(allowAuthToLocal);
     Preconditions.checkArgument(numMetadataLoadingThreads > 0);
     // This trick saves having to pass a TLogLevel enum, which is an object and more
     // complex to pass through JNI.

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/service/JniFrontend.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/service/JniFrontend.java b/fe/src/main/java/com/cloudera/impala/service/JniFrontend.java
index cacefc0..b5fcbf3 100644
--- a/fe/src/main/java/com/cloudera/impala/service/JniFrontend.java
+++ b/fe/src/main/java/com/cloudera/impala/service/JniFrontend.java
@@ -49,6 +49,7 @@ import com.cloudera.impala.common.FileSystemUtil;
 import com.cloudera.impala.common.ImpalaException;
 import com.cloudera.impala.common.InternalException;
 import com.cloudera.impala.common.JniUtil;
+import com.cloudera.impala.service.BackendConfig;
 import com.cloudera.impala.thrift.TCatalogObject;
 import com.cloudera.impala.thrift.TDatabase;
 import com.cloudera.impala.thrift.TDescribeDbParams;
@@ -108,7 +109,8 @@ public class JniFrontend {
    */
   public JniFrontend(boolean lazy, String serverName, String authorizationPolicyFile,
       String sentryConfigFile, String authPolicyProviderClass, int impalaLogLevel,
-      int otherLogLevel) throws InternalException {
+      int otherLogLevel, boolean allowAuthToLocal) throws InternalException {
+    BackendConfig.setAuthToLocal(allowAuthToLocal);
     GlogAppender.Install(TLogLevel.values()[impalaLogLevel],
         TLogLevel.values()[otherLogLevel]);
 

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/main/java/com/cloudera/impala/util/RequestPoolService.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/com/cloudera/impala/util/RequestPoolService.java b/fe/src/main/java/com/cloudera/impala/util/RequestPoolService.java
index e41db76..5e5e0c2 100644
--- a/fe/src/main/java/com/cloudera/impala/util/RequestPoolService.java
+++ b/fe/src/main/java/com/cloudera/impala/util/RequestPoolService.java
@@ -283,7 +283,7 @@ public class RequestPoolService {
 
   @VisibleForTesting
   TResolveRequestPoolResult resolveRequestPool(
-      TResolveRequestPoolParams resolvePoolParams) {
+      TResolveRequestPoolParams resolvePoolParams) throws InternalException {
     String requestedPool = resolvePoolParams.getRequested_pool();
     String user = resolvePoolParams.getUser();
     TResolveRequestPoolResult result = new TResolveRequestPoolResult();
@@ -410,7 +410,7 @@ public class RequestPoolService {
    */
   @VisibleForTesting
   String assignToPool(String requestedPool, String user)
-      throws IOException {
+      throws InternalException, IOException {
     Preconditions.checkState(running_.get());
     Preconditions.checkNotNull(requestedPool);
     Preconditions.checkArgument(!Strings.isNullOrEmpty(user));
@@ -432,14 +432,16 @@ public class RequestPoolService {
    * @return True if the user has access to the pool.
    */
   @VisibleForTesting
-  boolean hasAccess(String pool, String user) {
+  boolean hasAccess(String pool, String user) throws InternalException {
     Preconditions.checkState(running_.get());
     Preconditions.checkArgument(!Strings.isNullOrEmpty(pool));
     Preconditions.checkArgument(!Strings.isNullOrEmpty(user));
     // Convert the user name to a short name (e.g. 'user1@domain' to 'user1') because
     // the UserGroupInformation will check group membership which should always be done
     // on the short name of the principal.
-    String shortName = new User(user).getShortName();
+    String shortName;
+    User requestingUser = new User(user);
+    shortName = requestingUser.getShortName();
     UserGroupInformation ugi = UserGroupInformation.createRemoteUser(shortName);
     return allocationConf_.get().hasAccess(pool, QueueACL.SUBMIT_APPLICATIONS, ugi);
   }

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/test/java/com/cloudera/impala/analysis/AuditingTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/com/cloudera/impala/analysis/AuditingTest.java b/fe/src/test/java/com/cloudera/impala/analysis/AuditingTest.java
index 4258994..6b3c426 100644
--- a/fe/src/test/java/com/cloudera/impala/analysis/AuditingTest.java
+++ b/fe/src/test/java/com/cloudera/impala/analysis/AuditingTest.java
@@ -24,6 +24,7 @@ import com.cloudera.impala.catalog.AuthorizationException;
 import com.cloudera.impala.catalog.Catalog;
 import com.cloudera.impala.catalog.ImpaladCatalog;
 import com.cloudera.impala.common.AnalysisException;
+import com.cloudera.impala.common.InternalException;
 import com.cloudera.impala.service.Frontend;
 import com.cloudera.impala.testutil.ImpaladTestCatalog;
 import com.cloudera.impala.testutil.TestUtils;
@@ -327,7 +328,7 @@ public class AuditingTest extends AnalyzerTest {
 
   @Test
   public void TestAccessEventsOnAuthFailure() throws AuthorizationException,
-      AnalysisException {
+      AnalysisException, InternalException {
     // The policy file doesn't exist so all operations will result in
     // an AuthorizationError
     AuthorizationConfig config = AuthorizationConfig.createHadoopGroupAuthConfig(

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/test/java/com/cloudera/impala/analysis/AuthorizationTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/com/cloudera/impala/analysis/AuthorizationTest.java b/fe/src/test/java/com/cloudera/impala/analysis/AuthorizationTest.java
index 499fdf7..b82d5d4 100644
--- a/fe/src/test/java/com/cloudera/impala/analysis/AuthorizationTest.java
+++ b/fe/src/test/java/com/cloudera/impala/analysis/AuthorizationTest.java
@@ -21,15 +21,20 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
+import org.apache.hadoop.conf.Configuration;
+import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTH_TO_LOCAL;
 import org.apache.hive.service.cli.thrift.TGetColumnsReq;
 import org.apache.hive.service.cli.thrift.TGetSchemasReq;
 import org.apache.hive.service.cli.thrift.TGetTablesReq;
 import org.apache.sentry.provider.common.ResourceAuthorizationProvider;
 import org.apache.sentry.provider.file.LocalGroupResourceAuthorizationProvider;
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Assert;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -49,6 +54,7 @@ import com.cloudera.impala.catalog.Type;
 import com.cloudera.impala.common.AnalysisException;
 import com.cloudera.impala.common.ImpalaException;
 import com.cloudera.impala.common.InternalException;
+import com.cloudera.impala.common.RuntimeEnv;
 import com.cloudera.impala.service.Frontend;
 import com.cloudera.impala.testutil.ImpaladTestCatalog;
 import com.cloudera.impala.testutil.TestUtils;
@@ -65,6 +71,7 @@ import com.cloudera.impala.thrift.TSessionState;
 import com.cloudera.impala.util.SentryPolicyService;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 @RunWith(Parameterized.class)
 public class AuthorizationTest {
@@ -155,6 +162,16 @@ public class AuthorizationTest {
     testCtxs_.add(new TestContext(sentryServiceAuthzConfig, sentryServiceCatalog));
   }
 
+  @BeforeClass
+  public static void setUp() throws Exception {
+    RuntimeEnv.INSTANCE.setTestEnv(true);
+  }
+
+  @AfterClass
+  public static void cleanUp() {
+    RuntimeEnv.INSTANCE.reset();
+  }
+
   public AuthorizationTest(TestContext ctx) throws Exception {
     ctx_ = ctx;
     queryCtx_ = TestUtils.createQueryContext(Catalog.DEFAULT_DB, USER.getName());
@@ -421,7 +438,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestSelect() throws AuthorizationException, AnalysisException {
+  public void TestSelect() throws ImpalaException {
     // Can select from table that user has privileges on.
     AuthzOk("select * from functional.alltypesagg");
 
@@ -535,7 +552,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestUnion() throws AuthorizationException, AnalysisException {
+  public void TestUnion() throws ImpalaException {
     AuthzOk("select * from functional.alltypesagg union all " +
         "select * from functional.alltypesagg");
 
@@ -553,7 +570,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestInsert() throws AuthorizationException, AnalysisException {
+  public void TestInsert() throws ImpalaException {
     AuthzOk("insert into functional_parquet.alltypes " +
         "partition(month,year) select * from functional_seq_snap.alltypes");
 
@@ -613,7 +630,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestWithClause() throws AuthorizationException, AnalysisException {
+  public void TestWithClause() throws ImpalaException {
     // User has SELECT privileges on table in WITH-clause view.
     AuthzOk("with t as (select * from functional.alltypesagg) select * from t");
     // User doesn't have SELECT privileges on table in WITH-clause view.
@@ -648,7 +665,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestExplain() throws AuthorizationException, AnalysisException {
+  public void TestExplain() throws ImpalaException {
     AuthzOk("explain select * from functional.alltypesagg");
     AuthzOk("explain insert into functional_parquet.alltypes " +
         "partition(month,year) select * from functional_seq_snap.alltypes");
@@ -727,7 +744,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestUseDb() throws AnalysisException, AuthorizationException {
+  public void TestUseDb() throws ImpalaException {
     // Positive cases (user has privileges on these tables).
     AuthzOk("use functional");
     AuthzOk("use tpcds");
@@ -804,7 +821,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestCreateTable() throws AnalysisException, AuthorizationException {
+  public void TestCreateTable() throws ImpalaException {
     AuthzOk("create table tpch.new_table (i int)");
     AuthzOk("create table tpch.new_lineitem like tpch.lineitem");
     // Create table IF NOT EXISTS, user has permission and table exists.
@@ -903,7 +920,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestCreateView() throws AuthorizationException, AnalysisException {
+  public void TestCreateView() throws ImpalaException {
     AuthzOk("create view tpch.new_view as select * from functional.alltypesagg");
     AuthzOk("create view tpch.new_view (a, b, c) as " +
         "select int_col, string_col, timestamp_col from functional.alltypesagg");
@@ -1003,7 +1020,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestDropDatabase() throws AnalysisException, AuthorizationException {
+  public void TestDropDatabase() throws ImpalaException {
     // User has permissions.
     AuthzOk("drop database tpch");
     AuthzOk("drop database tpch cascade");
@@ -1057,7 +1074,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestDropTable() throws AnalysisException, AuthorizationException {
+  public void TestDropTable() throws ImpalaException {
     // Drop table (user has permission).
     AuthzOk("drop table tpch.lineitem");
     AuthzOk("drop table if exists tpch.lineitem");
@@ -1093,7 +1110,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestDropView() throws AnalysisException, AuthorizationException {
+  public void TestDropView() throws ImpalaException {
     // Drop view (user has permission).
     AuthzOk("drop view functional_seq_snap.alltypes_view");
     AuthzOk("drop view if exists functional_seq_snap.alltypes_view");
@@ -1126,7 +1143,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestTruncate() throws AuthorizationException, AnalysisException {
+  public void TestTruncate() throws ImpalaException {
     AuthzOk("truncate table functional_parquet.alltypes");
 
     // User doesn't have INSERT permissions in the target table.
@@ -1147,7 +1164,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestAlterTable() throws AnalysisException, AuthorizationException {
+  public void TestAlterTable() throws ImpalaException {
     // User has permissions to modify tables.
     AuthzOk("ALTER TABLE functional_seq_snap.alltypes ADD COLUMNS (c1 int)");
     AuthzOk("ALTER TABLE functional_seq_snap.alltypes REPLACE COLUMNS (c1 int)");
@@ -1274,7 +1291,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestAlterView() throws AnalysisException, AuthorizationException {
+  public void TestAlterView() throws ImpalaException {
     AuthzOk("ALTER VIEW functional_seq_snap.alltypes_view rename to " +
         "functional_seq_snap.v1");
 
@@ -1330,7 +1347,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestComputeStatsTable() throws AnalysisException, AuthorizationException {
+  public void TestComputeStatsTable() throws ImpalaException {
     AuthzOk("compute stats functional_seq_snap.alltypes");
 
     AuthzError("compute stats functional.alltypes",
@@ -1344,7 +1361,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestDropStats() throws AnalysisException, AuthorizationException {
+  public void TestDropStats() throws ImpalaException {
     AuthzOk("drop stats functional_seq_snap.alltypes");
 
     AuthzError("drop stats functional.alltypes",
@@ -1358,7 +1375,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestDescribeDb() throws AuthorizationException, AnalysisException {
+  public void TestDescribeDb() throws ImpalaException {
     AuthzOk("describe database functional_seq_snap");
 
     // Database doesn't exist.
@@ -1370,7 +1387,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestDescribe() throws AuthorizationException, AnalysisException {
+  public void TestDescribe() throws ImpalaException {
     AuthzOk("describe functional.alltypesagg");
     AuthzOk("describe functional.alltypes");
     AuthzOk("describe functional.complex_view");
@@ -1406,7 +1423,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestLoad() throws AuthorizationException, AnalysisException {
+  public void TestLoad() throws ImpalaException {
     // User has permission on table and URI.
     AuthzOk("load data inpath 'hdfs://localhost:20500/test-warehouse/tpch.lineitem'" +
         " into table functional.alltypes partition(month=10, year=2009)");
@@ -1453,7 +1470,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestShowPermissions() throws AuthorizationException, AnalysisException {
+  public void TestShowPermissions() throws ImpalaException {
     AuthzOk("show tables in functional");
     AuthzOk("show databases");
     AuthzOk("show tables in _impala_builtins");
@@ -1657,11 +1674,10 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestShortUsernameUsed() throws AnalysisException,
-      AuthorizationException {
+  public void TestShortUsernameUsed() throws Exception {
     // Different long variations of the same username.
     List<User> users = Lists.newArrayList(
-        new User(USER.getName() + "/abc.host.com"),
+        new User(USER.getName() + "/abc.host.com@"),
         new User(USER.getName() + "/abc.host.com@REAL.COM"),
         new User(USER.getName() + "@REAL.COM"));
     for (User user: users) {
@@ -1677,14 +1693,84 @@ public class AuthorizationTest {
           "User '%s' does not have privileges to execute 'SELECT' on: default.alltypes",
           user);
     }
-    // If the first character is '/' or '@', the short username should be the same as
+    // If the first character is '/', the short username should be the same as
     // the full username.
     assertEquals("/" + USER.getName(), new User("/" + USER.getName()).getShortName());
-    assertEquals("@" + USER.getName(), new User("@" + USER.getName()).getShortName());
   }
 
   @Test
-  public void TestFunction() throws ImpalaException {
+  public void TestShortUsernameWithAuthToLocal() throws ImpalaException {
+    // We load the auth_to_local configs from core-site.xml in the test mode even if
+    // kerberos is disabled. We use the following configuration for tests
+    //   <property>
+    //     <name>hadoop.security.auth_to_local</name>
+    //     <value>RULE:[2:$1@$0](authtest@REALM.COM)s/(.*)@REALM.COM/auth_to_local_user/
+    //       RULE:[1:$1]
+    //       RULE:[2:$1]
+    //       DEFAULT
+    //     </value>
+    //   </property>
+    AuthorizationConfig authzConfig = new AuthorizationConfig("server1",
+        AUTHZ_POLICY_FILE, "",
+        LocalGroupResourceAuthorizationProvider.class.getName());
+    ImpaladCatalog catalog = new ImpaladTestCatalog(authzConfig);
+
+    // This test relies on the auth_to_local rule -
+    // "RULE:[2:$1@$0](authtest@REALM.COM)s/(.*)@REALM.COM/auth_to_local_user/"
+    // which converts any principal of type authtest/<hostname>@REALM.COM to user
+    // auth_to_local_user. We have a sentry privilege in place that grants 'SELECT'
+    // privilege on tpcds.* to user auth_to_local_user. To test the integration, we try
+    // running the query with authtest/hostname@REALM.COM user which is converted to user
+    // 'auth_to_local_user' and the authz should pass.
+    User.setRulesForTesting(
+        new Configuration().get(HADOOP_SECURITY_AUTH_TO_LOCAL, "DEFAULT"));
+    User user = new User("authtest/hostname@REALM.COM");
+    AnalysisContext context = new AnalysisContext(catalog,
+        TestUtils.createQueryContext(Catalog.DEFAULT_DB, user.getName()), authzConfig);
+    Frontend fe = new Frontend(authzConfig, catalog);
+
+    // Can select from table that user has privileges on.
+    AuthzOk(fe, context, "select * from tpcds.customer");
+    // Does not have privileges to execute a query
+    AuthzError(fe, context, "select * from functional.alltypes",
+        "User '%s' does not have privileges to execute 'SELECT' on: functional.alltypes",
+        user);
+
+    // Unit tests for User#getShortName()
+    // Different auth_to_local rules to apply on the username.
+    List<String> rules = Lists.newArrayList(
+        // Expects user@REALM and returns 'usera' (appends a in the end)
+        "RULE:[1:$1@$0](.*@REALM.COM)s/(.*)@REALM.COM/$1a/g",
+        // Same as above but expects user/host@REALM
+        "RULE:[2:$1@$0](.*@REALM.COM)s/(.*)@REALM.COM/$1a/g");
+
+    // Map from the user to the expected getShortName() output after applying
+    // the corresponding rule from 'rules' list.
+    List<Map.Entry<User, String>> users = Lists.newArrayList(
+        Maps.immutableEntry(new User(USER.getName() + "@REALM.COM"), USER.getName()
+            + "a"),
+        Maps.immutableEntry(new User(USER.getName() + "/abc.host.com@REALM.COM"),
+            USER.getName() + "a"));
+
+    for (int idx = 0; idx < users.size(); ++idx) {
+      Map.Entry<User, String> userObj = users.get(idx);
+      assertEquals(userObj.getKey().getShortNameForTesting(rules.get(idx)),
+          userObj.getValue());
+    }
+
+    // Test malformed rules. RuleParser throws an IllegalArgumentException.
+    String malformedRule = "{((()";
+    try {
+      user.getShortNameForTesting(malformedRule);
+    } catch (IllegalArgumentException e) {
+      Assert.assertTrue(e.getMessage().contains("Invalid rule"));
+      return;
+    }
+    Assert.fail("No exception caught while using getShortName() on a malformed rule");
+  }
+
+  @Test
+  public void TestFunction() throws Exception {
     // First try with the less privileged user.
     User currentUser = USER;
     AnalysisContext context = new AnalysisContext(ctx_.catalog,
@@ -1771,7 +1857,8 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestServerNameAuthorized() throws AnalysisException {
+  public void TestServerNameAuthorized()
+      throws AnalysisException, InternalException {
     if (ctx_.authzConfig.isFileBasedPolicy()) {
       // Authorization config that has a different server name from policy file.
       TestWithIncorrectConfig(AuthorizationConfig.createHadoopGroupAuthConfig(
@@ -1781,7 +1868,8 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestNoPermissionsWhenPolicyFileDoesNotExist() throws AnalysisException {
+  public void TestNoPermissionsWhenPolicyFileDoesNotExist()
+      throws AnalysisException, InternalException {
     // Test doesn't make sense except for file based policies.
     if (!ctx_.authzConfig.isFileBasedPolicy()) return;
 
@@ -1894,8 +1982,7 @@ public class AuthorizationTest {
   }
 
   @Test
-  public void TestLocalGroupPolicyProvider() throws AnalysisException,
-      AuthorizationException {
+  public void TestLocalGroupPolicyProvider() throws ImpalaException {
     if (!ctx_.authzConfig.isFileBasedPolicy()) return;
     // Use an authorization configuration that uses the
     // LocalGroupResourceAuthorizationProvider.
@@ -1930,7 +2017,7 @@ public class AuthorizationTest {
   }
 
   private void TestWithIncorrectConfig(AuthorizationConfig authzConfig, User user)
-      throws AnalysisException {
+      throws AnalysisException, InternalException {
     Frontend fe = new Frontend(authzConfig, ctx_.catalog);
     AnalysisContext ac = new AnalysisContext(new ImpaladTestCatalog(),
         TestUtils.createQueryContext(Catalog.DEFAULT_DB, user.getName()), authzConfig);
@@ -1947,18 +2034,16 @@ public class AuthorizationTest {
         "User '%s' does not have privileges to access: functional.*", user);
   }
 
-  private void AuthzOk(String stmt) throws AuthorizationException,
-      AnalysisException {
+  private void AuthzOk(String stmt) throws ImpalaException {
     AuthzOk(analysisContext_, stmt);
   }
 
-  private void AuthzOk(AnalysisContext context, String stmt)
-      throws AuthorizationException, AnalysisException {
+  private void AuthzOk(AnalysisContext context, String stmt) throws ImpalaException {
     AuthzOk(fe_, context, stmt);
   }
 
   private static void AuthzOk(Frontend fe, AnalysisContext context, String stmt)
-      throws AuthorizationException, AnalysisException {
+      throws ImpalaException {
     context.analyze(stmt);
     context.authorize(fe.getAuthzChecker());
   }
@@ -1968,17 +2053,19 @@ public class AuthorizationTest {
    * string matches.
    */
   private void AuthzError(String stmt, String expectedErrorString)
-      throws AnalysisException {
+      throws AnalysisException, InternalException {
     AuthzError(analysisContext_, stmt, expectedErrorString, USER);
   }
 
   private void AuthzError(AnalysisContext analysisContext,
-      String stmt, String expectedErrorString, User user) throws AnalysisException {
+      String stmt, String expectedErrorString, User user)
+      throws AnalysisException, InternalException {
     AuthzError(fe_, analysisContext, stmt, expectedErrorString, user);
   }
 
   private static void AuthzError(Frontend fe, AnalysisContext analysisContext,
-      String stmt, String expectedErrorString, User user) throws AnalysisException {
+      String stmt, String expectedErrorString, User user)
+      throws AnalysisException, InternalException {
     Preconditions.checkNotNull(expectedErrorString);
     try {
       try {

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/test/java/com/cloudera/impala/util/TestRequestPoolService.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/com/cloudera/impala/util/TestRequestPoolService.java b/fe/src/test/java/com/cloudera/impala/util/TestRequestPoolService.java
index 34255bd..c40ca0f 100644
--- a/fe/src/test/java/com/cloudera/impala/util/TestRequestPoolService.java
+++ b/fe/src/test/java/com/cloudera/impala/util/TestRequestPoolService.java
@@ -27,6 +27,7 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
 import com.cloudera.impala.common.ByteUnits;
+import com.cloudera.impala.common.InternalException;
 import com.cloudera.impala.thrift.TErrorCode;
 import com.cloudera.impala.thrift.TPoolConfig;
 import com.cloudera.impala.thrift.TResolveRequestPoolParams;
@@ -233,7 +234,8 @@ public class TestRequestPoolService {
     checkPoolConfigResult("root.queueC", -1, 200, 128 * ByteUnits.MEGABYTE);
   }
 
-  private void checkModifiedConfigResults() throws IOException {
+  private void checkModifiedConfigResults()
+      throws InternalException, IOException {
     // Test pool resolution: now there's a queueC
     Assert.assertEquals("root.queueA", poolService_.assignToPool("queueA", "userA"));
     Assert.assertNull(poolService_.assignToPool("queueX", "userA"));

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/fe/src/test/resources/authz-policy.ini.template
----------------------------------------------------------------------
diff --git a/fe/src/test/resources/authz-policy.ini.template b/fe/src/test/resources/authz-policy.ini.template
index e07cad5..4c11bc4 100644
--- a/fe/src/test/resources/authz-policy.ini.template
+++ b/fe/src/test/resources/authz-policy.ini.template
@@ -8,6 +8,7 @@ ${USER} = all_tpch, all_newdb, all_functional_seq_snap, select_tpcds,\
           select_functional_complex_view, select_functional_view_view,\
           insert_parquet, new_table_uri, tpch_data_uri, select_column_level_functional,\
           upper_case_uri
+auth_to_local_group = test_role
 server_admin = all_server
 
 # The [roles] section defines privileges for objects in the authorizeable hierarchy.
@@ -20,6 +21,7 @@ all_tpch = server=server1->db=tpch
 all_newdb = server=server1->db=newdb
 all_functional_seq_snap = server=server1->db=functional_seq_snap
 select_tpcds = server=server1->db=tpcds->table=*->action=select
+test_role = server=server1->db=tpcds->table=*->action=select
 select_functional_alltypesagg =\
     server=server1->db=functional->table=alltypesagg->action=select
 insert_functional_alltypes = server=server1->db=functional->table=alltypes->action=insert
@@ -59,4 +61,5 @@ upper_case_uri = server=server1->uri=hdfs://localhost:20500/test-warehouse/UPPER
 # HadoopGroupResourcePolicyProvider.
 [users]
 test_user = ${USER}
+auth_to_local_user = auth_to_local_group
 admin_user = server_admin

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3092c966/testdata/cluster/node_templates/common/etc/hadoop/conf/core-site.xml.tmpl
----------------------------------------------------------------------
diff --git a/testdata/cluster/node_templates/common/etc/hadoop/conf/core-site.xml.tmpl b/testdata/cluster/node_templates/common/etc/hadoop/conf/core-site.xml.tmpl
index 4f858f1..ab86878 100644
--- a/testdata/cluster/node_templates/common/etc/hadoop/conf/core-site.xml.tmpl
+++ b/testdata/cluster/node_templates/common/etc/hadoop/conf/core-site.xml.tmpl
@@ -35,6 +35,16 @@
   </property>
 
   <property>
+  <!-- AuthorizationTest depends on auth_to_local configs. These tests are run
+       irrespective of whether kerberos is enabled. -->
+    <name>hadoop.security.auth_to_local</name>
+    <value>RULE:[2:$1@$0](authtest@REALM.COM)s/(.*)@REALM.COM/auth_to_local_user/
+RULE:[1:$1]
+RULE:[2:$1]
+DEFAULT</value>
+  </property>
+
+  <property>
     <name>hadoop.proxyuser.${USER}.groups</name>
     <value>*</value>
   </property>
@@ -104,6 +114,7 @@
     <name>hadoop.proxyuser.llama.groups</name>
     <value>*</value>
   </property>
+
   <!-- END Kerberos settings -->
 
 </configuration>